OpenMP和#pragma omp atomic

时间:2012-12-24 01:07:45

标签: c++ parallel-processing openmp atomic

我遇到OpenMP问题。 MSVS编译器抛出我“pragma omp atomic有不正确的形式”。 我不知道为什么。 代码:(程序使用积分方法指定PI编号)

#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;
}

4 个答案:

答案 0 :(得分:9)

根据当前的OpenMP标准,您的程序是完全语法正确的OpenMP代码(例如,它使用GCC 4.7.1编译未经修改),但x应声明为private(这不是语法)而是一个语义错误)。遗憾的是,Microsoft Visual C ++实现了一个非常古老的OpenMP规范(2002年3月起的2.0),它只允许以下语句在atomic构造中可接受:

  

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

更高版本包括 x = x binop expr ,但即使在VS2012中,MSVC也永远停留在OpenMP 2.0版本。仅作比较,目前的OpenMP版本为3.1,我们预计在接下来的几个月内会出现4.0。

在OpenMP 2.0中,您的陈述应为:

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

但正如已经注意到的那样,使用减少会更好(并且通常更快):

#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);  
}

(你也可以写sum += 4.0/(1.+ x*x);

答案 1 :(得分:2)

尝试将sum = sum + 4.0/( 1. + x*x )更改为sum += 4.0/(1.+ x*x),但我担心这也不会奏效。你可以试着像这样分开工作:

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

这应该有效,但我不确定它是否符合您的需求。

答案 2 :(得分:2)

替换:

#pragma omp atomic

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

但我认为#pragma omp减少将是一个更好的选择,因为你有总和+ = Var;

这样做:

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

答案 3 :(得分:0)

您可能需要回顾#pragma以上问题的实际解决方案。

#pragma是一组非标准特定于编译器,大​​多数情况下,平台/系统特定 - 意味着在具有相同操作系统的不同机器上的行为可能不同,或者只是在具有不同设置的机器上 - 预处理器的一组功能。

因此,只有当您查看所选平台的编译器的官方文档时才能解决pragma的任何问题,这里有2个链接。

对于标准C / C ++ #pragma不存在。