Is the following problem a known bug What is the explanation
This code is being compiled using the C++ compiler in Visual Studio 2005 Developer Team edition.
This problem is a repost. Please respond.
-----------------------------------------------------------------
The following code uses the satement
"#pragma omp parallel for reduction(+:t)if ((loopsize-100)>OMPLIMIT)"
in order to parallelize the steps in the loop following it.
After the code calls the procedure a second time the number of threads falls which is
incorrect. A sample run of the following code will yield the following output.
Demo of OpenMP if clause issue
OMP check: pre call 1 ( thd 0 thd 1 )
OMP check: post call 1 ( thd 0 thd 1 )
OMP check: pre call 2 ( thd 0 thd 1 )
OMP check: post call 2 ( thd 0 )
-------------------------------MALFUNCTIONING CODE ---------------------------------------
// OMPIfClauseBug.cpp : Demonstrates issue with if clause in #pragma omp.
//
// Shows how if clause is basically disabling OMP to a single thread
// after second call to tryompif, omp only is working with a single thread
// thus losing all parallelism after that. tryompif contains a loop with a single if
pragma.
// showomp, called by SHOWOMP macro uses a simple parallel construct to see how many
// threads are available.
//
// falls to a single thread on both AMD Opteron 64 release mode and Win32 debug mode.
//
// uncommenting the omp_set_num_threads makes the problem go away.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include <omp.h>
#define OMPLIMIT 25000
#define SHOWOMP(msg) showomp(msg)
void showomp(char *msg);
void fillarrays(int n,double *a,double *b,double *c,double *d,double *e);
void tryompif(int n,double *a,double *b,double *c,double *d,double *e);
void main(int argc,char *argv[])
{
int n=50000;
double *a, *b, *c, *d, *e;
printf("Demo of OpenMP if clause issue\n");
#ifdef _OPENMP
// omp_set_num_threads(2);
#endif
a = (double *) malloc((n)*sizeof(double));
b = (double *) malloc((n)*sizeof(double));
c = (double *) malloc((n)*sizeof(double));
d = (double *) malloc((n)*sizeof(double));
e = (double *) malloc((n)*sizeof(double));
fillarrays(n,a,b,c,d,e);
SHOWOMP("pre call 1");
tryompif(n,a,b,c,d,e);
SHOWOMP("post call 1");
SHOWOMP("pre call 2");
tryompif(n/2,a,b,c,d,e);
SHOWOMP("post call 2");
//SHOWOMP("pre call 3");
//tryompif(n/2,b,c,a,d,e);
//SHOWOMP("post call 3");
//SHOWOMP("pre call 4");
//tryompif(n,a,b,c,d,e);
//SHOWOMP("post call 4");
return ;
}
void fillarrays(int n,double *a,double *b,double *c,double *d, double *e) {
for (int i = 0; i<n; i++) {
a = 1.0;
b = 1.0/(i%1000);
c = 3.14;
d = 0.0;
e = 0.0;
}
}
// function with single omp pragma with an if clause
void tryompif(int n,double *a,double *b,double *c,double *d, double *e) {
int i,k,diffcount=0;
int loopsize;
double t;
for (i=0;i<n;i++)
{
t=0.0;
loopsize = n;
#pragma omp parallel for reduction(+:t)if ((loopsize-100)>OMPLIMIT)
for (k=i;k<n;k++)
t+=a[k]*b+c;
d=t;
}
}
// debugging OMP issues tries to create parallel tasks and prints a line from each to show
OMP active
void showomp(char *msg) {
#ifdef _OPENMP
printf("OMP check: %s (",msg);
#pragma omp parallel
{
printf(" thd %d ", omp_get_thread_num());
}
printf(")\n");
#endif
}