I want to write a function which employs openMP parallelism but should work whether called from within a parallel region or not. So I used the if clause to suppress parallelism, but this doesn't work as I thought:
#include <omp.h>
#include <stdio.h>
int m=0,s=0;
void func()
{
bool p = omp_in_parallel();
// if clause to suppress nested parallelism
#pragma omp parallel if(!p)
{
/* do some massive work in parallel */
#pragma omp master
++m;
#pragma omp single
++s;
}
}
int main()
{
fprintf(stderr,"running func() serial:\n");
m=s=0;
func();
fprintf(stderr," m=%d s=%d\n",m,s);
fprintf(stderr,"running func() parallel:\n");
m=s=0;
#pragma omp parallel
func();
fprintf(stderr," m=%d s=%d\n",m,s);
}
which creates the output
running func() serial:
m=1 s=1
running func() parallel:
m=16 s=16
Thus the first call to func() worked fine: m and s obtain the values 1 as they should, but the second call to func() from within a parallel region did create nested parallelism (with 16 teams of 1 thread each) even though this was suppressed. That is the omp master and omp single directives bind to the preceeding omp parallel if(!p) directive rather than to the outside parallel region.
Of course, one can fix this problem by the following code
void work()
{
/* do some massive work in parallel */
#pragma omp master
++m;
#pragma omp single
++s;
}
void func()
{
if(omp_in_parallel())
work();
else
#pragma omp parallel
work();
}
but this requires an additional function to be defined etc. Is it possible to do this within a single function (and without repeating code)?