OpenMP程序执行中的错误

时间:2016-06-10 15:31:14

标签: openmp

我试图总结在同一代码中初始化的数组的所有元素。由于每个元素彼此独立,我试图并行执行求和。我的代码如下所示:

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 有谁知道这里发生了什么?

1 个答案:

答案 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;  
  ...