在 Fortran 90 子程序中重复使用二维数组

Repeatedly used 2D array in a Fortran 90 subroutine

我有一个 Fortran 90 程序,其结构如下所示。 subroutinne A 中的步骤 compute the 2D array myMatrix(1:N,1:N) 很昂贵。它只依赖于全局变量N并且只需要计算一次;子程序中的“其他步骤”不会改变 myMatrix 的值。目前,myMatrix 将在每次调用子程序时计算。

有没有办法写程序让二维数组myMatrix只计算一次?

module constants
    integer :: N
end module constans

module A_module
use constants
contains
    subroutine A
    ! compute the 2D real array myMatrix(1:N,1:N)
    ! other steps that use myMatrix
    end subroutine A
end module A_module

program main
    use constants
    use A_module
    integer :: k

    do  k = 1,10000
        call A 
    end do

end program main

当然可以。定义一个 init_a_matrix 子程序,在 do 循环之外初始化矩阵。

subroutine init_a_matrix
   ! Do initialization here
end subroutine init_a_matrix

那么你有

call init_a_matrix
do  k = 1,10000
    call A 
end do

如果要消除子程序A中myMatrix的冗余初始化(因为只需要计算一次,在子程序的初始调用时),可以使用SAVE 属性和 LOGICAL 标志。在子程序中 A 你做,

logical :: init_flag = .false.
real, save :: matrix_a(n,n)
if (init_flag .eqv. .false.) then
   ! Initialize matrix_a on the first call to the subroutine and reset init_flag.
   init_flag = .true.
end if

如果myMatrix是子程序A未保存本地变量,那么它将是有必要在子例程的每个条目上重新计算其值:当子例程完成执行时,未保存的局部变量变为未定义。

但是,有多种方法可以重用变量:

  • 使其成为保存局部变量:保存的局部变量保留其定义
  • 将其作为虚拟参数,而不是局部变量(参数关联):其定义来自调用者
  • 将它作为某种其他形式的非局部变量(其他forms of association):它的定义来自另一个地方

如果它是已保存的变量,则在第一次进入子例程时对其进行计算,并在后续调用中保留其定义:

subroutine A
  <declaration>, save :: mymatrix
  logical, save :: first_entry = .TRUE.

  if (first_entry) then
     ! set up mymatrix
     first_entry = .FALSE.
  end if
  ! ...
end subroutine A

您可以对 mymatrix 一个 module/host 变量做很多相同的事情。您可以使用 first_entry 保存的指示器或依靠用户(如 )有一个额外的设置步骤:

module A_module
use constants
<declaration> myMatrix  ! Example with host association, automatically saved
contains
    subroutine A
    ! myMatrix is reused, either set up by a distinct call or on first entry
    ! other steps that use myMatrix
    end subroutine A
end module A_module

或者您可以将变量作为虚拟参数:

mymatrix_actual = ...
do k = 1,10000
  call A(mymatrix_actual)  ! A now has the dummy variable
end do