OpenMP归约操作令人困惑

3

我正在尝试对两个数组进行简单的乘法运算,然后将每次乘法的结果相加,但是我的代码中的 reduction 让我感到困惑,以下是我的代码:

#include <omp.h>
#include <stdio.h>
#define SizeOfVector 8
#define NumberOfThreads 4
int main(){
    const int X[SizeOfVector] = {0,2,3,4,5,6,7,8};
    const int Y[SizeOfVector] = {1,2,4,8,16,32,64,128};
    int Result[SizeOfVector] = {0};
    int Sum = 0;
    unsigned short id;

    omp_set_num_threads(NumberOfThreads);

    #pragma omp parallel private(id)
    {
        id = omp_get_thread_num();

        #pragma omp for reduction(+:Sum)
        for(unsigned short i = 0; i < SizeOfVector; i++)
        {
            Result[i] = X[i] * Y[i];
            Sum = Result[i];    //Problem Here
            printf("Partial result by thread[%d]= %d\n", id, Result[i]);
        }
    }
    printf("Final result= %d\n", Sum);
    return 0;
}

事实上,如果我将 "Sum = Result [i]" 更改为 "Sum + = Result [i]",我会得到正确的结果。 为什么会这样呢? 难道不是对每个线程制作并初始化了一个局部变量Sum,然后当所有线程完成时,就总和它们吗?
这是使用Sum += Result [i]的结果:
Partial result by thread[2]= 80
Partial result by thread[2]= 192
Partial result by thread[0]= 0
Partial result by thread[0]= 4
Partial result by thread[1]= 12
Partial result by thread[1]= 32
Partial result by thread[3]= 448
Partial result by thread[3]= 1024
Final result= 1792

以下是使用Sum = Result[i]得到的结果:

Partial result by thread[2]= 80
Partial result by thread[2]= 192
Partial result by thread[0]= 0
Partial result by thread[0]= 4
Partial result by thread[3]= 448
Partial result by thread[3]= 1024
Partial result by thread[1]= 12
Partial result by thread[1]= 32
Final result= 1252
1个回答

2
每个线程在进行两次迭代后才能得出Sum的最终结果。因为你没有在每次迭代中添加到Sum中,而是赋值给它,所以最终结果将只是i是该线程上一次运行的值的Result[i]。这是最终与所有其他线程的结果相加的值。你需要使用Sum += Result[i],以便每个线程保持自己的运行Sum,直到它们重新相遇并将不同的Sum相加。

1
reduction子句仅创建一个初始化的私有副本变量,并在构造结束时将所有私有变量聚合成单个结果。它不会修改构造内部使用私有变量的方式。 - Michael Klemm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接