我正在尝试使用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:时间(毫秒)= 0.65846 // openmp
答案 0 :(得分:3)
浮点运算不可交换。因此,您的代码可能会根据浮点数添加到累积变量的顺序给出不同且可能不可预测的结果。
Openmp由于代码并行化的性质导致添加以任意顺序执行,因此由于浮动的上述非交换行为而导致稍微不可预测的值。
您需要接受这种不可预测性或序列化添加内容。
另一种选择是使用能够保证可交换加法的定点库,在这种情况下,无论结果的顺序如何,答案都是可预测的。