f2k  Reference documentation for version 0.0
timer.f90
Go to the documentation of this file.
1 !----------------------------------------------------------------------------------------
2 !
3 ! This file is part of f2k.
4 !
5 ! Copyright (C) 2016-2017 by the f2k authors
6 !
7 ! The f2k code is free software;
8 ! You can use it, redistribute it, and/or modify it under the terms
9 ! of the GNU General Public License as published by the Free Software Foundation;
10 ! either version 3 of the License, or (at your option) any later version.
11 ! The full text of the license can be found in the file LICENSE at
12 ! the top level of the f2k distribution.
13 !
14 !----------------------------------------------------------------------------------------
15 
18 
19 !----------------------------------------------------------------------------------------
21 
23 
24 module f2k_timer
25 
26  implicit none
27 
28  private
29 
30  !----------------------------------------------------------------------------------------
31  ! Internal definitions:
32 
33  integer, private, parameter :: allocated_num_loops = 50 ! number of elements to allocate temporarily arrays. If length exceeds this number then another chunk of this length is allocated.
34 
35  !----------------------------------------------------------------------------------------
43  type :: timer
44 
45  real ( kind=8 ), public :: start_time
46  real ( kind=8 ), public :: end_time
47 
48  integer ( kind=4 ), public :: number_loops
49 
50  real ( kind=8 ), public, allocatable, dimension(:) :: loop_times
51 
52  real ( kind=8 ), private :: internal_start_time
53  real ( kind=8 ), private :: internal_end_time
54 
55  contains
56 
57  procedure, public :: start => timer_start
58  procedure, public :: stop => timer_stop
59  procedure, public :: loop => timer_loop
60  procedure, public :: average => timer_average
61  procedure, public :: variance => timer_variance
62  procedure, public :: elapsed_time => timer_elapsed
63  procedure, public :: reset => timer_reset
64  procedure, public :: wait => timer_wait
65  procedure, public :: time => timer_time
66 
67  end type timer
68 
69  !----------------------------------------------------------------------------------------
70  ! public definitions:
71  public :: timer
72 
73  !----------------------------------------------------------------------------------------
74 
75 contains
76 
77  ! ---------------------------------------------------------------------------------------------
79  subroutine timer_start( self )
80 
81  implicit none
82 
83  class( timer ) :: self
84 
85  ! first reset the timer:
86  call self%reset()
87  ! then start the timer:
88  self%start_time = self%time()
89 
90  end subroutine timer_start
91 
92  ! ---------------------------------------------------------------------------------------------
94  subroutine timer_stop( self )
95 
96  implicit none
97 
98  class( timer ) :: self
99 
100  ! stop the timer:
101  self%end_time = self%time()
102 
103  end subroutine timer_stop
104 
105  ! ---------------------------------------------------------------------------------------------
107  subroutine timer_loop( self )
108 
109  implicit none
110 
111  class( timer ) :: self
112 
113  integer ( kind=4 ) :: temp_size, ind
114  real ( kind=8 ), allocatable, dimension(:) :: temp_loop_times
115 
116  ! take the time:
117  self%internal_end_time = self%time()
118  ! increase by one the number of loops:
119  self%number_loops = self%number_loops +1
120  ! check the allocation of the loop array:
121  if ( .not. allocated( self%loop_times ) ) then
122  allocate( self%loop_times(allocated_num_loops ) )
123  self%loop_times = 0.0d0
124  end if
125  ! get the length of the loop array:
126  temp_size = size(self%loop_times)
127  ! reallocate the loop array if needed:
128  if ( self%number_loops > temp_size ) then
129  ! allocate a temporary array:
130  allocate( temp_loop_times(temp_size) )
131  ! copy the timing array on the temporary one:
132  temp_loop_times = self%loop_times
133  ! deallocate the loop array and reallocate it:
134  deallocate( self%loop_times )
135  allocate( self%loop_times( (self%number_loops/allocated_num_loops+1)*allocated_num_loops ) )
136  self%loop_times = 0.0d0
137  ! copy the time data:
138  do ind=1, self%number_loops-1
139  self%loop_times(ind) = temp_loop_times(ind)
140  end do
141  end if
142  ! store the time:
143  if ( self%number_loops==1 ) then
144  self%loop_times(self%number_loops) = self%internal_end_time -self%start_time
145  else
146  self%loop_times(self%number_loops) = self%internal_end_time -self%internal_start_time
147  end if
148  ! restart the timer:
149  self%internal_start_time = self%time()
150 
151  end subroutine timer_loop
152 
153  ! ---------------------------------------------------------------------------------------------
155  function timer_average( self )
156 
157  implicit none
158 
159  class( timer ) :: self
160  real ( kind=8 ) :: timer_average
161 
162  integer ( kind=4 ) :: ind
163 
164  ! initialize:
165  timer_average = 0.0d+0
166  ! accumulate time measurements:
167  do ind=1, self%number_loops
168  timer_average = timer_average +self%loop_times(ind)
169  end do
170  ! compute and return the average:
171  timer_average = timer_average/REAL(self%number_loops)
172 
173  end function timer_average
174 
175  ! ---------------------------------------------------------------------------------------------
177  function timer_variance( self )
178 
179  implicit none
180 
181  class( timer ) :: self
182  real ( kind=8 ) :: timer_variance
183 
184  real ( kind=8 ) :: average_time
185  integer ( kind=4 ) :: ind
186 
187  ! initialize:
188  timer_variance = 0.0d+0
189  ! compute the variance:
190  if ( self%number_loops>1 ) then
191  average_time = self%average()
192  do ind=1, self%number_loops
193  timer_variance = timer_variance +( self%loop_times(ind) -average_time )**2
194  end do
195  timer_variance = sqrt( timer_variance/REAL(self%number_loops-1) )
196  end if
197 
198  end function timer_variance
199 
200  ! ---------------------------------------------------------------------------------------------
202  function timer_elapsed( self )
203 
204  implicit none
205 
206  class(timer) :: self
207  real ( kind=8 ) :: timer_elapsed
208 
209  timer_elapsed = self%end_time -self%start_time
210 
211  end function timer_elapsed
212 
213  ! ---------------------------------------------------------------------------------------------
215  subroutine timer_reset( self )
216 
217  implicit none
218 
219  class(timer) :: self
220 
221  self%start_time = 0.0d+0
222  self%end_time = 0.0d+0
223 
224  self%number_loops = 0
225 
226  self%internal_start_time = 0.0d+0
227  self%internal_end_time = 0.0d+0
228 
229  if ( allocated( self%loop_times ) ) deallocate( self%loop_times )
230 
231  end subroutine timer_reset
232 
233  ! ---------------------------------------------------------------------------------------------
235  subroutine timer_wait( self, time )
236 
237  implicit none
238 
239  class( timer ) :: self
240  real ( kind=8 ), intent(in) :: time
241 
242  real( kind=8 ) :: start_time, elapsed_time
243 
244  start_time = self%time()
245  do
246  elapsed_time = self%time() -start_time
247  if ( elapsed_time > time ) return
248  end do
249 
250  end subroutine timer_wait
251 
252  ! ---------------------------------------------------------------------------------------------
254  function timer_time( self )
255 
256  implicit none
257 
258  class(timer) :: self
259  real ( kind=8 ) :: timer_time
260 
261  call cpu_time(timer_time)
262 
263  end function timer_time
264 
265  ! ---------------------------------------------------------------------------------------------
266 
267 end module f2k_timer
This module contains a quality timer class to benchmark applications.
Definition: timer.f90:24