I'm currently learning Parallel Programming using C and OpenMP.
I wanted to write simple code where two shared values are beeing incremented by multiple threads.
Firstly I used reduction directive and it worked as it was meant to. Then I switched to using the critical directive to initiate critical section - it also worked.
Out of curiosity I've tried to merge these two solution and check the behaviour. I expected two valid, equal values.
code:
#include <stdio.h>
#include <stdlib.h>
#include "omp.h"
#define ITER 50000
int main( void )
{
int x, y;
#pragma omp parallel reduction(+:x,y)
{
#pragma omp for
for (int i = 0; i < ITER; i++ )
{
x++;
#pragma omp critical
y++;
}
}
printf("non critical = %d\ncritical = %d\n", x, y);
return 0;
}
output:
non critical = 50000
critical = 4246432
Of course output is random when it comes to 'critical' (variable y), the other behaves as expected and is always 50000.
The behaviour of x is understandable - reduction makes it private in scope of single thread. After the incrementation values from threads are summed up and passed to the non-local x.
What I don't understand is the behaviour of y. It's private just like x but it's also inside the critical section so it 'has more than one reason' to be inaccessible from other threads. Yet what, I think, happens is the race condition. Did the critical somehow made y public (shared)?
I know that this code makes no sense since it's enough to use only one of reduction / critical. I'd like just to know what's behind such behaviour.