Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用FORTRAN+;OpenMP_Fortran_Openmp_Race Condition - Fatal编程技术网

使用FORTRAN+;OpenMP

使用FORTRAN+;OpenMP,fortran,openmp,race-condition,Fortran,Openmp,Race Condition,首先,我在不使用-fopenmp的情况下编译了代码,并运行了代码,得到了一个串行结果,这是一个基准测试。 其次,我考虑使用OpenMP来加速我的代码 有两个奇怪的结果: 1.通过以下方式获得的结果: !$OMP CRITICAL p1=p1+1 !$OMP END CRITICAL 与系列结果有一点差异(1%)。我的代码不包含随机数,所以它一定是错的。 2.如果我替换$OMP临界带$OMP原子和删除$OMP END CRITICAL,两者之间的结果完全不同。在这种情

首先,我在不使用
-fopenmp
的情况下编译了代码,并运行了代码,得到了一个串行结果,这是一个基准测试。 其次,我考虑使用OpenMP来加速我的代码

有两个奇怪的结果: 1.通过以下方式获得的结果:

   !$OMP CRITICAL
       p1=p1+1
   !$OMP END CRITICAL 
与系列结果有一点差异(1%)。我的代码不包含随机数,所以它一定是错的。 2.如果我替换
$OMP临界
$OMP原子
和删除$OMP END CRITICAL,两者之间的结果完全不同。在这种情况下,对于
p1=p1+1
,这两者不是可以互相替换吗

我的想法: 1.最常见的问题可能是使用线程不安全的子例程。但我在下面的代码中找不到

这是从我的代码中复制的一部分

注意:

  • 除i、j、k、k1、k2、k3、距离以外的变量被视为“共享”
  • 下面的代码是整个代码中唯一并行的部分
  • (i,j,k,k1,k2,k3,距离)在并行循环后不使用,因此不考虑“private”声明的私有变量的不确定性

    p1=0;
    
    !$OMP PARALLEL PRIVATE(i,j,k,k1,k2,k3,distance)
    !$OMP DO
    do i=1,N_MESH;do j=1,N_MESH;do k=1,N_MESH;
    
       !$OMP CRITICAL
       p1=p1+1
       !$OMP END CRITICAL
    
       ! - box-1. special treatment for doing specturm operations for FFT.
       if (i.lt.(N_MESH/2+1))then
           k1=i-1
       elseif (i.eq.N_MESH/2+1) then
           k1=0
       else
           k1=i-1-N_MESH
       endif
    
       if (j.lt.(N_MESH/2+1))then
           k2=j-1
       elseif (j.eq.N_MESH/2+1)then
           k2=0
       else
           k2=j-1-N_MESH
       endif
    
       if (k.lt.(N_MESH/2+1))then
           k3=k-1
       elseif (k.eq.N_MESH/2+1)then
           k3=0
       else
           k3=k-1-N_MESH
       endif
    
       ! =============distance =====================
       distance=(k1*k1)+(k2*k2)+(k3*k3);
    
       ! -----============put them into =======================
       final_index(p1,l) = nint(dsqrt(distance));
    
       if (((k1.eq.0).AND.(k2.eq.0)).AND.(k3.eq.0)) THEN
          final(p1,l)=0d0
       else
          final(p1,l)=(abs(fu(i,j,k))**2+abs(fv(i,j,k))**2+abs(fw(i,j,k))**2)/2d0
    
       endif
    
    enddo;enddo;enddo
    !$OMP END DO
    !$OMP END PARALLEL
    

  • 问题在于
    p1
    是共享的,并且在循环主体期间可能会发生变化

    假设有两个线程,p1从零开始,它们同时开始。第一级0到达临界段,并将
    p1
    增加到1,而第1级则等待临界段结束。一旦秩0完成递增
    p1
    ,它开始执行其余的代码,但同时秩1开始执行临界段,并递增
    p1
    。在
    p1
    变为2之前,不能保证秩0将到达
    最终(p1,l)=…
    语句。如果发生这种情况,
    final(1,l)
    将永远不会更新。所以有一个竞赛条件

    p1 = k + N_MESH*(j-1+N_MESH*(i-1))
    
    为了避免此问题,我建议您基于
    I
    j
    k
    手动计算
    p1
    。这将允许您将
    p1
    设置为私有,为您保存一个关键部分,并删除此争用条件

    p1 = k + N_MESH*(j-1+N_MESH*(i-1))
    

    问题在于
    p1
    是共享的,并且在循环主体期间可能会发生变化

    假设有两个线程,p1从零开始,它们同时开始。第一级0到达临界段,并将
    p1
    增加到1,而第1级则等待临界段结束。一旦秩0完成递增
    p1
    ,它开始执行其余的代码,但同时秩1开始执行临界段,并递增
    p1
    。在
    p1
    变为2之前,不能保证秩0将到达
    最终(p1,l)=…
    语句。如果发生这种情况,
    final(1,l)
    将永远不会更新。所以有一个竞赛条件

    p1 = k + N_MESH*(j-1+N_MESH*(i-1))
    
    为了避免此问题,我建议您基于
    I
    j
    k
    手动计算
    p1
    。这将允许您将
    p1
    设置为私有,为您保存一个关键部分,并删除此争用条件

    p1 = k + N_MESH*(j-1+N_MESH*(i-1))
    

    我有点赶时间,所以这可能是错的。我看不到任何保证,这条语句--
    final_index(p1,l)=nint(dsqrt(distance))
    --不会由具有相同lhs的多个线程执行<代码>最终索引,
    p1
    l
    似乎都是共享的。事实上,我正在努力寻找
    l
    在哪里得到任何价值。我有点匆忙,所以这可能是错误的。我看不到任何保证,这条语句--
    final_index(p1,l)=nint(dsqrt(distance))
    --不会由具有相同lhs的多个线程执行<代码>最终索引,
    p1
    l
    似乎都是共享的。事实上,我正在努力寻找
    l
    在哪里有任何价值。答案很好!我真的没想到会发生这种事!我工作到凌晨4点。因此,综上所述,竞争条件不仅可能发生在多个线程同时读写(如a=a+1)中,而且也可能发生在多个位置读写,如在平行区域范围内的两个遥远位置。因为在逐行执行期间,可以更改共享变量。正如您所说,解决方案通常是寻找私有变量和共享变量之间的关系。@是的,每个线程都可以位于并行部分的任何位置—它们不会在同一时间执行同一行代码。在确定线程安全性时,必须考虑所有共享变量可以写入/读取的地方。我真的没想到会发生这种事!我工作到凌晨4点。因此,综上所述,竞争条件不仅可能发生在多个线程同时读写(如a=a+1)中,而且也可能发生在多个位置读写,如在平行区域范围内的两个遥远位置。因为在逐行执行期间,可以更改共享变量。正如您所说,解决方案通常是寻找私有变量和共享变量之间的关系。@是的,每个线程都可以位于并行部分的任何位置—它们不会在同一时间执行同一行代码。在确定线程安全性时,必须考虑所有共享变量可以写入/读取的地方。