我需要设置一个现有的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
,例如我的情况。
发布的代码使用一个整数来获取系统的时钟速率。CCD_ 7也可以使用实数变量来返回速率。我的怀疑现在通过交换意见得到了证实,即整数是时钟速率的不准确表示,从而解释了在使用system_clock
时观察到的不准确。
OP报告通过使用时钟速率的实际变量来解决问题。
I取决于您希望经过时间测量的精确程度。以下模块将允许您计算精确到毫秒的时间。
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
才能工作。如果您希望测量也以月份为单位,那么您可以扩展子程序。这应该很简单。
其他选项包括计时库system_clock
(请参阅此处)。此处为date_and_time
的参考