我有OpenMP的问题。 MSVC编译器抛出“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;
}
根据当前的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);
)
替换:
#pragma omp atomic
由#pragma omp reduction(+:sum)
或#pragma omp critical
但我认为#pragma omp减少将是一个更好的选择,因为你有sum + = Var;
这样做:
x = (i + .5)*step;
double z = 4.0/(1.+ x*x);
#pragma omp reduction(+:sum)
sum += z;
尝试将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;
这应该有效,但我不确定它是否符合您的需求。
你可能需要回顾一下#pragma
,而不是你问题的真正解决方案。
#pragma
是一组非标准的,特定于编译器的,并且大部分时间是特定于平台/系统的 - 这意味着在具有相同OS的不同机器上的行为可以是不同的,或者仅仅在具有不同设置的机器上的行为可以是不同的 - 用于预处理器。
因此,只有当您查看所选平台的编译器的官方文档时才能解决pragma的任何问题,这里有2个链接。
对于标准C / C ++,#pragma
不存在。