在 Fortran 中获得准确的 运行 时间
Attaining the exact run-time in Fortran
我需要将现有的 Fortran 代码设置为 运行 并有时间限制(即 24 小时周期)。我正在尝试实现一个简单的 运行-time 计时,它测量 "real life" 时间(而不是 CPU 时间)代码是 运行ning 并执行适当的保存和终止例程。
由于这种检查经常发生,我不想实际得到一整天的时间并从中计算总数 hours/minutes。我更喜欢 CPU_TIME()
的内容并做一个简单的 (Current-Start)/3600
(我真的只需要几个小时的分辨率)。
我实际上尝试以最简单的方式实现 CPU_TIME()
并且它似乎工作了很短的时间,但显然随着时间的增加,有一个 "drift" 我最终 运行ning 比实际的时间限制略多,它终止了我的代码而没有保存 "checkpoint"。
除了尝试设置小时数的下限以尝试考虑 "drift",是否有更精确但简单的实现可以在几分钟的分辨率内获得正确的 运行 时间?
编辑:
我也尝试使用 system_clock
,但是实际时间和该例程的输出时间完全不符......我做错了什么?
INTEGER :: scount, & ! Starting "time"
ecount, & ! Ending "time"
rate ! number of clock ticks per second
call system_clock(scount,rate)
...
<CODE>
...
call system_clock(ecount)
timer_elapsed_time = real(ecount-scount,8)/real(rate,8)
write(*,*) "Calculated run time is ",timer_elapsed_time *3600," hours"
解决方案:在某些情况下,时钟频率可以是real
而不是integer
,比如我的情况。
这取决于您希望经过的时间测量的精确度。以下模块将允许您计算精确到毫秒的时间。
module time_keeper
implicit none
integer :: start(8), now(8)
contains
subroutine startclock( )
implicit none
call date_and_time(values=start)
end subroutine startclock
subroutine elapsedtime_s( et_s )
implicit none
integer :: diffs(8)=0
real , intent(out):: et_s ! in seconds
call date_and_time(values=now)
! - Find the difference in times
diffs = now - start
! - This works only when the time is measured in a specific month
if (diffs(3) > 0) then
diffs(5) = 24*diffs(3) + diffs(5)
endif
et_s = diffs(5) * 3600 + diffs(6) * 60 + diffs(7) + 1e-3 * diffs(8)
end subroutine elapsedtime_s
end module time_keeper
program main
use time_keeper
implicit none
integer :: x=0, i
real :: et_s
call startclock()
do i = 1, 1e5
x = x + 1
end do
call elapsedtime_s( et_s )
write(*,*) et_s
end program main
请注意,time_keeper::elapsedtime_s
仅在测量时间在一个月内时有效。如果您希望测量结果也以月为单位,那么您可以扩展子例程。那应该很简单。
其他选项包括 time keeping library, system_clock
(see here). Reference for date_and_time
is here
发布的代码使用整数来获取系统的时钟频率。 system_clock
也可以使用实数变量来调用 return 的速率。我的怀疑现在通过评论交流得到证实,是整数是时钟速率的不准确表示,从而解释了在使用 system_clock
.
时观察到的不准确性
OP 报告通过使用时钟速率的实数变量解决了该问题。
我需要将现有的 Fortran 代码设置为 运行 并有时间限制(即 24 小时周期)。我正在尝试实现一个简单的 运行-time 计时,它测量 "real life" 时间(而不是 CPU 时间)代码是 运行ning 并执行适当的保存和终止例程。
由于这种检查经常发生,我不想实际得到一整天的时间并从中计算总数 hours/minutes。我更喜欢 CPU_TIME()
的内容并做一个简单的 (Current-Start)/3600
(我真的只需要几个小时的分辨率)。
我实际上尝试以最简单的方式实现 CPU_TIME()
并且它似乎工作了很短的时间,但显然随着时间的增加,有一个 "drift" 我最终 运行ning 比实际的时间限制略多,它终止了我的代码而没有保存 "checkpoint"。
除了尝试设置小时数的下限以尝试考虑 "drift",是否有更精确但简单的实现可以在几分钟的分辨率内获得正确的 运行 时间?
编辑:
我也尝试使用 system_clock
,但是实际时间和该例程的输出时间完全不符......我做错了什么?
INTEGER :: scount, & ! Starting "time"
ecount, & ! Ending "time"
rate ! number of clock ticks per second
call system_clock(scount,rate)
...
<CODE>
...
call system_clock(ecount)
timer_elapsed_time = real(ecount-scount,8)/real(rate,8)
write(*,*) "Calculated run time is ",timer_elapsed_time *3600," hours"
解决方案:在某些情况下,时钟频率可以是real
而不是integer
,比如我的情况。
这取决于您希望经过的时间测量的精确度。以下模块将允许您计算精确到毫秒的时间。
module time_keeper
implicit none
integer :: start(8), now(8)
contains
subroutine startclock( )
implicit none
call date_and_time(values=start)
end subroutine startclock
subroutine elapsedtime_s( et_s )
implicit none
integer :: diffs(8)=0
real , intent(out):: et_s ! in seconds
call date_and_time(values=now)
! - Find the difference in times
diffs = now - start
! - This works only when the time is measured in a specific month
if (diffs(3) > 0) then
diffs(5) = 24*diffs(3) + diffs(5)
endif
et_s = diffs(5) * 3600 + diffs(6) * 60 + diffs(7) + 1e-3 * diffs(8)
end subroutine elapsedtime_s
end module time_keeper
program main
use time_keeper
implicit none
integer :: x=0, i
real :: et_s
call startclock()
do i = 1, 1e5
x = x + 1
end do
call elapsedtime_s( et_s )
write(*,*) et_s
end program main
请注意,time_keeper::elapsedtime_s
仅在测量时间在一个月内时有效。如果您希望测量结果也以月为单位,那么您可以扩展子例程。那应该很简单。
其他选项包括 time keeping library, system_clock
(see here). Reference for date_and_time
is here
发布的代码使用整数来获取系统的时钟频率。 system_clock
也可以使用实数变量来调用 return 的速率。我的怀疑现在通过评论交流得到证实,是整数是时钟速率的不准确表示,从而解释了在使用 system_clock
.
OP 报告通过使用时钟速率的实数变量解决了该问题。