我试图总结在同一代码中初始化的数组的所有元素。由于每个元素彼此独立,我试图并行执行求和。我的代码如下所示:
int main(int argc, char** argv)
{
cout.precision(20);
double sumre=0.,Mre[11];
int n=11;
for(int i=0; i<n; i++)
Mre[i]=2.*exp(-10*M_PI*i/(1.*n));
#pragma omp parallel for reduction(+:sumre)
for(int i=0; i<n; i++)
{
sumre+=Mre[i];
}
cout<<sumre<<"\n";
}
我编译并运行:
g++ -O3 -o sum sumparallel.cpp -fopenmp
./sum
分别。我的问题是每次运行它时输出都不同。有时会给出
2.1220129388411006488
或
2.1220129388411002047 有谁知道这里发生了什么?
答案 0 :(得分:2)
其中一些评论暗示了这里的问题,但可能存在两个不同的问题
双精度数字不具有20小数精度
如果要打印sumre
的最大精度,请使用类似
#include <float.h>
int maint(int argc, char* argv[])
{
...
printf("%.*g", DBL_DECIMAL_DIG, number);
return 0;
}
浮点算术是非交换的
此属性的效果是舍入误差。实际上,您定义的函数(高斯函数)特别容易进行求和的舍入。考虑到OpenMP parallel for
的工作负载分配未定义,您在运行它时可能会收到不同的答案。要解决此问题,您可以使用kahan summation algorithm。 OpenMP的实现看起来像这样:
...
double sum = 0.0, c = 0.0;
#pragma omp parallel for reduction(+:sum, +:c)
for(i = 0; i < n; i++)
{
double y = Mre[i] - c;
double t = sum + y;
c = (t - sum) - y;
sum = t;
}
sum = sum - c;
...