single and critical are two very different things. As you mentioned:
singlespecifies that a section of code should be executed by single thread (not necessarily the master thread)criticalspecifies that code is executed by one thread at a time
So the former will be executed only once while the later will be executed as many times as there are of threads.
For example the following code
int a=0, b=0;
#pragma omp parallel num_threads(4)
{
#pragma omp single
a++;
#pragma omp critical
b++;
}
printf("single: %d -- critical: %d\n", a, b);
will print
single: 1 -- critical: 4
I hope you see the difference better now.
For the sake of completeness, I can add that:
masteris very similar tosinglewith two differences:masterwill be executed by the master only whilesinglecan be executed by whichever thread reaching the region first; andsinglehas an implicit barrier upon completion of the region, where all threads wait for synchronization, whilemasterdoesn’t have any.
atomicis very similar tocritical, but is restricted for a selection of simple operations.
I added these precisions since these two pairs of instructions are often the ones people tend to mix-up…