OpenMP线程执行和threadprivate变量的问题

时间:2015-09-15 22:35:14

标签: parallel-processing fortran openmp fortran90

我使用8个线程进行8次循环。我用过' print'看看并行代码是如何工作的。 0线程产生问题!我已在附图中显示(请查看下面附带的链接)并行工作原理。我使用过threadprivate但事实证明,线程0无法获得任何私有线程安全变量。

我也尝试过模块并得到相​​同的结果! 知道代码为何如此行事吗?我将不胜感激任何帮助或建议。谢谢!

  !$OMP PARALLEL DO
  do nb=m3+1, m3a, 2
  60 icall=nb
  65 iad=idint(a(icall))    
  if(iad.eq.0) goto 100     
  call ford(a(iad),servo)      
  if(.not.dflag) goto 80  
  atemp=dble(nemc)
  nemc=iad
  a(icall)=a(iad+6)
  a(iad+6) = atemp
  dflag=.false.
  goto 65    
  80 icall=iad+6     
  goto 65
  100 continue
  end do
  !$OMP END PARALLEL DO

  subroutine FORD(i,j)
  dimension zl(3),zg(3)
  common /ellip/ b1,c1,f1,g1,h1,d1,
   .               b2,c2,f2,g2,h2,p2,q2,r2,d2
  common /root/ root1,root2
  !$OMP threadprivate (/ellip/,/root/)
  CALL CONDACT(genflg,lapflg)
  return
  end subroutine

  SUBROUTINE CONDACT(genflg,lapflg)
  common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
  !$OMP threadprivate (/ellip/)
  RETURN
  END

enter image description here

1 个答案:

答案 0 :(得分:3)

只看前几行你就遇到了重大问题。

   do nb=m3+1, m3a, 2

这部分没问题,每个帖子都有nb正确初始化的私人副本。

60   icall=nb

这是一个问题。共享icall,每个线程将其私有值nb写入共享。线程并发运行,顺序和时间是非威慑性的,因此每个线程中icall的值不能提前知道。

65   iad=idint(a(icall))    

现在我们使用icall来计算要存储在共享变量iad中的值。有什么问题?如果另一个线程在此线程的执行之间写入,icall的值可能与上一行中的值不同。 iad的值被每个线程破坏。

     if(iad.eq.0) goto 100     
     call ford(a(iad),servo)

这些行具有与上述相同的问题。 iad的值可能与上面的不一样,并且这两行之间可能不一样,具体取决于其他线程的执行情况。

     if(.not.dflag) goto 80 

此时尚未初始化变量dflag

要解决这些问题,您需要将icalliad声明为私有

!$omp parallel do private(icall,iad)

您还应该在使用之前初始化dflag

这些第一个错误可能是您问题的一大部分,但可能无法解决所有问题。您构建了非常复杂(难以维护)的线程交互,并且您的代码充满了不良实践(隐式变量,自由使用goto),这使得此代码难以遵循。