2014-11-05 8 views
0

Я использую openmp для параллелизации моего кода. У меня есть исходный массив:Сжатие потока (или упаковка массива) с префиксом сканирования с использованием Openmp

A=[3,5,2,5,7,9,-4,6,7,-3,1,7,6,8,-1,2] 

и массив марок:

M=[1,0,1,0,0,0,1,0,0,1,1,0,0,0,1,1] 

с помощью массива M я могу сжать мой исходный массив в этом упакованном массиве:

A=[3,2,-4,-3,1,-1,2] 

я хотел для решения этой проблемы с использованием многопоточного подхода. Библиотека «Thrust» для C++ решает эту проблему, но я не могу найти аналогичные инструменты для Fortran. Есть ли библиотека, такая как «тяга» для C++, которую я могу использовать для выполнения уплотнения потока? Альтернативно, есть ли алгоритм, который я могу написать, используя fortran и openmp, чтобы решить это?

+1

Думаю, вам будет сложно написать программу OpenMP, чтобы превзойти 'A = pack (A, M == 1)'. Я думаю, что накладные расходы, связанные с тем, что несколько потоков записываются в 'A', убьет любое ускорение от распространения работы' pack'ing. Но я с нетерпением жду того, что я ошибаюсь. Как Thrust решает проблему? –

+0

Я мог бы и, возможно, должен был добавить к моему предыдущему комментарию, что я не знаю никакой библиотеки для реализации параллельной версии встроенного в Fortran 'pack'. Полагаю, вам может быть достаточно легко вызвать подпрограммы C++ из Thrust. –

+0

Если ваш вектор очень длинный, вы можете попробовать и разбить его на несколько кусков в цикле «OMP do» и использовать 'pack' для каждого подмножества. Вам нужно будет сохранить полученные подмножества самостоятельно и объединить их в конце. – damienfrancois

ответ

1

Есть библиотека, как «тяга» на C++, что я могу использовать для выполнения потока уплотнению?

Это не должно быть трудно назвать упорную рутина из Fortran (если вы готовы написать немного кода C++). Кроме того, тяга может ориентироваться на OMP-сервер, а не на GPU.

Кроме того, есть алгоритм, который я могу написать сам, используя Fortran и OpenMP, чтобы решить эту проблему?

Основной алгоритм уплотнения параллельного потока заключается в следующем. Предположим, что в вашем массиве данных имеется один поток, назначенный для каждого элемента.

  1. Выполните parallel prefix sum (inclusive scan) на M массива:

    M=[1,0,1,0,0,0,1,0,0,1,1,0,0,0,1,1] 
    sM=[1,1,2,2,2,2,3,3,3,4,5,5,5,5,6,7] 
    
  2. Каждый поток будет проверять его элемент в M массиве, и если этот элемент не равен нулю, он будет копировать его соответствующий элемент в A массива выходной массив (назовем его O):

    M=[1,0,1,0,0,0, 1,0,0, 1,1,0,0,0, 1,1] 
    sM=[1,1,2,2,2,2, 3,3,3, 4,5,5,5,5, 6,7] 
    A=[3,5,2,5,7,9,-4,6,7,-3,1,7,6,8,-1,2] 
    O=[3, 2,  -4, -3,1,  -1,2] 
    

Если вы делали это в OMP, вам понадобится барьер OMP между шагами 1 и 2. Работа на шаге 2 относительно проста и полностью независима, поэтому вы можете использовать цикл OMP parallel do и разорвать работу вверх любым способом. Шаг 1 будет сложным, и я предлагаю следовать схеме, приведенной в главе, с которой вы и я связаны. Код OMP там потребует различных барьеров на этом пути, но параллелизуется.

Как уже упоминалось в комментариях, если это только часть работы, которую вы хотите, чтобы распараллелить, я бы не рекомендовал GPU, поскольку стоимость передачи данных в/из ГПУ, вероятно, перевешивают любые которые вы можете получить. Но, как я уже упоминал, тяга может ориентироваться на реализацию OMP, а не на реализацию GPU. Возможно, стоит попробовать.

Что касается тяги от fortran, то больше всего вам нужно here. Это, по общему признанию, CUDA fortran, но единственными отличиями должны быть не использование атрибута device, а использование thrust :: host_vector вместо thrust :: device_vector (по крайней мере, для начала).

 Смежные вопросы

  • Нет связанных вопросов^_^