It is important to consider the precision of the available timers and not just their reported ticks.
"Count_Rate" is merely a scaler for the number of reported ticks per second, but does not guarantee that the precision of the timer is to the nearest tick.
This is more obvious with CPU_TIME, where the elapsed cpu_time is typically updated only 64 times per second.
In gFortran on windows, this reported clock rate varies with kind and also the processor and possibly O/S.
I report what precision is being achieved with the following code. Hopefully it may be of interest.
subroutine report_timer_precision
!
! USE OMP_Variables
!
! checks the precision of the following timers in use
! CPU_Time (CPU) ! Fortran intrinsic
! System_Clock ! Fortran intrinsic
! omp_get_wtime (wtime) ! OMP Library
! QueryPerformance_tick ! WINAPI library
! QueryPerformance_sec ! my wrapper
!
! precision is minimum time between change of value
!
integer*4 k,n
real*8 timer_precision, timer_seconds, next_seconds, dt
integer*8 clock_precision, clock_tick, next_tick
!
real*8, external :: omp_get_wtick
real*8, external :: omp_get_wtime
integer*8, external :: system_clock_rate
integer*8, external :: system_clock_tick
integer*8, external :: QueryPerformance_rate
integer*8, external :: QueryPerformance_tick
real*8, external :: QueryPerformance_sec
!
call report_text ( '>> call report_timer_precision',0)
!
write ( *,2000)
write (98,2000)
2000 format (/ &
' Timer Precision Report'/ &
' This routine checks the accuracy of the timers available'/ &
' the accuracy is the minimum time for a change of reported value'/ &
' this accuracy differs from the resolution of tick values reported'/ &
' the number of call cycles between change of value is also reported'/ )
!
! test precision of omp_get_wtime
timer_precision = omp_get_wtick () ; timer_precision = 1./timer_precision
timer_seconds = omp_get_wtime ()
k = -2 ; n = 0
do
n = n+1
next_seconds = omp_get_wtime () ! call to timer
if ( next_seconds == timer_seconds ) cycle
k = k+1
if (k > 0) exit
timer_seconds = next_seconds
n = 0
end do
dt = next_seconds-timer_seconds ! minimum time between ticks
write ( *,11) 'omp_get_wtime rate = ', timer_precision,' ticks per second'
write ( *,11) 'omp_get_wtime acc = ', dt,' seconds : ', n,' cycles'
write (98,11) 'omp_get_wtime rate = ', timer_precision,' ticks per second'
write (98,11) 'omp_get_wtime acc = ', dt,' seconds : ', n,' cycles'
11 format ( 1x,a,es12.3,a,i0,a)
12 format ( 1x,a,i12,a,i0,a)
!
! compare to precision of SYSTEM_CLOCK
clock_precision = system_clock_rate ()
clock_tick = system_clock_tick ()
k = -2 ; n = 0
do
n = n+1
next_tick = system_clock_tick () ! call to timer
if ( next_tick == clock_tick ) cycle
k = k+1
if (k > 0) exit
clock_tick = next_tick
n = 0
end do
dt = dble(next_tick-clock_tick)/dble(clock_precision) ! minimum time between ticks
write ( *,12) 'system_clock_rate = ', clock_precision,' ticks per second'
write ( *,11) 'system_clock_tick acc = ', dt,' seconds : ', n,' cycles'
write (98,12) 'system_clock_rate = ', clock_precision,' ticks per second'
write (98,11) 'system_clock_tick acc = ', dt,' seconds : ', n,' cycles'
!
! compare to precision of QueryPerformance
clock_precision = QueryPerformance_rate ()
clock_tick = QueryPerformance_tick ()
k = -2 ; n = 0
do
n = n+1
next_tick = QueryPerformance_tick () ! call to timer
if ( next_tick == clock_tick ) cycle
k = k+1
if (k > 0) exit
clock_tick = next_tick
n = 0
end do
dt = dble(next_tick-clock_tick)/dble(clock_precision) ! minimum time between ticks
write ( *,12) 'QueryPerformance_rate =', clock_precision,' ticks per second'
write ( *,11) 'QueryPerformance_tick =', dt,' seconds : ', n,' cycles'
write (98,12) 'QueryPerformance_rate =', clock_precision,' ticks per second'
write (98,11) 'QueryPerformance_tick =', dt,' seconds : ', n,' cycles'
!
! compare to precision of QueryPerformance_sec
timer_seconds = QueryPerformance_sec ()
k = -2 ; n = 0
do
n = n+1
next_seconds = QueryPerformance_sec () ! call to timer
if ( next_seconds == timer_seconds ) cycle
k = k+1
if (k > 0) exit
timer_seconds = next_seconds
n = 0
end do
dt = next_seconds-timer_seconds ! minimum time between ticks
write ( *,11) 'QueryPerformance_sec =', dt,' seconds : ', n,' cycles'
write (98,11) 'QueryPerformance_sec =', dt,' seconds : ', n,' cycles'
!
! test precision of CPU_Time
call CPU_Time (timer_seconds)
k = -2 ; n = 0
do
n = n+1
call CPU_Time (next_seconds) ! call to timer
if ( next_seconds == timer_seconds ) cycle
k = k+1
if (k > 0) exit
timer_seconds = next_seconds
n = 0
end do
dt = next_seconds-timer_seconds ! minimum time between ticks
write ( *,11) 'CPU_Time accuracy =', dt,' seconds : ', n,' cycles'
write (98,11) 'CPU_Time accuracy =', dt,' seconds : ', n,' cycles'
!
write ( *,13) 'NOTE : precision is minimum time between change of value'
write (98,13) 'NOTE : precision is minimum time between change of value'
13 format (1x,a/1x)
!
end subroutine report_timer_precision