C++ Bug: "#pragma omp parallel for reduction ..." fails to work as advertised - please comment  
Author Message
Anzol





PostPosted: Visual C++ Language, C++ Bug: "#pragma omp parallel for reduction ..." fails to work as advertised - please comment Top

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.

-----------------------------------------------------------------

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++) {
  aIdea = 1.0;
  bIdea = 1.0/(i%1000);
  cIdea = 3.14;
  dIdea = 0.0;
  eIdea = 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]*bIdea+cIdea;
      dIdea=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
 }



Visual C++12