У меня есть несколько функций, которые необходимо применять последовательно к матрице некоторых структур. Для одного потока я использую следующий код:OpenMP с вложенными циклами
for(int t = 0; t < maxT; ++t)
{
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function1(i, j);
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function2(i, j);
}
Теперь я пытаюсь распараллелить этот код:
#pragma omp parallel
{
for(int t = 0; t < maxT; ++t)
{
#pragma omp single
function3(); // call this function once (once for each iteration of t)
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function1(i, j);
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function2(i, j);
}
}
это правильно? Работает ли это способом повторного использования потоков (не создавая новую команду нитей в основном цикле)?
Обновление: Явный барьер действительно не нужен.
На самом деле кажется, что я был смущен, когда задал этот вопрос - пример кода работает правильно. Теперь возникает вопрос: можно ли вызывать функцию (прокомментированную строку в коде) после #pragma omp parrallel (не вызывать функцию3 в каждом потоке на каждой итерации). Существует #pragma omp atomic для вызова операторов инкремента и некоторых других, но если я хочу вызвать один экземпляр произвольной функции (или, как правило, выполнить блок кода)?
Комментарий Марка. Я предполагаю, что буду обрабатывать расы данных в своих параллельных функциях. Единственный вопрос здесь: контейнеры stl не просто потокобезопасны при использовании OpenMP? то есть, если я хочу push_back() в std :: list из нескольких потоков, мне все равно нужно заблокировать этот список вручную.
Обновление 2: Я обнаружил, что для запуска одиночного действия в параллельном разделе необходимо использовать #pragma omp single. Итак, этот вопрос закрыт.
* Правильно? * Возможно. Возможно, нет. Похоже, что ваши функции действуют через побочные эффекты. Эти побочные эффекты могут реализовывать расы данных ... –