Ste*_*ini 2 performance fortran
我在这个琐碎的节目中发现了一个非常奇怪的效果
module Moo
contains
subroutine main()
integer :: res
real :: start, finish
integer :: i
call cpu_time(start)
do i = 1, 1000000000
call Squared(5, res)
enddo
call cpu_time(finish)
print '("Time = ",f6.3," seconds.")',finish-start
end subroutine
subroutine Squared(v, res)
integer, intent(in) :: v
integer, intent(out) :: res
res = v*v
end subroutine
! subroutine main2()
! integer :: res
! real :: start, finish
! integer :: i
!
! call cpu_time(start)
!
! do i = 1, 1000000000
! res = v*v
! enddo
! call cpu_time(finish)
!
! print '("Time = ",f6.3," seconds.")',finish-start
! end subroutine
end module
program foo
use Moo
call main()
! call main2()
end program
Run Code Online (Sandbox Code Playgroud)
编译器是mac上的gfortran 4.6.2.如果我编译-O0并运行程序,时间是4.36秒.如果我取消注释子程序main2(),而不取消其调用,则时间平均变为4.15秒.如果我也取消注释,call main2()第一个时间变为3.80,第二个时间变为1.86(可理解,我没有函数调用).
我比较了在第二和第三种情况下生成的汇编程序(例程未注释;调用注释和未注释)并且它们完全相同,除了实际调用main2例程.
代码如何通过调用将来会发生的例程来提高性能,并且在结果代码中基本没有区别?
我注意到的第一件事是你的程序太短,无法进行适当的基准测试.你用多少次跑步来平均?什么是标准偏差?我在代码中添加了一个嵌套的do循环,使其更长:
do i = 1, 1000000000
do j=1,10
call Squared(5, res)
enddo
enddo
Run Code Online (Sandbox Code Playgroud)
我只查看了案例1和案例2(main2评论和未注释),因为案例3是不同的,与此比较无关.我希望在案例2中运行时略有增加,因为需要将更大的可执行文件加载到内存中,即使该部分未在程序中使用.
因此,对于三个编译器,我为第1和第2个案例进行了计时(每次运行3次):
pgf90 10.6-0 x86-64上的64位目标Linux -tp istanbul-64
英特尔(R)Fortran英特尔(R)64编译器XE,适用于运行在英特尔(R)64,版本12.0.2.137 Build 20110112上的应用程序
GNU Fortran(GCC)4.1.2 20080704(Red Hat 4.1.2-51)
在AMD Opteron(tm)处理器6134上
我的脚本输出是:
exp 1 with pgf90:
Time = 30.619 seconds.
Time = 30.620 seconds.
Time = 30.686 seconds.
exp 2 with pgf90:
Time = 30.606 seconds.
Time = 30.693 seconds.
Time = 30.635 seconds.
exp 1 with ifort:
Time = 77.412 seconds.
Time = 77.381 seconds.
Time = 77.395 seconds.
exp 2 with ifort:
Time = 77.834 seconds.
Time = 77.853 seconds.
Time = 77.825 seconds.
exp 1 with gfortran:
Time = 68.713 seconds.
Time = 68.659 seconds.
Time = 68.650 seconds.
exp 2 with gfortran:
Time = 71.923 seconds.
Time = 74.857 seconds.
Time = 72.126 seconds.
Run Code Online (Sandbox Code Playgroud)
请注意,案例1和案例2之间的时间差异对于gfortran而言最大,而对于pgf90而言则最小.
编辑:在Stefano Borini指出我忽略了这样一个事实,即只使用调用cpu_time对循环进行基准测试,可执行加载时间是不合适的.AShelley的回答提出了可能的原因.对于更长的运行时间,两种情况之间的差异变得最小.仍然 - 我观察到gfortran的情况有显着差异(见上文)
我认为@ IRO-bot有正确的答案,但我想指出代码放置会影响时序,即使是相同的汇编.
我有两个在相同处理器上运行的嵌入式应用程 每个都有相同的手动编码程序例程,以提供尽可能紧密的忙循环(用于插入亚微秒延迟).我最近惊讶地发现,在一个应用程序中,循环占用了50%!比另一个更长.两者都生成了完全相同的组件.
事实证明,在一个可执行文件中,循环体的起始地址允许它完全落在处理器的唯一指令缓存行中.在较慢的一个上,相同的功能从一个地址开始,导致它跨越两行.需要额外的提取主导了这种紧密循环的时间.
因此,由于指令缓存序列的变化,有可能找到添加未执行代码会影响代码时序的实例.