STL并行累加功能错了吗?

时间:2015-09-03 20:34:00

标签: c++ multithreading

有没有人知道为什么以下脚本在多个线程上运行时会产生错误的结果?累积中使用的向量长度是否有限制?当向量的长度> 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, %e\n",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;
}

2 个答案:

答案 0 :(得分:3)

为了获得一致的结果,您的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

答案 1 :(得分:0)

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