I'm finding a significant error for certain input values when I use a particular offset to add values. Due to the nature of the algorithm I'm considering (not relevant to the question), I need to start a sum value with the first element of an array. I was able to extract a minimal working example, which is appended below.
Even though there are less than 50 floating point additions involved, I'm seeing error far beyond that order of magnitude of ulps, and I don't understand what I am doing wrong. See the following code snippet, along with the invocation and what my results are:
// icc -std=c++11 -O3 commutative.cpp -o commutative -lm -lcilkrts -fp-model precise -fp-model source
// echo 0x1.2a30cp+36 -0x1.04b3b6p+35 0x1.92204p+32 -0x1.b9319p+34 0x1.1a88f4p+33 -0x1.39b0f2p+35 0x1.744a68p+31 -0x1.73385p+34 0x1.6ad72ep+34 -0x1.8a076cp+34 0x1.dc6578p+34 0x1.8f075ep+35 0x1.d1bd22p+34 0x1.ff211p+30 0x1.43b8cap+36 -0x1.1efd2p+32 0x1.1e646cp+35 0x1.c91e16p+34 -0x1.b1e3eap+35 -0x1.52ce1p+32 -0x1.cf6f2cp+34 -0x1.c7007ep+35 -0x1.efe1fp+35 0x1.90143cp+34 | ./commutative
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cilk/cilk.h>
int main(int argc, char**) {
if (argc != 1) {
printf("Usage: echo 1 2 3 | commutative\n");
return 1;
}
std::vector<float> vec;
while(!feof(stdin)) {
float f;
if (scanf("%a", &f) > 0) {
vec.push_back(f);
}
}
auto sz = vec.size();
printf("size %d\n", sz);
float* arr = &vec.front();
float sum1 = arr[0];
sum1 += __sec_reduce_add(arr[1:sz-1] + arr[1:sz-1]);
float sum2 = arr[0];
for (int i = 1; i < sz; ++i) sum2 += arr[i] + arr[i];
if (sum1 != sum2) printf("ERROR! unequal sums (%f vs %f), rel. err %f\n",
sum1, sum2, (float) std::abs((sum1 - sum2) / sum2));
printf("sum1 %a\n", sum1);
printf("sum2 %a\n", sum2);
return sum1 != sum2;
}size 24 ERROR! unequal sums (-13099008.000000 vs -13139968.000000), rel. err 0.003117 sum1 -0x1.8fcp+23 sum2 -0x1.91p+23
$ icc --version icc (ICC) 15.0.2 20150121 Copyright (C) 1985-2015 Intel Corporation. All rights reserved.