Fortran:计时代码部分的最佳方法?


15

有时在优化代码时需要对代码的某些部分进行计时,但我多年来一直在使用以下代码,但想知道是否有更简单/更好的方法来做到这一点?

call system_clock(count_rate=clock_rate) !Find the time rate
call system_clock(count=clock_start)     !Start Timer

call do_something_subroutine             !This is what gets timed

call system_clock(count=clock_stop)      ! Stop Timer

e_time = real(clock_stop-clock_start)/real(clock_rate)

Answers:


11

还有其他几种方法,各有利弊:

  • MPI_WTIME:这是高分辨率壁钟。这可能是最“值得信赖”的选择。它只是工作。缺点是,如果您的程序尚未使用MPI,则必须将MPI包装起来(这并不困难)。
  • 使用fortran内部函数(如您所愿):这可能是最简单的方法,通常就足够了,但是在奇怪的体系结构或并行作业上可能无法很好地工作。关于此堆栈溢出有一些讨论
  • 包装C调用:Fortran和C是对象兼容的,因此它很容易为C调用编写包装器。我使用的代码使用getrusage,这可能是一个奇怪的选择。关于堆栈溢出有很多 讨论

我个人的建议是MPI_WTIME,因为您知道只要有MPI,它都会很好地工作。这是快速搜索的示例

  include 'mpif.h'
  DOUBLE PRECISION :: start, end
  start = MPI_Wtime()

  ! code to be timed

  end   = MPI_Wtime()
  write(*,*) 'That took ',end-start,' seconds'

4

如果使用GNU编译器,请签出gprof

简而言之,您将-g标志添加到编译器中,如下所示:

g77 -g -pg -0 myprogram myprogram.F

然后,运行输出,一个名为gmon.out的文件将显示在您的目录中。然后打电话

gprof --line myprogram gmon.out

这将提供逐行的CPU时间配置文件。


感谢您的回答,我只需要澄清一下,我正在寻求一个程序化解决方案。探查器很棒,但它超出了我的要求。
隔震荡

3
标志是-pg-g用于调试符号(也很有趣,但不是必需的)
RSFalcon7 2013年

我听说在多个地方,通过gprof的给出的时机不一定准确,如yosefk.com/blog/...stackoverflow.com/questions/1777556/alternatives-to-gprof/...(以及各种其他迈克Dunlavey答案在堆栈溢出)。诸如gprof和kcachegrind之类的工具仍然有用,因为函数调用的数量仍然正确,并且它们为您提供了一些计时数据,但我不会将其视为福音。DOE为此提供了一些工具,但我不知道它们是否比插入计时器更好。
Geoff Oxberry

1
认真地,@IsopycnalOscillation尝试使用探查器。这是新知识,但是从长远来看,它将极大地帮助您(并清理代码!)。
tmarthal

谢谢@tmarthal我以前使用过探查器,并且我肯定会在下一个项目中使用探查器-我完全同意您的意见。
Isopycnal振荡2013年

2

如icurays1所述,分析是最好的。您也可以略微简化以上内容...

use utils
...
call tic()
   ! Section to be timed
call toc()
...
call tic()
   ! Section to be timed
call toc()
...

utils模块包含...

real(8) :: t1,t2
...
subroutine tic()
  implicit none
  call cpu_time(t1)
end subroutine tic

subroutine toc()
  implicit none
  call cpu_time(t2)
  ! if (rank==0) print*,"Time Taken -->", real(t2-t1)
  print*,"Time Taken -->", real(t2-t1)
end subroutine toc

如果您有很多这样的部分,则在toc中传递一个字符串,例如“ section_id”,以便它显示ID /名称以及时间。


我建议不要进行make t1t2global,而是将其t1作为参数传递给两个函数,以允许多个计时器。您也可以只返回时间,而不打印任何内容。
Pedro
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.