I have some serial code:
double* a = malloc((1000000) * sizeof(double));
double* b = malloc((1000000) * sizeof(double));
double totalA = 0;
for (int i = 0; i < 1000000; i++) {
if (i == 0) {
a[i] = sin(i);
}
b[i] = sin(i+1);
if (i < 1000000-1) {
a[i+1] = b[i];
}
totalA += a[i];
}
The output of totalA after this serial loop is 0.232883978073.
I then have an OpenMP version of this (note: all variables are re-initialised):
double* a = malloc((1000000) * sizeof(double));
double* b = malloc((1000000) * sizeof(double));
double totalA = 0;
#pragma omp parallel for reduction(+:totalA)
for (int i = 0; i < 1000000; i++) {
if (i == 0) {
a[i] = sin(i);
}
b[i] = sin(i+1);
if (i < 1000000-1) {
a[i+1] = b[i];
}
totalA += a[i];
}
However, the output of totalA from this code is -0.733714826779.
I can't figure out for the life of me why it is different.
Thanks.
UPDATE
After some more playing around it seems that the if statements within the loop are ignored oddly. The actual statements within the if blocks are executed on all iterations of the loop (as if the if clause doesn't exist).
For example, changing the if block to:
if (i < 555555) {
a[i+1] = b[i];
}
seems to make absolutely no difference.
I am still none the wiser as to what is going on here.
Your code contains a race condition. The conflicting statements are the assignment
a[i+1] = b[i];that writes to the arrayaand the statementtotalA += a[i];that reads froma.In your code there is no guarantee that the iteration that is responsible for writing to a particular location in the array is executed before the iteration that reads from that location.
To further demonstrate the issue, ordering the loop segment that contains the conflicting statements resolves the problem (but is most likely devastating for your performance):
It is probably better to avoid the problem altogether and rewrite your program to get rid of the loop-carried dependency:
Finally, note that, as
sin(0) ≈ 0.0, the statementscan simply be replaced by