Если вы хотите вручную распараллелить цикл, а также сокращения вы можете сделать это следующим образом:
#pragma omp parallel private(i)
{
int id = omp_get_thread_num();
int numthreads = omp_get_num_threads();
int start = id*num_steps/numthreads;
int finish = (id+1)*num_steps/numthreads;
double x;
double partial_sum = 0;
for (i=start; i<finish ; i++){
x = (i+0.5)*step;
partial_sum += + 4.0/(1.0+x*x);
}
#pragma omp atomic
sum += partial_sum;
}
Однако я не рекомендую это. Сокращения не должны выполняться с помощью атома, и вы должны просто позволить OpenMP распараллелить цикл. Первый случай - лучшее решение (но убедитесь, что вы объявляете x частным).
Редактировать: Согласно Христу, когда вы делаете x private, эти два метода почти одинаковы по скорости. Я хочу объяснить, почему использование критического в вашем втором методе вместо атомарного или разрешение OpenMP делать сокращение вряд ли повлияет на производительность в этом случае.
Есть два способа я могу думать делать сокращение:
- Суммы частичные суммы линейно с использованием атомной или критический
- Суммы частичных сумм с использованием дерева. То есть если у вас есть 8 ядер, это дает вам восемь частичных сумм, вы уменьшаете это до 4 частичных сумм, затем 2 частичные суммы, затем 1.
Первый литой имеет линейную конвергенцию в количестве сердечников. Второй случай относится к журналу количества ядер. Поэтому один из меня может подумать, что второй случай всегда лучше. Однако, только для восьми ядер, восстановление полностью доминирует за счет частичных сумм. Добавление восьми чисел с атомарным/критическим против сокращения дерева в 3 этапа будет небрежным.
Что делать, если у вас есть, например, 1024 ядра? Тогда дерево может быть уменьшено всего за 10 шагов, а линейная сумма - 1024 шага. Но постоянный член может быть намного больше для второго случая и делать частичную сумму большого массива, например. с 1 миллионом элементов, вероятно, все еще доминирует над сокращением.
Таким образом, я подозреваю, что использование атомного или даже критического для сокращения оказывает незначительное влияние на время сокращения вообще.
Как вы измеряете время? Насколько велико num_steps? Возможно, первый из них медленнее, потому что он первый. Если вы не выполняете фазу прогрева, это может быть плата за затраты на запуск OpenMP. – pburka