当计时一个FORTRAN程序时,我通常只使用命令call cpu_time(t)
。然后我偶然发现了call system_clock([count,count_rate,count_max])
,它似乎也可以完成同样的任务,但是更加复杂。我的知识来源于:旧的英特尔文档。我在英特尔的主页上没有找到它。请参见下面的标记。
- 哪个更准确,或者它们相似吗?
- 它们中的一个会计算缓存未命中(或其他类似的东西),而另一个不会吗?或者它们中的任何一个都会计算?
- 还是下面标记的唯一区别?
这些是我的问题,下面我提供了一些代码,供您查看一些计时和用法。它们显示输出非常相似,因此在实现上似乎是相似的。我应该指出,我可能会一直使用cpu_time
,我并不需要更精确的计时。
在下面的代码中,我尝试进行比较。(我还尝试了更复杂的事情,但为了保持简洁,将不提供)所以基本上我的结果是:
cpu_time
- 更易于使用,不需要初始化调用
- 直接计算差值时间
- 应该也是编译器特定的,但没有办法看到精度。(通常为毫秒)
- 是线程时间的总和。即不建议用于并行运行。
system_clock
- 需要预先初始化。
- 在处理后以除法形式表示。(虽然很小,但是仍然有区别)
- 是编译器特定的。在我的PC上发现以下内容:
- Intel 12.0.4 使用10000的计数率,由于
INTEGER
精度。 - gcc-4.4.5 使用1000,不知道如何区分
- Intel 12.0.4 使用10000的计数率,由于
- 容易遇到wraparounds,即如果
c1 > c2
,由于count_max
- 是从一个标准时间开始计算的。因此,这将产生一个线程的实际时间,而不是总和。
代码:
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
with-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
with-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
感谢阅读...
INTEGER(8)
来表示SYSTEM_CLOCK
可以显著增加count_max
的值,对于其他一些编译器也应该这样做。 - gauteh