不同机器的不同 OpenMP 输出
different OpenMP output in different machine
当我尝试 运行 我的系统 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;
}
如果你的程序在一台机器上运行正确,那一定是因为它实际上不是运行在那台机器上并行的。
您的程序在 s=s+tid;
代码行中存在竞争条件。 s
是共享变量,多个线程同时尝试更新,导致数据丢失。
您可以通过将该行代码转换为原子操作来解决问题:
#pragma omp atomic
s=s+tid;
这样一次只有一个线程可以读取和更新变量s
,并且竞争条件不再存在。
在更复杂的程序中,您应该仅在必要时使用原子操作或关键区域,因为您在这些区域中没有并行性,这会影响性能。
编辑:正如用户 High Performance Mark 所建议的,我必须指出,由于原子操作,上面的程序效率非常低。进行这种计算的正确方法(在循环的所有迭代中添加到相同的变量)是实现 reduction。 OpenMP 通过使用 reduction
子句使其变得简单:
#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;
}
以下link以更详细的方式解释了临界区、原子操作和缩减:http://www.lindonslog.com/programming/openmp/openmp-tutorial-critical-atomic-and-reduction/
当我尝试 运行 我的系统 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;
}
如果你的程序在一台机器上运行正确,那一定是因为它实际上不是运行在那台机器上并行的。
您的程序在 s=s+tid;
代码行中存在竞争条件。 s
是共享变量,多个线程同时尝试更新,导致数据丢失。
您可以通过将该行代码转换为原子操作来解决问题:
#pragma omp atomic
s=s+tid;
这样一次只有一个线程可以读取和更新变量s
,并且竞争条件不再存在。
在更复杂的程序中,您应该仅在必要时使用原子操作或关键区域,因为您在这些区域中没有并行性,这会影响性能。
编辑:正如用户 High Performance Mark 所建议的,我必须指出,由于原子操作,上面的程序效率非常低。进行这种计算的正确方法(在循环的所有迭代中添加到相同的变量)是实现 reduction。 OpenMP 通过使用 reduction
子句使其变得简单:
#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;
}
以下link以更详细的方式解释了临界区、原子操作和缩减:http://www.lindonslog.com/programming/openmp/openmp-tutorial-critical-atomic-and-reduction/