STL并行累加函数错误



有谁知道为什么下面的脚本给出错误的结果,而运行在超过1个线程?累加函数中使用的向量的长度是否有限制?当向量的长度大于999时给出错误的答案。

ksaha@cswarmfe:g++ -fopenmp test2.cc 
ksaha@cswarmfe:export OMP_NUM_THREADS=1
ksaha@cswarmfe:./a.out 
result 4000
Time 0.000114875
ksaha@cswarmfe:export OMP_NUM_THREADS=2
ksaha@cswarmfe:./a.out 
0.000000e+00, 1.998000e+03
3.996000e+03, 1.998000e+03
result 7992
Time 0.000231437
ksaha@cswarmfe:export OMP_NUM_THREADS=4
ksaha@cswarmfe:./a.out 
0.000000e+00, 9.980000e+02
1.996000e+03, 9.980000e+02
3.992000e+03, 9.980000e+02
5.988000e+03, 9.980000e+02
result 7984
Time 0.000265011
//============================================================
#include <vector>
#include <iostream>
#include <numeric>
#include <parallel/numeric>
namespace par = std::__parallel;

double myfunction (double x, double y) {
               if(y!=2) printf("%e, %en",x,y);
               return x+2.0*y;
               }

int main(int argc, char **argv)
{
  double t = omp_get_wtime();
  int err = 0;
  std::vector<double> vec(1000,2.0);
  for (int i=0; i<1000; i++)
  if(vec[i]!=2) std::cout << vec[i] << "+++" << std::endl;

  double init = 0.0;
  // parallel
  double result = par::accumulate(vec.begin(),vec.end(),init,myfunction);
  std::cout << "result " << result << std::endl;
  std::cout << "Time " << omp_get_wtime()-t << std::endl;
  return err;
}

为了获得一致的结果,您的myfunction需要是关联的。在串行模式下,它一次只处理一个元素,所以myfunction总是被调用,x是累积值,y是数组中的一个条目。因此,总数是所有累积值之和的2倍,即4000。

但是当并行调用时,x和y都可能是累积值,如果你的myfunction不是关联的,你会得到不同的结果,这取决于处理顺序。

例如,在你的向量中有4个元素,串行版本将得到总共16个元素,但并行版本可以按如下方式处理,得到24个元素:

0.0  2.0      0.0   2.0
    /            /
  4.0    2.0    4.0    2.0  
       /             /
      8.0           8.0
                 /
            24.0

您的二进制操作(x+2*y)不是关联的,因此结果取决于操作的顺序。

最新更新