我的目标是在openMP中使用原子的或关键的原子,并获得与以下代码中使用firstprivate(state)相同的结果,但是编译器抛出的错误是omp原子的形式错误。
代码如下:
omp_set_dynamic(0);
omp_set_num_threads(threads[y]);
#pragma omp parallel for reduction(+:count) private(i)
for(i=1;i<=niter;i++){
double x, y, z;
long seed;
seed=i;
#pragma omp atomic
x=ran2(&seed, &state);
#pragma omp atomic
y=ran2(&seed, &state);
#pragma omp atomic
z=x*x+y*y;
if(z<1){
count+=1;
}
}
预期输出为:
The value of pi for 1 threads is 3.14320000000000
The value of pi for 2 threads is 3.13320000000000
The value of pi for 4 threads is 3.12400000000000
The value of pi for 8 threads is 3.14680000000000
The value of pi for 16 threads is 3.15880000000000
但是不一样吗?有获得相同指示的任何指示吗?
答案 0 :(得分:1)
编译器抛出omp原子无效的格式错误。
atomic
编译指示不适用于任何语句。仅允许使用特定形式的语句,具体取决于您使用哪种原子子句。如果未指定风味,则将获得“更新”风味,它需要使用以下形式之一的表达式语句(到目前为止非常好):
x++;
x--;
++x;
--x;
x binop= expr;
x = x binop expr;
x = expr binop x;
,其中binop
代表运算符+
,*
,-
,/
,&
,ˆ
中的一个,|
,<<
或>>
。还有更多的要求。参见the OpenMP specification的第2.13.6节。您尝试声明为atomic的语句均未满足这些要求。
但是不一样吗?有获得相同指示的任何指示吗?
以上解释了警告,但是即使允许使用这些表格,您对atomic
的期望似乎也比OpemMP更高。对于格式正确的原子操作,这是对特定存储位置(即上述x
指定)的访问,这是原子的,而不是整个语句的执行。您的x
,y
和z
已经是私有的,因此原子地更新它们不会给您带来任何好处。但是,state
是一个共享变量(与声明它firstprivate
时相反),您会遇到涉及对其进行访问的竞争条件,因此程序的行为是不确定的。
我想您的预期结果来自您在其中state
被声明为firstprivate
的替代代码中获得的结果,但是即使您对state
的访问已正确同步-通过将其放入{例如,{1}}节-期望得到相同的结果是不合理的,因为您将执行不同的计算。此外,结果的详细信息(可能)取决于线程调度的顺序。
我的目标是在openMP中使用原子的或关键的,并获得与以下代码中使用firstprivate(state)相同的结果
不能。如前所述,尽管您可以使用omp critical
部分来解决数据争用,但是所得的一系列计算与critical
所获得的计算有不同的,而且取决于线程调度。没有理由期望获得相同的结果。
此外,将关键部分置于如此紧密的循环中几乎肯定会消除并行化带来的任何性能优势。我希望随着线程数量的增加,甚至只有两个线程,并行版本会比串行版本迅速变慢。
答案 1 :(得分:0)
由于您没有在omp atomic
构造中指定 atomic-clause ,它将假定您想要update
。您的表达式语句不是更新语句。
您的omp指令应使用的是
#pragma omp atomic write
但是,由于x
,y
和z
都是局部变量,因此每个线程将具有其自己的副本,并且不需要原子构造。调用ran2
原子是不起作用的;只有结果分配。