2

So i'm working on some homework related to fixing som buggy code when i ran into an interesting problem. I don't think it was one of the indended bugs because the lecturer was confused by it as well. For the sake of the homework i found a workaround but i wonder what the 'correct' way to fix it is. The code was structured something like this:

int i; //iterator
/* some other initilization code */

# pragma omp parallel private(i)
{
/* set up threads */

# pragma omp for
for (i=0;i<N;i++){
    /* doing some stuff */
}
// for debugging:
printf("this thread's last index was %i", i);

} // end parallel

The problem is that when the code reaches the print statement, i isn't the last index but instead some random large number (same for each thread). The code inside the for loop seems to work fine, but ironically the debug print is broken (even worse in the actual code since it tried to index an array and promptly seg faulted).

What would be the proper way to do this? (either keep the index in general, or at least find out the final index of the thread)

4
  • Declare a local variable inside the parallel region, set it to the iterator in each iteration. I'm not sure about why you see your behavior. Commented Oct 4 at 13:32
  • yeah that's the workaround. it seems very bodge though, that can't be the intended way to do it, right? Commented Oct 4 at 13:36
  • 1
    The for construct implicitly privatizes i. Lastprivate has the effect of exporting the last value of the variable . Just make i lastprivate in the for construct. Regarding the ub explanation for the output I concur with @marcobonelli's answer Commented Oct 5 at 4:40
  • @Joachim cannot do that, it will conflict with the private(i) of the parallel section. Same thing happens removing the private(i) and declaring i inside the parallel region. Commented Oct 5 at 11:07

1 Answer 1

6

This is the result of undefined behavior. Even though you specify private(i), and therefore each thread in the parallel block gets its own copy, the for directive will again create separate copies shadowing the same variable name. At the end of the loop, those copies will be discarded, and the original i will be printed out. Since you do not initialize it, you will be causing undefined behavior by accessing it, which is why you see a random large value printed. It is most likely just garbage present on the thread stack at its start. If you initialize it with int i = 123456; and use firstprivate(i) (removing the undefined behavior) you will see 123456 printed by all threads.

I don't think there is a "clean" way to achieve exactly what you want, i.e. a per-thread variable that is both used in the loop with the for directive and retained after the loop. You cannot tell the for directive to avoid creating an additional implicit private copy of the loop variable. If you want to print the final index you will have to add an additional variable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.