1

I am required to set up an existing Fortran code to run with a time limit (i.e. 24 hour cycles). I'm trying to implement a simple run-time timing which measures the "real life" time (not CPU time) which the code was running and executes a proper save and terminate routine. Since this check happens very often, I don't want to actually get the whole day-time and calculate the total hours/minutes from that. I would much prefer something on the lines of CPU_TIME() and do a simple (Current-Start)/3600 (I really only need hours resolution).

I actually tried implementing the CPU_TIME() in the simplest way and it seemed to work for short times, but apparently as the time increases, there is a "drift" and I end up running slightly more than the actual time limitation, which terminates my code without saving a "checkpoint". Other then trying to set a lower limit on the hours to try to account for the "drift", is there a more precise, yet simple implementation that gets the correct run-time within a resolution of few minutes?

Edit: I tried using system_clock as well, but the actual time and the output time from this routine is completely off... What am I doing wrong?

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"

Solution: The clock rate can be real and not integer in some cases, such as my case.

2 Answers2

2

The code posted uses an integer for getting the system's clock rate. system_clock can also be called using a real variable to return the rate. My suspicion, validated now by an exchange of comments, was that the integer was an inaccurate representation of the clock rate, thereby accounting for the inaccuracy observed in using system_clock.

OP reports fixing the problem by using a real variable for the clock rate.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
1

I depends on how precise you want the elapsed time measure to be. The following module will allow you to calculate time up to a precision of milliseconds.

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

Note that the time_keeper::elapsedtime_s works only if the time is measured within a month. If you want the measurements to factor in months as well then you can extend the subroutine. That should be simple.

Other options include a time keeping library, system_clock (see here). Reference for date_and_time is here

newkid
  • 1,368
  • 1
  • 11
  • 27
  • I appreciate the the answer, this is what I was thinking of doing in the beginning, however I want to avoid this, if possible (simply due to the amount of times this is called). If I can't solve it any other way, this is my fall-back plan. Thanks. Also, I'm not sure why `system_clock` did not work properly for me... – TheWhitestOfFangs Jan 19 '19 at 19:34
  • Unfortunately, these seem to be your only options. The other strategy is perhaps use `bash` to track time ... then again this isn't very straight forward. – newkid Jan 19 '19 at 21:24