不同机器的不同 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/