Parallel processing OpenMP线程执行和threadprivate变量出现问题
我已经使用了8个线程进行8个循环。我用“print”来了解并行代码是如何工作的。0线程产生问题!我已经在所附的图表(请检查下面所附的链接)中展示了并行的工作原理。我使用了threadprivate,但结果表明线程0无法获取任何私有threadsafe变量 我也尝试过模块,得到了同样的结果! 你知道为什么代码会这样吗?如果有任何帮助或建议,我将不胜感激。谢谢Parallel processing OpenMP线程执行和threadprivate变量出现问题,parallel-processing,fortran,openmp,fortran90,Parallel Processing,Fortran,Openmp,Fortran90,我已经使用了8个线程进行8个循环。我用“print”来了解并行代码是如何工作的。0线程产生问题!我已经在所附的图表(请检查下面所附的链接)中展示了并行的工作原理。我使用了threadprivate,但结果表明线程0无法获取任何私有threadsafe变量 我也尝试过模块,得到了同样的结果! 你知道为什么代码会这样吗?如果有任何帮助或建议,我将不胜感激。谢谢 !$OMP PARALLEL DO do nb=m3+1, m3a, 2 60 icall=nb 65 iad=idint(
!$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
仅看前几行,您就遇到了重大问题
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
尚未初始化
要解决这些问题,您需要将icall
和iad
声明为private with
!$omp parallel do private(icall,iad)
在使用dflag之前,还应初始化它
这些最初的错误可能会导致您的大部分问题,但可能无法解决所有问题。您已经构建了非常复杂(难以维护)的线程交互,并且您的代码中充满了错误的做法(隐式变量,随意使用
goto
),这使得代码很难遵循。如果没有未显示的声明,则do循环体中有许多共享变量(icall
,iad
等)。您需要解决这个问题。请重新考虑这样的编码。隐式键入、common
块,甚至goto
都是麻烦。正如其他地方所写的,全局变量对于并行执行来说是个坏主意,正如您所发现的,不管全局变量是模块变量还是公共块实体,都无关紧要。正如在我对你的问题的回答中指出,你可能应该使用派生数据类型并将其传递给他人。然而,我仍然有点不清楚,你的实际算法是什么。你的福特呼叫的结果是在伺服中还是在一个公共块中找到的?现在,甚至不清楚这是否是可并行化的。责骂+1在你的最后一段中——隐式批量、多线程、共享内存、公共块、gotos——它将以眼泪结束。我支持Mark.OpenMP和典型Fortran 77或66的评论,这不是一个令人愉快的组合。