当我试图在我的系统centos中运行以下代码时,我正在获得正确的输出,但是当我试图在紧凑型超级计算机“Param Shavak”上运行相同的代码时,我得到的输出不正确....: (
#include<stdio.h>
#include<omp.h>
int main()
{
int p=1,s=1,ti
#pragma omp parallel private(p,tid)shared(s)
{
p=1;
tid=omp_get_thread_num();
p=p+tid;
s=s+tid;
printf("Thread %d P=%d S=%d\n",tid,p,s);
}
return 0;
}
答案 0 :(得分:0)
如果你的程序在一台机器上正确运行,那一定是因为它实际上并没有在那台机器上并行运行。
您的程序在s=s+tid;
代码行中遇到竞争条件。 s
是一个共享变量,因此多个线程同时尝试更新它,这会导致数据丢失。
您可以通过将该行代码转换为原子操作来解决问题:
#pragma omp atomic
s=s+tid;
这样一次只有一个线程可以读取和更新变量s
,并且竞争条件不再存在。
在更复杂的程序中,您应该仅在必要时使用原子操作或关键区域 ,因为您在这些区域中没有并行性并且会损害性能。
编辑:正如用户高性能标记所建议的那样,我必须注意上面的程序由于原子操作而效率很低。进行这种计算的正确方法(在循环的所有迭代中添加相同的变量)是实现减少。通过使用reduction
子句,OpenMP使其变得简单:
#pragma omp reduction(operator : variables)
尝试此版本的程序,使用还原:
#include<stdio.h>
#include<omp.h>
int main()
{
int p=1,s=1,tid;
#pragma omp parallel reduction(+:s) private(p,tid)
{
p=1;
tid=omp_get_thread_num();
p=p+tid;
s=s+tid;
printf("Thread %d P=%d S=%d\n",tid,p,s);
}
return 0;
}
以下链接以更详细的方式解释关键部分,原子操作和缩减:http://www.lindonslog.com/programming/openmp/openmp-tutorial-critical-atomic-and-reduction/