OpenMP and #pragma omp atomic

2019-04-29 06:41发布

问题:

I have an issue with OpenMP. MSVS compilator throws me "pragma omp atomic has improper form". I don't have any idea why. Code: (program appoints PI number using integrals method)

#include <stdio.h>
#include <time.h>
#include <omp.h>

long long num_steps = 1000000000;
double step;

int main(int argc, char* argv[])
{
    clock_t start, stop;
    double x, pi, sum=0.0;
    int i;
    step = 1./(double)num_steps;
    start = clock();

    #pragma omp parallel for
    for (i=0; i<num_steps; i++)
    { 
        x = (i + .5)*step;
        #pragma omp atomic //this part contains error
        sum = sum + 4.0/(1.+ x*x);  
    }

    pi = sum*step;
    stop = clock();

    // some printf to show results
return 0;
}

回答1:

Your program is a perfectly syntactically correct OpenMP code by the current OpenMP standards (e.g. it compiles unmodified with GCC 4.7.1), except that x should be declared private (which is not a syntactic but rather a semantic error). Unfortunately Microsoft Visual C++ implements a very old OpenMP specification (2.0 from March 2002) which only allows the following statements as acceptable in an atomic construct:

x binop= expr
x++
++x
x--
--x

Later versions included x = x binop expr, but MSVC is forever stuck at OpenMP version 2.0 even in VS2012. Just for comparison, the current OpenMP version is 3.1 and we expect 4.0 to come up in the following months.

In OpenMP 2.0 your statement should read:

#pragma omp atomic
sum += 4.0/(1.+ x*x);

But as already noticed, it would be better (and generally faster) to use reduction:

#pragma omp parallel for private(x) reduction(+:sum)
for (i=0; i<num_steps; i++)
{ 
    x = (i + .5)*step;
    sum = sum + 4.0/(1.+ x*x);  
}

(you could also write sum += 4.0/(1.+ x*x);)



回答2:

Try to change sum = sum + 4.0/(1.+ x*x) to sum += 4.0/(1.+ x*x).But I am affraid this won't work too. You can try to split the work like this:

    x = (i + .5)*step;
    double xx = 4.0/(1.+ x*x);
    #pragma omp atomic //this part contains error
    sum += xx;

this should work,but I am not sure whether it fits your needs.



回答3:

Replace :

#pragma omp atomic

by #pragma omp reduction(+:sum) or #pragma omp critical

But I guess #pragma omp reduction will be a better option as you have sum+=Var;

Do like this:

x = (i + .5)*step;
double z = 4.0/(1.+ x*x);
#pragma omp reduction(+:sum)
sum += z;


回答4:

You probably need a recap about #pragma more than the real solution to your problem.

#pragma are a set of non-standard, compiler specific, and most of the time, platform/system specific - meaning that the behaviour can be different on different machines with the same OS or simply on machines with different setups - set of instrunctions for the pre-processor.

As consequence any issue with pragma can be solved only if you look at the official documentation for your compiler for your platform of choice, here are 2 links.

  • http://msdn.microsoft.com/en-us/library/d9x1s805.aspx
  • http://msdn.microsoft.com/en-us/library/0ykxx45t.aspx

For the standard C/C++ #pragma doesn't exist.