如何解决连续调用fortran中的同一子例程,性能明显降低
TL; DR
我的程序两次调用一个子例程。该子例程两次都执行基本相同的操作,但是第二次运行需要更长的时间。这两个调用之间的唯一区别是,第一个调用中生成的数据被用作第二个调用中的输入。该数据存储在第一次调用子例程之前在模块中声明的可分配数组中。
全文
program Economy
!! Declarations !!
use Modern_mod,only: Modern
use Globals,only: Na,Ny,Ne,Vimp,Xmp,Pmp,FCp,Vimu,& ! Globals is a module containing vbles.
& Xmu,Pmu,FCu
implicit none
real(kind=nag_wp) :: param(4)
!! Execution !!
! First call to modern !
param = (/1.0d0,2.0d0,3.0d0,4.0d0/)
allocate(Vimp(Na,Ne),FCp(4,Na*Ne),Pmp(Ny,Xmp(Ny,Ne))
call Modern(param,Xmp)
! Second call to modern !
param = (/5.0d0,6.0d0,7.0d0,8.0d0/)
allocate(Vimu(Na,FCu(4,Pmu(Ny,Xmu(Ny,FCu,Xmu)
end program Economy
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module Modern_mod
implicit none
contains
subroutine Modern(param,Vim,FCm,Pm,Xm)
!! Declarations !!
! Modules !
use Globals,Ny
use FindVmp_mod,only: FindVmp
use FindVmu_mod,only: FindVmu
implicit none
! Declaring other variables !
real(kind=nag_wp),intent(in) :: param(4) ! param-Parameters specific to one of the modern sectors;
real(kind=nag_wp),intent(out),allocatable :: FCm(:,:),Xm(:,& ! FCm-Firm choices; Xm-Policy fun;
& Pm(:,Vim(:,:) ! Pm-Price of a share; Vim-Start of period value function;
real(kind=nag_wp),allocatable :: Vm1(:,Vim1(:,Pm1(:,& ! Vm1-Vm next guess; Pm1-Next share price guess;
& Vm(:,:) ! Vm-End of period value function; Vim1-Next Vim guess;
!! Execution !!
! Allocating and initializing functions !
allocate(Vim(Na,FCm(4,Vm(Ny,Pm(Ny,Xm(Ny,Ne))
allocate(Vim1(Na,Vm1(Ny,Pm1(Ny,Ne))
! Inizializing arrays !
Vm = ...
Vim = ...
...
! Doing calculations !
if(param(1) .eq. 1.0d0) then
call FindVmp(FCm,Vm1,Pm1,Xm) ! New value funciton guess for productive guys
else
call FindVmu(FCm,Xm) ! New value funciton guess for unproductive guys
end if
end subroutine Modern
end module Modern_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module FindVmp_mod
implicit none
contains
subroutine FindVmp(FCm,Vim0,P0,Vm,P,x)
!! Declarations !!
use Vmfp_mod,only: Calculations ! Contains the operations computing the final values of the outputs to FindVmp
implicit none
real(kind=nag_wp),allocatable,intent(out) :: Vm(:,x(:,P(:,:) ! Vm-New value function; x-Policy function; P-Share price;
real(kind=nag_wp),intent(in) :: P0(:,Vim0(:,FCm(:,:) ! P0-Initial share price guess; Vim-Initial guess for beginning of period value function;
! FCm-Firm choices;
!! Execution !!
! Allocate matrices !
allocate(Vm(Ny,x(Ny,P(Ny,Ne))
! Compute results !
call Calculations(FCm,x)
end subroutine FindVmp
end module FindVmp_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module FindVmu_mod
implicit none
contains
subroutine FindVmu(FCm,x)
!! Declarations !!
use Globals,only: Vmp,Pmp
use VmFu_mod,only: Calculations ! Contains the operations computing the final values of the outputs to FindVmu
implicit none
real(kind=nag_wp),x,Vmp,Pmp) ! Using the values of Vmp and Pmp computes in the first call to Modern
end subroutine FindVmu
end module FindVmu_mod
每次运行时,Modern
被馈入在模块*p
中声明的相同大小和类型(分别为*u
和Globals
)的不同数组。 Modern
类似地调用两个非常相似的子例程FindVm?
中的一个,为它们提供相应的数组。 FindVmp
和FindVmu
计算几乎相同的操作,只是后者使用Vimp,Pmp
的值(在FindVmp
中计算)作为输入。
我一直在试图弄清为什么第二个对Modern
的调用与第一个相比要花费更长的时间来完成。
我的第一个猜测是,也许通过在程序开始时分配Vimp
和Pmp
,然后再分配一堆其他数组,每个对前一个数组的引用可能会很昂贵,因为它们的内存地址与FindVmu
中当前正在计算的数组(供参考,Na = 101,Ny = 91,Ne = 9
)相距很远。但是后来我读到allocated
数组存储在堆中,并且堆中的数据没有被 stacked (没有双关语),因此这不一定是我的问题的根源。实际上,我尝试在Modern
中以不同的点和顺序将所有矩阵分配给我,但是执行时间大致相同。
本着同样的精神,我试图改变在不同子例程中声明某些数组的方式(例如,使某些数组自动而不是可分配,并使用编译器(ifort18)选项将其强制放在堆栈上),尽管我确实会在整个代码中产生整体性能差异,两次调用Modern
的相对性能不会改变。
最后,我读到in this thread,说您在内存中拥有的数组越多,代码通常就变得越慢。尽管这种解释对我来说确实有意义,但这是我第一次在整个fortran程序中遇到如此重大的性能损失。如果这确实是我面临的问题,那么我可能会在之前的许多项目中都遇到过这个问题。尽管如此,这是否可能是这里发生的事情的原因?
我基本上没有主意...
奖励问题
我们正在研究它,但发现Economy
中的以下几行(对我而言)令人惊讶地不会导致段错误:
allocate(Vimp(Na,Ne))
allocate(Vimu(Na,Ne))
换句话说:如果我不手动分配在Globals
中声明的数组,那么当我将它们传递给Modern
时,程序似乎就自动执行了。是这种标准行为,还是当我最初自己不分配它们时很幸运?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。