Fortran 中的循环变量是否已保存?

Are loop variables in Fortran SAVEd?

我在子例程或函数中有 SAVE 语句。我也没有IMPLICIT NONE。在那种情况下,Fortran 中的循环变量是否已保存?示例:

FUNCTION GLOB7S(P)
      REAL LONG
      LOGICAL mess
      COMMON/iounit/konsol,mess
      COMMON/LPOLY/PLG(9,4),CTLOC,STLOC,C2TLOC,S2TLOC,C3TLOC,S3TLOC,
     $ IYR,DAY,DF,DFA,APD,APDF,APT(4),LONG
      COMMON/CSW/SW(25),ISW,SWC(25)
      DIMENSION P(100),T(14)
      SAVE
      DATA DR/1.72142E-2/,DGTR/1.74533E-2/,PSET/2./
      DATA DAYL/-1./,P32,P18,P14,P39/4*-1000./
!$OMP THREADPRIVATE(/iounit/)
!$OMP THREADPRIVATE(/LPOLY/)
!$OMP THREADPRIVATE(/CSW/)

!$OMP THREADPRIVATE(T,DR,DGTR,PSET,DAYL,P32,P18,P14,P39)
!$OMP THREADPRIVATE(CD32,CD18,CD14,CD39)
!$OMP THREADPRIVATE(T71,T72,T81,T82,TT,GLOB7S)
C       CONFIRM PARAMETER SET
      IF(P(100).EQ.0) P(100)=PSET
      IF(P(100).NE.PSET) THEN
        if(mess) WRITE(konsol,900) PSET,P(100)
  900   FORMAT(1X,'WRONG PARAMETER SET FOR GLOB7S',3F10.1)
        STOP
      ENDIF
      DO 10 J=1,14
        T(J)=0.
   10 CONTINUE
      IF(DAY.NE.DAYL.OR.P32.NE.P(32)) CD32=COS(DR*(DAY-P(32)))
      IF(DAY.NE.DAYL.OR.P18.NE.P(18)) CD18=COS(2.*DR*(DAY-P(18)))
      IF(DAY.NE.DAYL.OR.P14.NE.P(14)) CD14=COS(DR*(DAY-P(14)))
      IF(DAY.NE.DAYL.OR.P39.NE.P(39)) CD39=COS(2.*DR*(DAY-P(39)))
      DAYL=DAY
      P32=P(32)
      P18=P(18)
      P14=P(14)
      P39=P(39)
...

在此示例中 J 已保存?我需要知道这一点,因为我正在尝试使用 OpenMP 并行化非常古老且非常大的 Fortran 代码,但我不确定我是否正确使用了 THREADPRIVATE 指令。

问题形式的 DO 构造不是范围界定单元。此外,这种构造的“循环变量”不是特权实体:它只是包含以特定方式使用的循环的范围内的变量。

在这种情况下,

j 是存在于 DO 构造之前的变量,它存在于 after DO 构造中。

j 是隐式声明的类型是不相关的:不是具有隐式类型的构造或语句实体的变量存在于引用出现的整个范围单元(以及可能的其他单元)中(请参阅之后)。也就是说,这里的隐式类型 j 存在于整个函数中,而不仅仅是从它出现在 DO 构造中的那一点开始。

SAVE 语句适用于整个 (non-inclusive) 范围单元。如果 j 是局部变量(在这种情况下,不使用 - 或 host-associated),则 SAVE 将其保存。


正如 Steve Lionel 在评论中指出的那样,一般来说,事情可能要复杂得多。尽管与这个问题无关,但上面可能被视为一揽子陈述的内容也有例外。

考虑类似的概念(为清楚起见,切换到自由格式代码)

integer t(10)

data (t(j), integer :: j=1,10)/10*0/

t = [(0, integer :: j=1,10)]

forall (integer :: j=1:10) t(j) = 0

do concurrent (integer :: j=1:10)
  t(j) = 0
end do

end program

在每种情况下 j 语句或 DO CONCURRENT 构造的范围。 SAVE 语句将不适用于这些变量,因为它们不是作用域单元的局部变量。

即使没有显式 integer :: j,使用隐式类型,这些形式也不会在语句或构造之外隐式声明变量。

在其他结构中,例如 ASSOCIATE 结构:

associate (a => 1+2)
end associate

实体具有构造的范围,但在这种情况下,我们应该注意任何构造实体的类型都不是隐式的:它正是选择器的类型,而不是基于其名称的首字母。

最后,请注意(目前)没有

do integer :: j=1,10
end do

这使得普通的 DO 构造在这方面非常乏味。