OpenMP - nowait、reduction子句
nowait
nowait
是OpenMP中用于指示编译器在并行执行完指定代码块后不需要隐式等待的指令。通常情况下,当并行区域的代码执行完毕后,OpenMP 会隐式地等待所有线程都执行完毕,然后再继续执行下面的代码。但是,如果在并行区域的结尾使用了nowait
指令,则编译器会立即执行下面的代码,而不等待所有线程都完成。它通常与并行构造(如parallel for
、sections
等)一起使用
#include <iostream>
#include <omp.h>
using namespace std;
int main(int argc, char* argv[]){
#pragma omp parallel
{
int id = omp_get_thread_num();
#pragma omp for nowait
for (int i = 0; i < 5; ++i) {
cout << "thread " << id << " -> " << i << endl;
}
cout << "nowait - > " << id << endl;
}
return 0;
}
nowait
thread thread 02 -> -> 03thread
thread 0 -> 1
1 -> 2
nowait - > 1
nowait - > 0
thread 3 -> 4
nowait - > 3
nowait - > 2
non nowait
thread thread thread 1 -> 220 -> -> 30
thread 0 -> 1
thread 3 -> 4
nowait - > nowait - > 02
nowait - > 1
nowait - > 3
reduction
reduction
是 OpenMP 中用于执行归约操作的指令。归约操作是指对多个值进行聚合计算,如求和、求积、求最大值、求最小值等。
归约操作是并行安全的,不需要显式地使用临界区或原子操作来确保结果的正确性。
reduction(op:list)
reduction中的op操作必须满足算术结合律和交换律。
使用规约操作
#include <iostream>
#include <omp.h>
using namespace std;
int main(int argc, char* argv[]){
int sum = 0;
#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < 10000; ++i) {
sum++;
}
cout << "sum = " << sum << endl;
return 0;
}
结果正确
sum = 10000
不使用规约操作
结果错误
sum = 9987
每个线程都会计算它负责迭代的那部分数组元素的总和,并将结果加到私有副本sum
上。最终,所有这些部分和会被加到全局的sum
变量中。