Fortran固有的时序例程,哪个更好? cpu_time或system_clock

时间:2011-07-29 19:44:51

标签: timer fortran

在为FORTRAN程序计时时,我通常只使用命令call cpu_time(t) 然后我偶然发现了call system_clock([count,count_rate,count_max])似乎在做同样的事情。但是,在一个更难的庄园。 我对这些的了解来自:Old Intel documentation 我无法在英特尔的主页上找到它。请参阅下面的标记。

  1. 哪个更准确,还是相似?
  2. 其中一个是否计算缓存未命中(或其他类别)而另一个没有,或者执行其中任何一个?
  3. 或者唯一的区别是我的标记中标记的东西?
  4. 这些是我的问题,下面我提供了一些代码供您查看一些时间和用法。他们告诉我他们在输出方面非常相似,因此在实施方面似乎相似 我应该注意,我可能总是坚持使用cpu_time,而且我并不需要更精确的时间。

    在下面的代码中,我试图比较它们。 (我也尝试了更精细的东西,但为了保持简洁而不会供应) 所以基本上我的结果是:

    • cpu_time
      1. 更容易使用,您不需要初始化调用
      2. 差异的直接时间
      3. 也应该是编译器特定的,但是没有办法看到精度。 (标准是毫秒)
      4. 是线程时间的总和。即不推荐用于并行运行。
    • system_clock
      1. 需要预先初始化。
      2. 后续过程,以分裂的形式。 (小事,但仍有区别)
      3. 是否特定于编译器。在我的电脑上发现以下内容:
        • 英特尔12.0.4 使用的计数率为10000,因为INTEGER精度。
        • gcc-4.4.5 使用1000,不知道这是如何区分的
      4. 由于c1 > c2
      5. ,很容易遇到 wraparounds ,即如果count_max
      6. 是时间从一个标准时间开始。因此,这将产生一个线程的实际时间而不是总和。

    代码:

    PROGRAM timer
      IMPLICIT NONE
      REAL :: t1,t2,rate 
      INTEGER :: c1,c2,cr,cm,i,j,n,s
      INTEGER , PARAMETER :: x=20000,y=15000,runs=1000
      REAL :: array(x,y),a_diff,diff
    
      ! First initialize the system_clock
      CALL system_clock(count_rate=cr)
      CALL system_clock(count_max=cm)
      rate = REAL(cr)
      WRITE(*,*) "system_clock rate ",rate
    
      diff = 0.0
      a_diff = 0.0
      s = 0
      DO n = 1 , runs
         CALL CPU_TIME(t1)
         CALL SYSTEM_CLOCK(c1)
         FORALL(i = 1:x,j = 1:y)
            array(i,j) = REAL(i)*REAL(j) + 2
         END FORALL
         CALL CPU_TIME(t2)
         CALL SYSTEM_CLOCK(c2)
         array(1,1) = array(1,2)     
         IF ( (c2 - c1)/rate < (t2-t1) ) s = s + 1
         diff = (c2 - c1)/rate - (t2-t1) + diff
         a_diff = ABS((c2 - c1)/rate - (t2-t1)) + a_diff
      END DO
    
      WRITE(*,*) "system_clock : ",(c2 - c1)/rate
      WRITE(*,*) "cpu_time     : ",(t2-t1)
      WRITE(*,*) "sc < ct      : ",s,"of",runs
      WRITE(*,*) "mean diff    : ",diff/runs
      WRITE(*,*) "abs mean diff: ",a_diff/runs
    END PROGRAM timer
    

    要完成此处,请提供我的Intel 12.0.4和gcc-4.4.5编译器的输出。

    • Intel 12.0.4-O0

      system_clock rate    10000.00    
      system_clock :    2.389600    
      cpu_time     :    2.384033    
      sc < ct      :            1 of        1000
      mean diff    :   4.2409324E-03
      abs mean diff:   4.2409897E-03
      
      real    42m5.340s
      user    41m48.869s
      sys 0m12.233s
      
    • gcc-4.4.5-O0

      system_clock rate    1000.0000    
      system_clock :    1.1849999    
      cpu_time     :    1.1840820    
      sc < ct      :          275 of        1000  
      mean diff    :   2.05709646E-03  
      abs mean diff:   2.71424348E-03  
      
      real    19m45.351s  
      user    19m42.954s  
      sys 0m0.348s  
      

    感谢阅读...

4 个答案:

答案 0 :(得分:18)

这两个内在函数报告了不同类型的时间。 system_clock报告“挂起时间”或已用时间。 cpu_time报告CPU使用的时间。在多任务机器上,这些可能是非常不同的,例如,如果您的进程与其他三个进程共享CPU,因此接收了25%的CPU并使用了10 cpu秒,则需要大约40秒的实际流逝或墙壁时钟时间。

答案 1 :(得分:5)

cpu_time()在Intel兼容CPU上的分辨率通常约为0.01秒。这意味着较小的时间间隔可以计为零时间。 linux的大多数当前编译器使得system_clock()的分辨率取决于参数的数据类型,因此整数(int64)将提供优于1微秒的分辨率,以及允许在相当长的时间间隔内进行计数。 最近(2015年)更改了Windows的gfortran,以使system_clock()等同于query_performance调用。但是,即使在将omp_get_wtime更改为使用query_performance之后,ifort Windows仍然显示system_clock的约0.01分辨率。 我会打算以前关于在时钟滴答中测量cpu_time或system_clock分辨率的评论,特别是如果这可能被认为与CPU或数据总线滴答相关,例如rdtsc指令可以报告。

答案 2 :(得分:3)

我发现itime(请参阅gfortran manual)是system_clock计时堡垒计划的一个很好的替代方案。它非常易于使用:

integer, dimension(3) :: time
call itime(time)
print *, 'Hour:  ', time(1)
print *, 'Minute:', time(2)
print *, 'Second:', time(3)

答案 3 :(得分:0)

我发现秒()是最简单的获取时间的方法。它的用法几乎与cpu_time()相同。

real(8)::t1,delta
t1=secnds(0.0)
!Do stuff
delta=seconds(t1)