I have a sizable model (~5000 lines) written in C. It is a serial program, with no random number generation anywhere. It makes use of the FFTW library for functions using FFT - I do not know the details of the FFTW implementation , but I assume the functions therein are deterministic also (correct me if I'm in err).
The issue I cannot understand is that I am getting small differences in the results for identical runs on the same machine (same compiler, same libraries).
I use double-precision variables, and to output the result in variable value
for example, I issue:
fprintf(outFID, "%.15e\n", value);
or
fwrite(&value, 1, sizeof(double), outFID);
And I would constantly get differences such as:
2.078434696522064e-16 vs. 2.078434696522063e-16
I have spent much time trying to figure out why this is. I initially thought one of my memory chips have gone bad, and I've ordered and replaced them, to no avail. I subsequently also tried running my code on a colleague's Linux machine, and I get differences of the same nature.
What could be causing this? It is a small issue now, but I wonder if it is the "tip of the iceberg" (of a serious problem).
I thought I would post here instead of StackOverflow in case someone working with numerical models might have come across this issue. If anyone can shed light on this, I'd be much obliged.
Followup to comments:
Christian Clason and Vikram: first, thank you for your attention to my question. The articles you linked to suggest that: 1. rounding errors limits the accuracy, and 2. different code (such as introducing seemingly harmless print statements) can affect the results up to the machine epsilon. I should clarify that I am not comparing the effects fwrite
and fprintf
functions. I am using one OR the other. In particular, the same executable is used for both runs. I am simply stating the issue occurs whether I use fprintf
OR fwrite
.
So the code path (and executable) is the same, and the hardware is the same. With all these external factors held constant, where does the randomness come from, fundamentally? I suspected the bit flip happened due to faulty memory not retaining a bit correctly, which is why I replaced the memory chips, but that doesn't seem to be the issue here, I verified and you indicated. My program outputs thousands of these double precision numbers in a single run, and there are always a random handful that have random bit flips.
Followup to Christian Clason's first comment: Why is $2\cdot 10^{-16}$ the same as 0 within machine precision? The smallest positive number for a double is 2.22e-308, so shouldn't that be equal to 0? My program outputs thousands of values in the 10^-16 range (ranging from 1e-15 to 8e-17) and we've been seeing meaningful variations in our research project, so I'm hope we've not been looking at nonsensical numbers.
Followup #2:
This is a plot of the time series output by the model, to aid in the offshoot discussion in the comments.