OpenMP and #pragma omp atomic

32,618

Solution 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);)

Solution 2

Try to change sum = sum + 4.0/( 1. + x*x ) to sum += 4.0/(1.+ x*x) , But I'm afraid this won't work either. 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.

Solution 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;
Share:
32,618
krzakov
Author by

krzakov

Java dev.

Updated on July 10, 2022

Comments

  • krzakov
    krzakov almost 2 years

    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;
    }
    
  • krzakov
    krzakov over 11 years
    Yes. I'm using MSVS, which supports openMP. Btw. I'm using standard MSVS compiler.
  • krzakov
    krzakov over 11 years
    It helps. More advanced construction than I thought before. I should read a specification.
  • krzakov
    krzakov over 11 years
    I had to change construction. '#pragma omp reduction(+:sum)' is correct.
  • NiVeR
    NiVeR over 11 years
    I suggested a solution using atomic..This is the way how it is explained in the official reference site. If the problem is solved good for you.
  • Hristo Iliev
    Hristo Iliev over 11 years
    reduction is a data-sharing clause, applicable to the parallel directive (or to the combined parallel for), not a directive on its own.
  • Hristo Iliev
    Hristo Iliev over 11 years
    Fortunately, OpenMP pragmas are very well defined in a set of standard documents and any compliant C/C++ compiler should follow exactly the same OpenMP pragma syntax.
  • Hristo Iliev
    Hristo Iliev over 11 years
    @krzakov, #pragma omp reduction(+:sum) is not correct. It is likely ignored by the compiler and you get a dangerous data race that is hidden by the numerical imprecision. reduction is a clause, it has to be applied to another OpenMP directive - the parallel for directive in your case.