Here's the basic premise of my code:
while(norm_of_error > tol){
#pragma omp parallel for
for(i = 1; i <= N*N; i++){
//printf("thread id: %d\n",omp_get_thread_num());
:
int val = based on i
:
#pragma omp critical
x[i-1] = val;
}
#pragma omp barrier
iter++;
}
In short, I am solving Ax = b using the Jacobi iterative method. My problem is that, with the printf() statement uncommented, the norm_of_error tends to zero and the while loop ends. However, by simply commenting out the printf() statement, this doesn't happen. Can anyone give me a hint as to why the printf() statement has any impact? I'm guessing that the issue has to do with the call to omp_get_thread_num(), but I don't see why that would make any difference.
Edit: I changed the printf() statement to printf("hi\n"); and the code works. Comment that out, and the code doesn't work.
Code that works with a printf() statement present, but fails when it is removed, is usually a sign of some invalid operation affecting memory in the program somewhere (e.g. falling off the end of an array, dereferencing NULL, etc). The misbehaving code may be in some other section of the program entirely (e.g. not within the function that contains the printf() statement)
That is even more likely when the offending printf() statement is something obviously innocent, and without any side effects that can affect behaviour of other code (such as printf("Hi\n")).
The reason is that the presence of the extra printf() does actually affect layout of memory for the program as a whole. So the offending code (which may be in some completely unrelated part of the program) still overwrites memory, but the consequence changes (e.g. overwriting some data the program is permitted to change, rather than some area of memory that causes the operating system to terminate the program).
This is true whether or not the code is multithreaded.
Without complete code that illustrates the problem (i.e. a small sample that someone else can compile, build, and run to get the same symptom) it is not possible to be more specific.
You haven't posted your code so we can't know for sure, but this typically arises because you are trying to share data amongst threads without adequately indicating that the data is to be shared.
With the printf removed, your program is loading the data into a register, and when it needs the data again, it remembers the value in the register rather than fetching it from memory again, thus it doesn't see any changes your other threads may have made.
With the printf in place, your program doesn't hold the data in register -- maybe it can't afford to spend a register that way, or it can't determine that a function call is incapable of changing the data (sure, it's just printf, but it might not be special cased, and even if it is, the compiler is better at finding loopholes that might allow printf to change data than you are) -- so it rereads the data from memory after the call to printf, and thus sees whatever prior changes that have been made in other threads.
Another thing the printf could change is timing: I/O statements are pretty slow as compared to computation, and there is likely some amount of synchronization happening inside the I/O library; your print might be acting as a pseudo-barrier that is preventing a race condition from occurring.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With