Как собрать данные для каждого потока OpenMP - PullRequest
0 голосов
/ 20 апреля 2020

Я новичок в OpenMP и пытаюсь разобраться в проблеме сбора данных из потоков. Я изучаю пример применения OpenMP по методу Монте-Карло (квадрат круга вписан в квадрат). Я понял, как работает следующий код:

unsigned pointsInside = 0;
#pragma omp parallel for num_threads(threadNum) shared(threadNum) reduction(+: pointsInside)
for (unsigned i = 0; i < threadNum; i++)  { ... }

Я прав, что изначально pointsInside является переменной, но OpenMP представляет ее как массив, а затем мантра reduction(+: pointsInside) суммирует элементы "массива" "?

Но главный вопрос - как собрать информацию непосредственно в массив или вектор? Я попытался объявить массив или вектор и предоставить указатель или адрес в OpenMP через shared и собрать информацию для каждого потока по соответствующему индексу. Но работает медленнее, чем с переменной и reduction. Такой подход с вектором или массивом нужен мне для моего текущего проекта. Большое спасибо!

UPD: Когда я сказал выше, что «он работает медленнее», я имел в виду сравнение двух реализаций метода Монте-Карло: 1) через shared и вектора / массив и 2) через скалярную переменную и reduction. Первый случай быстрее. Мое предположение и вопрос об этом ниже.

Я хотел бы перефразировать мой вопрос более четко. Я создаю вектор / массив и предоставляю его в OpenMP через shared. Я хочу собрать данные для каждого потока по соответствующему индексу в векторе / массиве. При таком подходе мне не нужна синхронизация доступа к вектору / массиву. Правда ли, что OpenMP разрешает синхронизацию по умолчанию, когда я использую shared. Если это так, то как это отключить. Или, может быть, существуют другие подходы. Если это не так, то как правильно разделить вектор / массив на параллельную часть без синхронизации доступа.

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

1 Ответ

0 голосов
/ 20 апреля 2020

Частичный ответ:

Правильно ли я понимаю, что первоначально pointsInside является переменной, но OpenMP представляет ее как массив, а затем суммы сокращения мантры (+: pointsInside) по элементам массива " «?

Я думаю, что лучше думать о pointsInside как о скаляре. Когда параллельная область запускается, среда выполнения заботится о создании отдельных скаляров, возможно, вы можете думать о них как о myPointsInside, по одному такому скаляру для каждого потока. Когда параллельная область заканчивается, время выполнения уменьшает значения всех скаляров потока на исходный скаляр pointsInside. Это как раз то, что OpenMP на самом деле делает за кулисами.

Что касается остальной части вашего вопроса:

Да, вы можете выполнять сокращения массивов - но это было добавлено только в OpenMP, для C и C ++ программы, в OpenMP 4.5 (я думаю). То, что происходит, во многом аналогично скалярному случаю. Эти вопросы и ответы предоставляют некоторую помощь - Можно ли сделать сокращение массива с помощью openmp?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...