OpenMP线程执行和threadprivate变量问题 [英] Issue with OpenMP thread execution and threadprivate variable

查看:307
本文介绍了OpenMP线程执行和threadprivate变量问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经将8个线程用于8个循环.我已经使用打印"来查看并行代码的工作方式. 0线程会产生问题!我在附图中(请检查下面的链接)显示了并行工作的方式.我使用过threadprivate,但事实证明,线程0无法获得任何私有线程安全变量.

I have used 8 threads for 8 loops. I have used 'print' to see how the parallel code works. The 0 thread creates problems!I have showed in the attached diagram (please check the attached link below) how the parallel works. I have used threadprivate but it turned out that thread 0 can not get any private threadsafe variables.

我也尝试过使用模块,并且得到了相同的结果! 知道为什么代码以这种方式工作吗?我将不胜感激任何帮助或建议.谢谢!

I have tried with modules as well and got same results! Any idea why the code acts this way? I would appreciate any help or suggestion. Thanks!

  !$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

推荐答案

仅看头几行,您就会遇到重大问题.

Looking at just the first few lines you have major problems.

   do nb=m3+1, m3a, 2

这部分很好,每个线程都有一个正确初始化的nb的专用副本.

This part is fine, each thread will have a private copy of nb properly initialized.

60   icall=nb

这是一个问题. icall是共享的,每个线程都会将其nb的私有值写入共享中.线程是同时运行的,并且顺序和计时是不确定的,因此无法提前知道每个线程中的icall值.

This is a problem. icall is shared and each thread will write its private value of nb into the shared. Threads run concurrently and the order and timing is non-determanistic so the value of icall in each thread cannot be known ahead of time.

65   iad=idint(a(icall))    

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

Now we use icall to calculate a value to store in the shared variable iad. What are the problems? The value of icall may not be the same as in the previous line if another thread wrote to it between this thread's execution. The value of iad is being clobbered by each thread.

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

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

These lines have the same problems as above. The value of iad may not be the same as above and it may not be the same between these two lines depending on the execution of the other threads.

     if(.not.dflag) goto 80 

此时变量dflag尚未初始化.

要解决这些问题,您需要将icalliad声明为private with

To fix these problems you need to declare icall and iad as private with

!$omp parallel do private(icall,iad)

您还应该在使用dflag之前对其进行初始化.

You should also initialize dflag before you use it.

这些最初的错误可能会导致很大一部分问题,但可能无法解决所有问题.您已经设计了非常复杂(难以维护)的线程交互,并且代码中充斥着不良做法(隐式变量,goto的随意使用),这使该代码难以遵循.

These first errors are probably responsible for a large chunk of your problem but may not fix everything. You have architected very complex (hard to maintain) thread interaction and your code is full of bad practices (implicit variables, liberal use of goto) which make this code hard to follow.

这篇关于OpenMP线程执行和threadprivate变量问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆