9

我对 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

4 回答 4

13

根据当前的 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);

于 2012-12-25T22:52:53.723 回答
3

尝试更改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;

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

于 2012-12-24T01:26:08.247 回答
2

代替 :

#pragma omp atomic

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

但我想 #pragma omp reduction 将是一个更好的选择,因为你有 sum+=Var;

这样做:

x = (i + .5)*step;
double z = 4.0/(1.+ x*x);
#pragma omp reduction(+:sum)
sum += z;
于 2012-12-24T04:24:23.080 回答
0

您可能需要回顾一下#pragma问题的真正解决方案。

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

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

因为标准的 C/C++#pragma不存在。

于 2012-12-24T01:36:12.783 回答