Ответ 1
Да, вы можете - предложение сокращения применимо ко всей параллельной области, а также к индивидуальным конструкциям обхода for
. Это позволяет, например, сокращение по сравнению с вычислениями, выполненными в разных параллельных сечениях (предпочтительный способ реструктурирования кода):
#pragma omp parallel sections private(val) reduction(+:sum)
{
#pragma omp section
{
bla bla code
sum += val;
}
#pragma omp section
{
bla bla code
sum += val;
}
}
Вы также можете использовать конструкцию OpenMP for
workharing для автоматического распределения итераций цикла между потоками в команде, а не переопределять ее с помощью разделов:
#pragma omp parallel for private(val) reduction(+:sum)
for (row = 0; row < Rows; row++)
{
bla bla code
sum += val;
}
Обратите внимание, что редукционные переменные являются частными и их промежуточные значения (т.е. значение, которое они удерживают до сокращения в конце области parallel
), являются лишь частичными и не очень полезными. Например, следующий последовательный цикл не может быть (легко?) Преобразован в параллельный с восстановлением:
for (row = 0; row < Rows; row++)
{
bla bla code
sum += val;
if (sum > threshold)
yada yada code
}
Здесь yada yada code
должен выполняться на каждой итерации, как только накопленное значение sum
прошло значение threshold
. Когда цикл выполняется параллельно, частные значения sum
могут никогда не достигнуть threshold
, даже если их сумма будет выполнена.