openmp reduction 不提供与顺序方法相同的答案

openmp reduction does not provide the same answer as the sequential methodd

我正在尝试使用 OpenMP 并行化矢量点积程序。下面的代码显示了我所做的。

#define N 1000000

float dotProduct = 0;
float vector1Host[N], vector2Host[N]; //each element in the vectors are initialized to a value between 1 and 2

#pragma omp parallel for private(i)  reduction(+:dotProduct)
        for (i = 0; i < N; i++)
                dotProduct += vector1Host[i] * vector2Host[i];

我在这里得到的答案与我按顺序进行乘法时得到的答案略有不同。此外,当我删除 reduction(+:dotProduct) 并分别计算每个项目的乘法并稍后(按顺序)将它们加在一起时,我得到与完全顺序方法相同的答案。

float productComponents[N];

#pragma omp parallel for private(i)
     for (i = 0; i < N; i++)
            productComponents[i] += vector1Host[i] * vector2Host[i];

for (i=0; i<N; i++)
     dotProduct += productComponents[i];

此方法的问题在于性能。请帮助我找出第一种方法中的错误,或性能良好的替代方法。

更新: 我添加了示例 运行.

的输出

N=1000000: Ans=2251335.750000: 时间(ms)=2.59163 //顺序
N=1000000: Ans=2251356.750000: 时间(ms)=0.65846 //openmp

浮点运算不可交换。因此,根据将浮点数添加到累积变量的顺序,您的代码可能会给出不同且可能无法预测的结果。

由于代码并行化的性质,Openmp 导致以任意顺序执行加法,因此由于浮点数的上述非交换行为,导致值略微不可预测。

要么你需要接受这种不可预测性,要么将这些添加序列化。

另一种选择是使用能够保证交换加法的定点库,在这种情况下,无论加法的结果顺序如何,答案都是可预测的。