在 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
我有一个 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