我正在运行一些用fortan编写的代码。它由几个子程序组成,我使用模块中指定的全局变量在它们之间共享变量。
使用多个cpu时出现问题。在一个子例程中,代码应该通过全局变量的值更新局部变量的值。碰巧在一些随机传递的子程序中,当我使用多个cpus运行它时,代码不会更新变量。但是,如果我暂停它并使其上升以强制代码传递更新它工作的变量的代码片段!魔法!然后,我实现了一个循环,检查变量是否已更新并尝试在代码中使用(GOTO' s)返回以更新变量....但是对于2次尝试,它仍然有时会执行不更新变量。如果我只使用一个核心运行代码,那么它工作正常....任何想法??
由于
一段代码:
Subroutine1() !Where the variable A0 should be updated
nTries = 0
777 IF (nItems.NE.0) THEN
DO J = 1,nItems
IF (nint(mDATA(J,3)).EQ.nint(XCOORD+U1NE0)
& .AND. nint(mDATA(J,4)).EQ.nint(YCOORD+U2NE0) .AND.
2 nint(mDATA(J,5)).EQ.nint(ZCOORD+U3NE0)) THEN
A0 = mDATA(J,1)
JNODE = mDATA(J,2)
EXIT
ELSE
A0 = A02
ENDIF
ENDDO
IF (A0.EQ.ZERO) THEN !If the variable was not updated
IF (nTries.LE.2) THEN
nTries = nTries + 1
GOTO 777
ENDIF
write(6,*) "ZERO A0", IELEM, JTYPE
A0 = MAXT
ENDIF
答案 0 :(得分:1)
我不完全知道Abaqus如何与你的FORTRAN子程序交互,也不清楚上面的代码是什么出错了,但是你遇到的似乎是“竞争条件”的典型例子。你所谓的“一个核心领先于另一个。”
一般性评论是GOTO
和全局变量非常危险,因为它们使程序很难推理。一旦开始并行化,这些问题就会复杂化。如果Abaqus正在进行某种负责并行化的“黑盒子”计算,那么您(作为仅对数据进行预处理和后处理的用户)应该与此绝缘。但是,从上面来看,听起来你正在做一些与Abaqus并行计算交错的东西。在这种情况下,您需要确保您所做的一切都是线程安全的。在许多其他事情中,你绝对需要确保你没有写任何全局变量。
另一个评论是,您对A0
的检查基本上是一个名为“自旋锁”的锁。这是使线程安全的一种方法,但锁具有自己的缺陷。如果Abaqus没有给你一种方法来同步所有的线程并保证它完成了它的工作,那么这样的某种锁可能就是你想要的。