Using accumulate and reduce with any type of execution policy produces large error for huge number of data

Viewed 47

The result of the following code is very surprising to me. Why does using accumulate produce such a large error? I know that because it is single precisions, it will have a round-off error but when using reduce without any policy (single precision), this round-off error is not so significant! In fact, round-off errors is reasonable. But again, when I use reduce with policy (either of par seq unseq), its result will be the same with such a huge error compared to exact sum. Can anyone explain this?

#include <fstream>
#include <iomanip>
#include <execution>
#include <random>
#include <iostream>
#include <chrono>
#include <cfloat>
using namespace std;

int main() {

    const int N=100*1e6;

    default_random_engine g(time(0));
    uniform_real_distribution<float> d(0.0f,nextafter(1.0f, DBL_MAX));

    vector<float>  a;
    vector<double> b;
    double exact{0.0};
    float sum;


    for(auto i=0; i<N ;i++){
        a.push_back(d(g));

        b.push_back(static_cast<double>(a[i]));
    }

    exact=accumulate(b.begin(),b.end(),0.0);
    cout<<" exact sum is:  "<<exact<<endl;
    sum=accumulate(a.begin(),a.end(),0.0f);
    cout<<" using accumulate for float : "<<sum<<endl;
    sum=reduce(a.begin(),a.end());
    cout<<" using reduce for float : "<<sum<<endl;
    sum=reduce(execution::unseq,a.begin(),a.end());
    cout<<" using reduce with ploicy : "<<sum<<endl;

}

it's result is :

  exact sum is:  4.99979e+07
 using accumulate for float : 1.67772e+07
 using reduce for float : 5.00006e+07
 using reduce with ploicy : 1.67772e+07
0 Answers
Related