OpenMP - nowait、reduction子句

nowait

nowait是OpenMP中用于指示编译器在并行执行完指定代码块后不需要隐式等待的指令。通常情况下,当并行区域的代码执行完毕后,OpenMP 会隐式地等待所有线程都执行完毕,然后再继续执行下面的代码。但是,如果在并行区域的结尾使用了nowait指令,则编译器会立即执行下面的代码,而不等待所有线程都完成。它通常与并行构造(如parallel forsections等)一起使用

#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变量中。

 
posted @ 2024-03-12 16:09  酥炸小黄瓜  阅读(151)  评论(0编辑  收藏  举报