我需要设置一个现有的Fortran代码,使其有时间限制(即24小时周期)运行。我正在尝试实现一个简单的运行时计时,该计时可测量代码正在运行的“实际时间”(而不是CPU时间),并执行适当的保存和终止例程。
由于这种检查经常发生,因此我不想真正获得整个白天的时间并从中计算出总的小时/分钟。我更喜欢CPU_TIME()
上的内容,并做一个简单的(Current-Start)/3600
(我真的只需要几个小时的时间)。
我实际上尝试过以最简单的方式实现CPU_TIME()
,它似乎可以工作很短的时间,但是显然随着时间的增加,出现了“漂移”现象,并且我最终运行的时间比实际时间略多限制,它终止了我的代码而没有保存“检查点”。
除了尝试设置小时数下限以解决“漂移”之外,还有没有更精确,更简单的实现方案来在几分钟内获得正确的运行时间?
编辑:
我也尝试过使用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
。
答案 0 :(得分:2)
发布的代码使用整数来获取系统的时钟频率。也可以使用实数变量调用system_clock
以返回费率。我的怀疑(现在通过交流交换意见得到了证实)是整数是时钟速率的不正确表示,从而解释了使用system_clock
时观察到的不准确性。
OP报告通过使用实数变量作为时钟速率来解决此问题。
答案 1 :(得分:1)
我取决于您希望经过的时间测量的精确度。以下模块将允许您计算时间,精确到毫秒。
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
(请参阅here)。 date_and_time
的引用是here