Line data Source code
1 : !> \file mo_timer.f90
2 : !> \brief \copybrief mo_timer
3 : !> \details \copydetails mo_timer
4 :
5 : !> \brief Timing routines
6 : !> \details This module uses F90 cpu time routines to allowing setting of
7 : !! multiple CPU timers.
8 : !> \changelog
9 : !! - Matthias Cuntz, Aug. 2012
10 : !! - adapted to UFZ library, called mo_timer.f90
11 : !! - Matthias Cuntz, Jan. 2013
12 : !! - clear one or all timers
13 : !> \authors Matthias Cuntz - from timers.f (c) the Regents of the University of Californi
14 : !> \date Dec 2012
15 : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
16 : !! FORCES is released under the LGPLv3+ license \license_note
17 : module mo_timer
18 :
19 : ! -----------------------------------------------------------------------
20 :
21 : ! This module uses F90 cpu time routines to allowing setting of
22 : ! multiple CPU timers.
23 :
24 : ! -----------------------------------------------------------------------
25 :
26 : ! CVS:$Id: timers.f,v 1.2 2000/04/19 21:56:26 pwjones Exp $
27 :
28 : ! Copyright (c) 1997, 1998 the Regents of the University of
29 : ! California.
30 :
31 : ! This software and ancillary information (herein called software)
32 : ! called SCRIP is made available under the terms described here.
33 : ! The software has been approved for release with associated
34 : ! LA-CC Number 98-45.
35 :
36 : ! Unless otherwise indicated, this software has been authored
37 : ! by an employee or employees of the University of California,
38 : ! operator of the Los Alamos National Laboratory under Contract
39 : ! No. W-7405-ENG-36 with the U.S. Department of Energy. The U.S.
40 : ! Government has rights to use, reproduce, and distribute this
41 : ! software. The public may copy and use this software without
42 : ! charge, provided that this Notice and any statement of authorship
43 : ! are reproduced on all copies. Neither the Government nor the
44 : ! University makes any warranty, express or implied, or assumes
45 : ! any liability or responsibility for the use of this software.
46 :
47 : ! If software is modified to produce derivative works, such modified
48 : ! software should be clearly marked, so as not to confuse it with
49 : ! the version available from Los Alamos National Laboratory.
50 :
51 : ! -----------------------------------------------------------------------
52 :
53 : use mo_kind, only : i4, sp
54 :
55 : implicit none
56 :
57 : private
58 :
59 : ! Variables
60 : public :: max_timers ! max number of timers allowed
61 : public :: cycles_max ! max value of clock allowed by system
62 : public :: clock_rate ! clock_rate in seconds for each cycle
63 : public :: cycles1 ! cycle number at start for each timer
64 : public :: cycles2 ! cycle number at stop for each timer
65 : public :: cputime ! accumulated cpu time in each timer
66 : public :: status ! timer status string
67 : ! Routines
68 : public :: timer_check ! Checks a given timer
69 : public :: timer_clear ! Clears (a given) timer(s)
70 : public :: timer_get ! Returns the result of a given timer
71 : public :: timer_print ! Prints the accumulated cpu time of a given timer
72 : public :: timer_start ! Stops a given timer
73 : public :: timer_stop ! Starts a given timer
74 : public :: timers_init ! Initialises the module
75 :
76 : ! Save variables
77 : !> max number of timers allowed
78 : integer(i4), parameter :: max_timers = 500
79 : !> max value of clock allowed by system
80 : integer(i4), save :: cycles_max
81 : !> clock_rate in seconds for each cycle
82 : real(sp), save :: clock_rate
83 : !> cycle number at start for each timer
84 : integer(i4), dimension(max_timers), save :: cycles1
85 : !> cycle number at stop for each timer
86 : integer(i4), dimension(max_timers), save :: cycles2
87 : !> accumulated cpu time in each timer
88 : real(sp), dimension(max_timers), save :: cputime
89 : !> timer status string
90 : character(len = 8), dimension(max_timers), save :: status
91 :
92 : ! -----------------------------------------------------------------------
93 :
94 : contains
95 :
96 : ! ------------------------------------------------------------------
97 :
98 : !> \brief Check a timer
99 :
100 : !> \details
101 : !! This routine checks a given timer. This is primarily used to
102 : !! periodically accumulate time in the timer to prevent timer cycles
103 : !! from wrapping around max_cycles.
104 : !!
105 : !! \b Example
106 : !!
107 : !! Check timer 3
108 : !! \code{.f90}
109 : !! call timer_check(3)
110 : !! \endcode
111 :
112 : !> \param[in] "integer(i4) :: timer" timer number
113 :
114 : !> \author Matthias Cuntz
115 : !> \date Aug 2012
116 :
117 0 : subroutine timer_check(timer)
118 :
119 : implicit none
120 :
121 : integer(i4), intent(in) :: timer ! timer number
122 :
123 0 : if (status(timer) .eq. 'running') then
124 0 : call timer_stop (timer)
125 0 : call timer_start(timer)
126 : end if
127 :
128 0 : end subroutine timer_check
129 :
130 : ! ------------------------------------------------------------------
131 :
132 : !> \brief Reset a timer
133 :
134 : !> \details
135 : !! This routine resets a given timer or all timers to 0.
136 : !!
137 : !! \b Example
138 : !!
139 : !! ! Clear timer 3
140 : !! \code{.f90}
141 : !! call timer_clear(3)
142 : !! \endcode
143 : !!
144 : !! Clear all timers
145 : !! \code{.f90}
146 : !! call timer_clear()
147 : !! \endcode
148 :
149 : !> \param[in] "integer(i4), optional :: timer" timer number if given.\n
150 : !! If missing, all timers will be reset.
151 :
152 : !> \author Matthias Cuntz
153 : !> \date Aug 2012
154 :
155 501 : subroutine timer_clear(timer)
156 :
157 : implicit none
158 :
159 : integer(i4), intent(in), optional :: timer ! timer number
160 :
161 501 : if (present(timer)) then
162 501 : cputime(timer) = 0.0_sp ! clear the timer
163 : else
164 0 : cputime(:) = 0.0_sp ! clear all timers
165 : end if
166 :
167 0 : end subroutine timer_clear
168 :
169 : ! ------------------------------------------------------------------
170 :
171 : !> \brief Return a timer
172 :
173 : !> \details This routine returns the result of a given timer. This can be
174 : !! called instead of timer_print so that the calling routine can
175 : !! print it in desired format.
176 : !!
177 : !! \b Example
178 : !!
179 : !! Return timer 3
180 : !! \code{.f90}
181 : !! call timer_get(3)
182 : !! \endcode
183 :
184 : !> \param[in] "integer(i4) :: timer" timer number
185 :
186 : !> \author Matthias Cuntz
187 : !> \date Aug 2012
188 :
189 503 : function timer_get(timer)
190 :
191 : implicit none
192 :
193 : integer(i4), intent(in) :: timer ! timer number
194 :
195 : real(sp) :: timer_get ! accumulated cputime in given timer
196 :
197 503 : if (status(timer) .eq. 'stopped') then
198 503 : timer_get = cputime(timer)
199 : else
200 0 : call timer_stop(timer)
201 0 : timer_get = cputime(timer)
202 0 : call timer_start(timer)
203 : end if
204 :
205 501 : end function timer_get
206 :
207 : ! ------------------------------------------------------------------
208 :
209 : !> \brief Print a timer
210 :
211 : !> \details This routine prints the accumulated cpu time in given timer.
212 : !!
213 : !! \b Example
214 : !!
215 : !! Prints timer 3
216 : !! \code{.f90}
217 : !! call timer_print(3)
218 : !! \endcode
219 :
220 : !> \param[in] "integer(i4) :: timer" timer number
221 :
222 : !> \author Matthias Cuntz
223 : !> \date Aug 2012
224 :
225 0 : subroutine timer_print(timer)
226 :
227 : implicit none
228 :
229 : integer(i4), intent(in) :: timer ! timer number
230 :
231 : !---
232 : !--- print the cputime accumulated for timer
233 : !--- make sure timer is stopped
234 : !---
235 :
236 0 : if (status(timer) .eq. 'stopped') then
237 : write(*, "(' CPU time for timer',i3,':',1p,e16.8)") &
238 0 : timer, cputime(timer)
239 : else
240 0 : call timer_stop(timer)
241 : write(*, "(' CPU time for timer',i3,':',1p,e16.8)") &
242 0 : timer, cputime(timer)
243 0 : call timer_start(timer)
244 : end if
245 :
246 503 : end subroutine timer_print
247 :
248 : ! ------------------------------------------------------------------
249 :
250 : !> \brief Start a timer
251 :
252 : !> \details This routine starts a given timer.
253 : !!
254 : !! \b Example
255 : !!
256 : !! Start timer 3
257 : !! \code{.f90}
258 : !! call timer_start(3)
259 : !! \endcode
260 :
261 : !> \param[in] "integer(i4) :: timer" timer number
262 :
263 : !> \author Matthias Cuntz
264 : !> \date Aug 2012
265 :
266 2 : subroutine timer_start(timer)
267 :
268 : implicit none
269 :
270 : integer(i4), intent(in) :: timer ! timer number
271 :
272 : !---
273 : !--- Start the timer and change timer status.
274 : !---
275 :
276 2 : if (status(timer) .eq. 'stopped') then
277 2 : call system_clock(count = cycles1(timer))
278 2 : status(timer) = 'running'
279 : end if
280 :
281 0 : end subroutine timer_start
282 :
283 : ! ------------------------------------------------------------------
284 :
285 : !> \brief Stop a timer
286 :
287 : !> \details This routine stops a given timer.
288 : !! \b Example
289 : !!
290 : !! Stop timer 3
291 : !! \code{.f90}
292 : !! call timer_stop(3)
293 : !! \endcode
294 :
295 : !> \param[in] "integer(i4) :: timer" timer number
296 :
297 : !> \author Matthias Cuntz
298 : !> \date Aug 2012
299 :
300 2 : subroutine timer_stop(timer)
301 :
302 : implicit none
303 :
304 : integer(i4), intent(in) :: timer ! timer number
305 :
306 2 : if (status(timer) .eq. 'running') then
307 :
308 : !---
309 : !--- Stop the desired timer.
310 : !---
311 :
312 2 : call system_clock(count = cycles2(timer))
313 :
314 : !---
315 : !--- check and correct for cycle wrapping
316 : !---
317 :
318 2 : if (cycles2(timer) .ge. cycles1(timer)) then
319 : cputime(timer) = cputime(timer) + clock_rate * &
320 2 : (cycles2(timer) - cycles1(timer))
321 : else
322 : cputime(timer) = cputime(timer) + clock_rate * &
323 0 : (cycles2(timer) - cycles1(timer) + cycles_max)
324 : end if
325 :
326 : !---
327 : !--- Change timer status.
328 : !---
329 :
330 2 : status(timer) = 'stopped'
331 :
332 : end if
333 :
334 2 : end subroutine timer_stop
335 :
336 : !-----------------------------------------------------------------------
337 :
338 : ! This routine initializes some machine parameters necessary for
339 : ! computing cpu time from F90 intrinsics.
340 :
341 : ! ------------------------------------------------------------------
342 :
343 : !> \brief Initialise timer module
344 :
345 : !> \details This routine initializes some machine parameters necessary for
346 : !! computing cpu time from F90 intrinsics.
347 : !!
348 : !! \b Example
349 : !!
350 : !! Initialize timers (before running timers)
351 : !! \code{.f90}
352 : !! call timers_init()
353 : !! \endcode
354 :
355 : !> \author Matthias Cuntz
356 : !> \date Aug 2012
357 :
358 1 : subroutine timers_init
359 :
360 : implicit none
361 :
362 : integer(i4) :: cycles ! count rate return by sys_clock
363 :
364 : !---
365 : !--- Initialize timer arrays and clock_rate.
366 : !---
367 :
368 1 : clock_rate = 0.0_sp
369 1 : cycles1(:) = 0
370 1 : cycles2(:) = 0
371 1 : cputime(:) = 0.0_sp
372 501 : status(:) = 'stopped'
373 :
374 : !---
375 : !--- Call F90 intrinsic system_clock to determine clock rate
376 : !--- and maximum cycles. If no clock available, print message.
377 : !---
378 :
379 1 : call system_clock(count_rate = cycles, count_max = cycles_max)
380 :
381 1 : if (cycles /= 0) then
382 1 : clock_rate = 1.0_sp / real(cycles)
383 : else
384 0 : clock_rate = 0.0_sp
385 0 : print *, '--- No system clock available ---'
386 : end if
387 :
388 2 : end subroutine timers_init
389 :
390 : end module mo_timer
|