Line data Source code
1 : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 :
3 : module ice_timers
4 :
5 : ! This module contains routine for supporting multiple CPU timers
6 : ! and accumulates time for each individual block and node (task).
7 : !
8 : ! 2005: Adapted from POP by William Lipscomb
9 : ! Replaced 'stdout' by 'nu_diag'
10 :
11 : use ice_kinds_mod
12 : use ice_constants, only: c0, c1
13 : use ice_domain, only: nblocks, distrb_info
14 : use ice_global_reductions, only: global_minval, global_maxval, global_sum
15 : use ice_exit, only: abort_ice
16 : use ice_fileunits, only: nu_diag
17 : use ice_communicate, only: my_task, master_task
18 : use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
19 : use icepack_intfc, only: icepack_query_parameters
20 :
21 : implicit none
22 : private
23 :
24 : public :: init_ice_timers, &
25 : get_ice_timer, & ! LCOV_EXCL_LINE
26 : ice_timer_clear, & ! LCOV_EXCL_LINE
27 : ice_timer_start, & ! LCOV_EXCL_LINE
28 : ice_timer_stop, & ! LCOV_EXCL_LINE
29 : ice_timer_print, & ! LCOV_EXCL_LINE
30 : ice_timer_print_all, & ! LCOV_EXCL_LINE
31 : ice_timer_check
32 :
33 : logical(log_kind), public :: &
34 : timer_stats ! controls printing of timer statistics
35 :
36 : !-----------------------------------------------------------------------
37 : ! public timers
38 : !-----------------------------------------------------------------------
39 :
40 : integer (int_kind), public :: &
41 : timer_total, &! total time ! LCOV_EXCL_LINE
42 : timer_step, &! time stepping ! LCOV_EXCL_LINE
43 : timer_dynamics, &! dynamics ! LCOV_EXCL_LINE
44 : timer_advect, &! horizontal advection ! LCOV_EXCL_LINE
45 : timer_column, &! column ! LCOV_EXCL_LINE
46 : timer_thermo, &! thermodynamics ! LCOV_EXCL_LINE
47 : timer_sw, &! radiative transfer ! LCOV_EXCL_LINE
48 : timer_ponds, &! melt ponds ! LCOV_EXCL_LINE
49 : timer_ridge, &! ridging ! LCOV_EXCL_LINE
50 : timer_catconv, &! category conversions ! LCOV_EXCL_LINE
51 : timer_fsd, &! floe size distribution ! LCOV_EXCL_LINE
52 : timer_couple, &! coupling ! LCOV_EXCL_LINE
53 : timer_readwrite, &! read/write ! LCOV_EXCL_LINE
54 : timer_diags, &! diagnostics/history ! LCOV_EXCL_LINE
55 : timer_hist, &! diagnostics/history ! LCOV_EXCL_LINE
56 : timer_bound, &! boundary updates ! LCOV_EXCL_LINE
57 : timer_bundbound, &! boundary updates ! LCOV_EXCL_LINE
58 : timer_bgc, &! biogeochemistry ! LCOV_EXCL_LINE
59 : timer_forcing, &! forcing ! LCOV_EXCL_LINE
60 : timer_evp_1d, &! timer only loop ! LCOV_EXCL_LINE
61 : timer_evp_2d, &! timer including conversion 1d/2d ! LCOV_EXCL_LINE
62 : timer_updstate ! update state
63 : ! timer_updstate, &! update state
64 : ! timer_tmp1, &! for temporary timings ! LCOV_EXCL_LINE
65 : ! timer_tmp2, &! for temporary timings ! LCOV_EXCL_LINE
66 : ! timer_tmp3, &! for temporary timings ! LCOV_EXCL_LINE
67 : ! timer_tmp4, &! for temporary timings ! LCOV_EXCL_LINE
68 : ! timer_tmp5, &! for temporary timings ! LCOV_EXCL_LINE
69 : ! timer_tmp6, &! for temporary timings ! LCOV_EXCL_LINE
70 : ! timer_tmp7, &! for temporary timings ! LCOV_EXCL_LINE
71 : ! timer_tmp8, &! for temporary timings ! LCOV_EXCL_LINE
72 : ! timer_tmp9 ! for temporary timings
73 :
74 : !-----------------------------------------------------------------------
75 : !
76 : ! module variables
77 : !
78 : !-----------------------------------------------------------------------
79 :
80 : integer (int_kind), parameter :: &
81 : max_timers = 50 ! max number of timers
82 :
83 : type timer_data
84 : character (char_len) :: &
85 : name ! timer name
86 :
87 : logical (log_kind) :: &
88 : in_use, &! true if timer initialized ! LCOV_EXCL_LINE
89 : node_started ! true if any thread has started timer
90 :
91 : integer (int_kind) :: &
92 : num_blocks, &! number of blocks using this timer ! LCOV_EXCL_LINE
93 : num_nodes, &! number of nodes using this timer ! LCOV_EXCL_LINE
94 : num_starts, &! number of start requests ! LCOV_EXCL_LINE
95 : num_stops ! number of stop requests
96 :
97 : real (dbl_kind) :: &
98 : node_cycles1, &! cycle number at start for node timer ! LCOV_EXCL_LINE
99 : node_cycles2 ! cycle number at stop for node timer
100 :
101 : real (dbl_kind) :: &
102 : node_accum_time ! accumulated time for node timer
103 :
104 : logical (log_kind), dimension(:), pointer :: &
105 : block_started ! true if block timer started
106 :
107 : real (dbl_kind), dimension(:), pointer :: &
108 : block_cycles1, &! cycle number at start for block timers ! LCOV_EXCL_LINE
109 : block_cycles2 ! cycle number at stop for block timers
110 :
111 : real (dbl_kind), dimension(:), pointer :: &
112 : block_accum_time ! accumulated time for block timers
113 :
114 : end type
115 :
116 : type (timer_data), dimension(max_timers) :: &
117 : all_timers ! timer data for all timers
118 :
119 : integer (int_kind) :: &
120 : cycles_max ! max clock cycles allowed by system
121 :
122 : real (dbl_kind) :: &
123 : clock_rate ! clock rate in seconds for each cycle
124 :
125 : !***********************************************************************
126 :
127 : contains
128 :
129 : !***********************************************************************
130 :
131 1 : subroutine init_ice_timers
132 :
133 : ! This routine initializes machine parameters and timer structures
134 : ! for computing cpu time from F90 intrinsic timer functions.
135 :
136 : !-----------------------------------------------------------------------
137 : !
138 : ! local variables
139 : !
140 : !-----------------------------------------------------------------------
141 :
142 : integer (int_kind) :: &
143 : n, &! dummy loop counters ! LCOV_EXCL_LINE
144 : cycles ! count rate returned by sys_clock
145 :
146 : character(len=*), parameter :: subname = '(init_ice_timers)'
147 :
148 : !-----------------------------------------------------------------------
149 : !
150 : ! Call F90 intrinsic system_clock to determine clock rate
151 : ! and maximum cycles for single-processor runs. If no clock
152 : ! available, print message.
153 : !
154 : !-----------------------------------------------------------------------
155 :
156 1 : cycles = 0
157 :
158 1 : call system_clock(count_rate=cycles, count_max=cycles_max)
159 :
160 1 : if (cycles /= 0) then
161 1 : clock_rate = c1/real(cycles,kind=dbl_kind)
162 : else
163 0 : clock_rate = c0
164 0 : write(nu_diag,'(/,a33,/)') '--- No system clock available ---'
165 : endif
166 :
167 : !-----------------------------------------------------------------------
168 : !
169 : ! initialize timer structures
170 : !
171 : !-----------------------------------------------------------------------
172 :
173 51 : do n=1,max_timers
174 50 : all_timers(n)%name = 'unknown_timer_name'
175 :
176 50 : all_timers(n)%in_use = .false.
177 50 : all_timers(n)%node_started = .false.
178 :
179 50 : all_timers(n)%num_blocks = 0
180 50 : all_timers(n)%num_nodes = 0
181 50 : all_timers(n)%num_starts = 0
182 50 : all_timers(n)%num_stops = 0
183 50 : all_timers(n)%node_cycles1 = c0
184 50 : all_timers(n)%node_cycles2 = c0
185 :
186 50 : all_timers(n)%node_accum_time = c0
187 :
188 50 : nullify(all_timers(n)%block_started)
189 50 : nullify(all_timers(n)%block_cycles1)
190 50 : nullify(all_timers(n)%block_cycles2)
191 51 : nullify(all_timers(n)%block_accum_time)
192 : end do
193 :
194 1 : call get_ice_timer(timer_total, 'Total', nblocks,distrb_info%nprocs)
195 1 : call get_ice_timer(timer_step, 'TimeLoop', nblocks,distrb_info%nprocs)
196 1 : call get_ice_timer(timer_dynamics, 'Dynamics', nblocks,distrb_info%nprocs)
197 1 : call get_ice_timer(timer_advect, 'Advection',nblocks,distrb_info%nprocs)
198 1 : call get_ice_timer(timer_column, 'Column', nblocks,distrb_info%nprocs)
199 1 : call get_ice_timer(timer_thermo, 'Thermo', nblocks,distrb_info%nprocs)
200 1 : call get_ice_timer(timer_sw, 'Shortwave',nblocks,distrb_info%nprocs)
201 : ! call get_ice_timer(timer_ponds, 'Meltponds',nblocks,distrb_info%nprocs)
202 1 : call get_ice_timer(timer_ridge, 'Ridging', nblocks,distrb_info%nprocs)
203 : ! call get_ice_timer(timer_catconv, 'Cat Conv', nblocks,distrb_info%nprocs)
204 1 : call get_ice_timer(timer_fsd, 'FloeSize', nblocks,distrb_info%nprocs)
205 1 : call get_ice_timer(timer_couple, 'Coupling', nblocks,distrb_info%nprocs)
206 1 : call get_ice_timer(timer_readwrite,'ReadWrite',nblocks,distrb_info%nprocs)
207 1 : call get_ice_timer(timer_diags, 'Diags ',nblocks,distrb_info%nprocs)
208 1 : call get_ice_timer(timer_hist, 'History ',nblocks,distrb_info%nprocs)
209 1 : call get_ice_timer(timer_bound, 'Bound', nblocks,distrb_info%nprocs)
210 1 : call get_ice_timer(timer_bundbound,'Bundbound',nblocks,distrb_info%nprocs)
211 1 : call get_ice_timer(timer_bgc, 'BGC', nblocks,distrb_info%nprocs)
212 1 : call get_ice_timer(timer_forcing, 'Forcing', nblocks,distrb_info%nprocs)
213 1 : call get_ice_timer(timer_evp_1d, '1d-evp', nblocks,distrb_info%nprocs)
214 1 : call get_ice_timer(timer_evp_2d, '2d-evp', nblocks,distrb_info%nprocs)
215 1 : call get_ice_timer(timer_updstate, 'UpdState', nblocks,distrb_info%nprocs)
216 : ! call get_ice_timer(timer_tmp1, 'tmp1', nblocks,distrb_info%nprocs)
217 : ! call get_ice_timer(timer_tmp2, 'tmp2', nblocks,distrb_info%nprocs)
218 : ! call get_ice_timer(timer_tmp3, 'tmp3', nblocks,distrb_info%nprocs)
219 : ! call get_ice_timer(timer_tmp4, 'tmp4', nblocks,distrb_info%nprocs)
220 : ! call get_ice_timer(timer_tmp5, 'tmp5', nblocks,distrb_info%nprocs)
221 : ! call get_ice_timer(timer_tmp6, 'tmp6', nblocks,distrb_info%nprocs)
222 : ! call get_ice_timer(timer_tmp7, 'tmp7', nblocks,distrb_info%nprocs)
223 : ! call get_ice_timer(timer_tmp8, 'tmp8', nblocks,distrb_info%nprocs)
224 : ! call get_ice_timer(timer_tmp9, 'tmp9', nblocks,distrb_info%nprocs)
225 :
226 : !-----------------------------------------------------------------------
227 :
228 1 : end subroutine init_ice_timers
229 :
230 : !***********************************************************************
231 :
232 20 : subroutine get_ice_timer(timer_id, name_choice, num_blocks, num_nodes)
233 :
234 : ! This routine initializes a timer with a given name and returns a
235 : ! timer id.
236 :
237 : character (*), intent(in) :: &
238 : name_choice ! input name for this timer
239 :
240 : integer (int_kind), intent(in) :: &
241 : num_nodes, &! number of nodes(tasks) using this timer ! LCOV_EXCL_LINE
242 : num_blocks ! number of blocks using this timer
243 : ! (can be =1 if timer called outside
244 : ! threaded region)
245 :
246 : integer (int_kind), intent(out) :: &
247 : timer_id ! timer number assigned to this timer
248 :
249 : !-----------------------------------------------------------------------
250 : !
251 : ! local variables
252 : !
253 : !-----------------------------------------------------------------------
254 :
255 : integer (int_kind) :: &
256 : n, &! dummy loop index ! LCOV_EXCL_LINE
257 : srch_error ! error flag for search
258 :
259 : character(len=*), parameter :: subname = '(get_ice_timer)'
260 :
261 : !-----------------------------------------------------------------------
262 : !
263 : ! search for next free timer
264 : !
265 : !-----------------------------------------------------------------------
266 :
267 20 : srch_error = 1
268 :
269 210 : srch_loop: do n=1,max_timers
270 210 : if (.not. all_timers(n)%in_use) then
271 20 : srch_error = 0
272 20 : timer_id = n
273 :
274 20 : all_timers(n)%name = ' '
275 20 : all_timers(n)%name = name_choice
276 20 : all_timers(n)%in_use = .true.
277 20 : all_timers(n)%num_blocks = num_blocks
278 20 : all_timers(n)%num_nodes = num_nodes
279 :
280 : allocate(all_timers(n)%block_started (num_blocks), &
281 : all_timers(n)%block_cycles1 (num_blocks), & ! LCOV_EXCL_LINE
282 : all_timers(n)%block_cycles2 (num_blocks), & ! LCOV_EXCL_LINE
283 20 : all_timers(n)%block_accum_time(num_blocks))
284 :
285 40 : all_timers(n)%block_started = .false.
286 40 : all_timers(n)%block_cycles1 = c0
287 40 : all_timers(n)%block_cycles2 = c0
288 40 : all_timers(n)%block_accum_time = c0
289 :
290 20 : exit srch_loop
291 : endif
292 : end do srch_loop
293 :
294 20 : if (srch_error /= 0) &
295 0 : call abort_ice(subname//'ERROR: Exceeded maximum number of timers')
296 :
297 :
298 : !-----------------------------------------------------------------------
299 :
300 20 : end subroutine get_ice_timer
301 :
302 : !***********************************************************************
303 :
304 0 : subroutine ice_timer_clear(timer_id)
305 :
306 : ! This routine resets the time for a timer which has already been
307 : ! defined. NOTE: This routine must be called from outside a threaded
308 : ! region to ensure correct reset of block timers.
309 :
310 : integer (int_kind), intent(in) :: &
311 : timer_id ! timer number
312 :
313 : character(len=*), parameter :: subname = '(ice_timer_clear)'
314 :
315 : !-----------------------------------------------------------------------
316 : !
317 : ! if the timer has been defined, reset all times to 0
318 : ! otherwise exit with an error
319 : !
320 : !-----------------------------------------------------------------------
321 :
322 0 : if (all_timers(timer_id)%in_use) then
323 0 : all_timers(timer_id)%node_started = .false.
324 0 : all_timers(timer_id)%num_starts = 0
325 0 : all_timers(timer_id)%num_stops = 0
326 0 : all_timers(timer_id)%node_cycles1 = c0
327 0 : all_timers(timer_id)%node_cycles2 = c0
328 :
329 0 : all_timers(timer_id)%node_accum_time = c0
330 :
331 0 : all_timers(timer_id)%block_started(:) = .false.
332 0 : all_timers(timer_id)%block_cycles1(:) = c0
333 0 : all_timers(timer_id)%block_cycles2(:) = c0
334 0 : all_timers(timer_id)%block_accum_time(:) = c0
335 : else
336 0 : call abort_ice(subname//'ERROR: attempt to reset undefined timer')
337 :
338 : endif
339 :
340 : !-----------------------------------------------------------------------
341 :
342 0 : end subroutine ice_timer_clear
343 :
344 : !***********************************************************************
345 :
346 6609 : subroutine ice_timer_start(timer_id, block_id)
347 :
348 : ! This routine starts a given node timer if it has not already
349 : ! been started by another thread. If block information is available,
350 : ! the appropriate block timer is also started.
351 :
352 : integer (int_kind), intent(in) :: &
353 : timer_id ! timer number
354 :
355 : integer (int_kind), intent(in), optional :: &
356 : block_id ! optional block id for this block
357 : ! this must be the actual local address
358 : ! of the block in the distribution
359 : ! from which it is called
360 : ! (if timer called outside of block
361 : ! region, no block info required)
362 :
363 : integer (int_kind) :: &
364 : cycles ! count rate return by sys_clock
365 :
366 : character(len=*), parameter :: subname = '(ice_timer_start)'
367 :
368 : ! if (my_task == master_task) write(nu_diag,*) subname,trim(all_timers(timer_id)%name)
369 :
370 : !-----------------------------------------------------------------------
371 : !
372 : ! if timer is defined, start it up
373 : !
374 : !-----------------------------------------------------------------------
375 :
376 6609 : if (all_timers(timer_id)%in_use) then
377 :
378 : !***
379 : !*** if called from within a block loop, start block timers
380 : !***
381 :
382 6609 : if (present(block_id)) then
383 :
384 : !*** if block timer already started, stop it first
385 :
386 120 : if (all_timers(timer_id)%block_started(block_id)) &
387 0 : call ice_timer_stop(timer_id, block_id)
388 :
389 : !*** start block timer
390 :
391 120 : all_timers(timer_id)%block_started(block_id) = .true.
392 120 : call system_clock(count=cycles)
393 120 : all_timers(timer_id)%block_cycles1(block_id) = real(cycles,kind=dbl_kind)
394 :
395 : !*** start node timer if not already started by
396 : !*** another thread. if already started, keep track
397 : !*** of number of start requests in order to match
398 : !*** start and stop requests
399 :
400 : !$OMP CRITICAL
401 :
402 120 : if (.not. all_timers(timer_id)%node_started) then
403 120 : all_timers(timer_id)%node_started = .true.
404 120 : all_timers(timer_id)%num_starts = 1
405 120 : all_timers(timer_id)%num_stops = 0
406 120 : call system_clock(count=cycles)
407 120 : all_timers(timer_id)%node_cycles1 = real(cycles,kind=dbl_kind)
408 : else
409 : all_timers(timer_id)%num_starts = &
410 0 : all_timers(timer_id)%num_starts + 1
411 : endif
412 :
413 : !$OMP END CRITICAL
414 :
415 : !***
416 : !*** if called from outside a block loop, start node timer
417 : !***
418 :
419 : else
420 :
421 : !*** stop timer if already started
422 6489 : if (all_timers(timer_id)%node_started) &
423 0 : call ice_timer_stop(timer_id)
424 :
425 : !*** start node timer
426 :
427 6489 : all_timers(timer_id)%node_started = .true.
428 6489 : call system_clock(count=cycles)
429 6489 : all_timers(timer_id)%node_cycles1 = real(cycles,kind=dbl_kind)
430 :
431 : endif
432 : else
433 0 : call abort_ice(subname//'ERROR: attempt to start undefined timer')
434 :
435 : endif
436 :
437 : !-----------------------------------------------------------------------
438 :
439 6609 : end subroutine ice_timer_start
440 :
441 : !***********************************************************************
442 :
443 6609 : subroutine ice_timer_stop(timer_id, block_id)
444 :
445 : ! This routine stops a given node timer if appropriate. If block
446 : ! information is available the appropriate block timer is also stopped.
447 :
448 : integer (int_kind), intent(in) :: &
449 : timer_id ! timer number
450 :
451 : integer (int_kind), intent(in), optional :: &
452 : block_id ! optional block id for this block
453 : ! this must be the actual local address
454 : ! of the block in the distribution
455 : ! from which it is called
456 : ! (if timer called outside of block
457 : ! region, no block info required)
458 :
459 : !-----------------------------------------------------------------------
460 : !
461 : ! local variables
462 : !
463 : !-----------------------------------------------------------------------
464 :
465 : real (dbl_kind) :: &
466 : cycles1, cycles2 ! temps to hold cycle info before correction
467 :
468 : integer (int_kind) :: &
469 : cycles ! count rate returned by sys_clock
470 :
471 : character(len=*), parameter :: subname = '(ice_timer_stop)'
472 :
473 : ! if (my_task == master_task) write(nu_diag,*) subname,trim(all_timers(timer_id)%name)
474 :
475 : !-----------------------------------------------------------------------
476 : !
477 : ! get end cycles
478 : !
479 : !-----------------------------------------------------------------------
480 :
481 6609 : call system_clock(count=cycles)
482 6609 : cycles2 = real(cycles,kind=dbl_kind)
483 :
484 : !-----------------------------------------------------------------------
485 : !
486 : ! if timer is defined, stop it
487 : !
488 : !-----------------------------------------------------------------------
489 :
490 6609 : if (all_timers(timer_id)%in_use) then
491 :
492 : !***
493 : !*** if called from within a block loop, stop block timer
494 : !***
495 :
496 6609 : if (present(block_id)) then
497 :
498 120 : all_timers(timer_id)%block_started(block_id) = .false.
499 :
500 : !*** correct for cycle wraparound and accumulate time
501 :
502 120 : cycles1 = all_timers(timer_id)%block_cycles1(block_id)
503 120 : if (cycles2 >= cycles1) then
504 : all_timers(timer_id)%block_accum_time(block_id) = &
505 : all_timers(timer_id)%block_accum_time(block_id) + & ! LCOV_EXCL_LINE
506 120 : clock_rate*(cycles2 - cycles1)
507 : else
508 : all_timers(timer_id)%block_accum_time(block_id) = &
509 : all_timers(timer_id)%block_accum_time(block_id) + & ! LCOV_EXCL_LINE
510 0 : clock_rate*(cycles_max + cycles2 - cycles1)
511 : endif
512 :
513 : !*** stop node timer if number of requested stops
514 : !*** matches the number of starts (to avoid stopping
515 : !*** a node timer started by multiple threads)
516 :
517 120 : cycles1 = all_timers(timer_id)%node_cycles1
518 :
519 : !$OMP CRITICAL
520 :
521 : all_timers(timer_id)%num_stops = &
522 120 : all_timers(timer_id)%num_stops + 1
523 :
524 120 : if (all_timers(timer_id)%num_starts == &
525 : all_timers(timer_id)%num_stops) then
526 :
527 120 : all_timers(timer_id)%node_started = .false.
528 120 : if (cycles2 >= cycles1) then
529 : all_timers(timer_id)%node_accum_time = &
530 : all_timers(timer_id)%node_accum_time + & ! LCOV_EXCL_LINE
531 120 : clock_rate*(cycles2 - cycles1)
532 : else
533 : all_timers(timer_id)%node_accum_time = &
534 : all_timers(timer_id)%node_accum_time + & ! LCOV_EXCL_LINE
535 0 : clock_rate*(cycles_max + cycles2 - cycles1)
536 : endif
537 :
538 120 : all_timers(timer_id)%num_starts = 0
539 120 : all_timers(timer_id)%num_stops = 0
540 :
541 : endif
542 :
543 : !$OMP END CRITICAL
544 :
545 : !***
546 : !*** if called from outside a block loop, stop node timer
547 : !***
548 :
549 : else
550 :
551 : !*** correct for wraparound and accumulate time
552 :
553 6489 : all_timers(timer_id)%node_started = .false.
554 6489 : cycles1 = all_timers(timer_id)%node_cycles1
555 :
556 6489 : if (cycles2 >= cycles1) then
557 : all_timers(timer_id)%node_accum_time = &
558 : all_timers(timer_id)%node_accum_time + & ! LCOV_EXCL_LINE
559 6489 : clock_rate*(cycles2 - cycles1)
560 : else
561 : all_timers(timer_id)%node_accum_time = &
562 : all_timers(timer_id)%node_accum_time + & ! LCOV_EXCL_LINE
563 0 : clock_rate*(cycles_max + cycles2 - cycles1)
564 : endif
565 :
566 : endif
567 : else
568 0 : call abort_ice(subname//'ERROR: attempt to stop undefined timer')
569 :
570 : endif
571 :
572 : !-----------------------------------------------------------------------
573 :
574 6609 : end subroutine ice_timer_stop
575 :
576 : !***********************************************************************
577 :
578 20 : subroutine ice_timer_print(timer_id,stats)
579 :
580 : ! Prints the accumulated time for a given timer and optional
581 : ! statistics for that timer. It is assumed that this routine
582 : ! is called outside of a block loop.
583 :
584 : integer (int_kind), intent(in) :: &
585 : timer_id ! timer number
586 :
587 : logical (log_kind), intent(in), optional :: &
588 : stats ! if true, print statistics for node
589 : ! and block times for this timer
590 :
591 : !-----------------------------------------------------------------------
592 : !
593 : ! local variables
594 : !
595 : !-----------------------------------------------------------------------
596 :
597 : integer (int_kind) :: &
598 : n,icount ! dummy loop index and counter
599 :
600 : logical (log_kind) :: &
601 : lrestart_timer ! flag to restart timer if timer is running
602 : ! when this routine is called
603 :
604 : real (dbl_kind) :: &
605 : bignum, &! big number ! LCOV_EXCL_LINE
606 : local_time, &! temp space for holding local timer results ! LCOV_EXCL_LINE
607 : min_time, &! minimum accumulated time ! LCOV_EXCL_LINE
608 : max_time, &! maximum accumulated time ! LCOV_EXCL_LINE
609 : mean_time ! mean accumulated time
610 :
611 : character (41), parameter :: &
612 : timer_format = "('Timer ',i3,': ',a9,f11.2,' seconds')"
613 :
614 : character (49), parameter :: &
615 : stats_fmt1 = "(' Timer stats (node): min = ',f11.2,' seconds')",& ! LCOV_EXCL_LINE
616 : stats_fmt2 = "(' max = ',f11.2,' seconds')",& ! LCOV_EXCL_LINE
617 : stats_fmt3 = "(' mean= ',f11.2,' seconds')",& ! LCOV_EXCL_LINE
618 : stats_fmt4 = "(' Timer stats(block): min = ',f11.2,' seconds')"
619 :
620 : character(len=*), parameter :: subname = '(ice_timer_print)'
621 :
622 : !-----------------------------------------------------------------------
623 : !
624 : ! if timer has been defined, check to see whether it is currently
625 : ! running. If it is, stop the timer and print the info.
626 : !
627 : !-----------------------------------------------------------------------
628 :
629 20 : call icepack_query_parameters(bignum_out=bignum)
630 20 : call icepack_warnings_flush(nu_diag)
631 20 : if (icepack_warnings_aborted()) call abort_ice(error_message=subname, &
632 0 : file=__FILE__, line=__LINE__)
633 :
634 20 : if (all_timers(timer_id)%in_use) then
635 20 : if (all_timers(timer_id)%node_started) then
636 0 : call ice_timer_stop(timer_id)
637 0 : lrestart_timer = .true.
638 : else
639 20 : lrestart_timer = .false.
640 : endif
641 :
642 : !*** Find max node time and print that time as default timer
643 : !*** result
644 :
645 20 : if (my_task < all_timers(timer_id)%num_nodes) then
646 20 : local_time = all_timers(timer_id)%node_accum_time
647 : else
648 0 : local_time = c0
649 : endif
650 20 : max_time = global_maxval(local_time,distrb_info)
651 :
652 20 : if (my_task == master_task) then
653 20 : write (nu_diag,timer_format) timer_id, &
654 40 : trim(all_timers(timer_id)%name),max_time
655 : endif
656 :
657 20 : if (present(stats)) then
658 20 : if (stats) then
659 :
660 : !*** compute and print statistics for node timer
661 :
662 0 : min_time = global_minval(local_time,distrb_info)
663 : mean_time = global_sum(local_time,distrb_info)/ &
664 0 : real(all_timers(timer_id)%num_nodes,kind=dbl_kind)
665 0 : if (my_task == master_task) then
666 0 : write (nu_diag,stats_fmt1) min_time
667 0 : write (nu_diag,stats_fmt2) max_time
668 0 : write (nu_diag,stats_fmt3) mean_time
669 : endif
670 :
671 : !*** compute and print statistics for block timers
672 : !*** min block time
673 :
674 0 : local_time = bignum
675 0 : do n=1,all_timers(timer_id)%num_blocks
676 : local_time = min(local_time, &
677 0 : all_timers(timer_id)%block_accum_time(n))
678 : end do
679 0 : min_time = global_minval(local_time,distrb_info)
680 0 : if (min_time == bignum) min_time = c0
681 :
682 : !*** max block time
683 :
684 0 : local_time = -bignum
685 0 : do n=1,all_timers(timer_id)%num_blocks
686 : local_time = max(local_time, &
687 0 : all_timers(timer_id)%block_accum_time(n))
688 : end do
689 0 : max_time = global_maxval(local_time,distrb_info)
690 0 : if (max_time == -bignum) min_time = c0
691 :
692 : !*** mean block time
693 :
694 0 : local_time = c0
695 0 : do n=1,all_timers(timer_id)%num_blocks
696 : local_time = local_time + &
697 0 : all_timers(timer_id)%block_accum_time(n)
698 : end do
699 : icount = global_sum(all_timers(timer_id)%num_blocks, &
700 0 : distrb_info)
701 0 : if (icount > 0) mean_time=global_sum(local_time,distrb_info)&
702 0 : /real(icount,kind=dbl_kind)
703 :
704 0 : if (my_task == master_task) then
705 0 : write (nu_diag,stats_fmt4) min_time
706 0 : write (nu_diag,stats_fmt2) max_time
707 0 : write (nu_diag,stats_fmt3) mean_time
708 : endif
709 :
710 : endif
711 : endif
712 :
713 20 : if (lrestart_timer) call ice_timer_start(timer_id)
714 : else
715 0 : call abort_ice(subname//'ERROR: attempt to print undefined timer')
716 :
717 : endif
718 :
719 : !-----------------------------------------------------------------------
720 :
721 20 : end subroutine ice_timer_print
722 :
723 : !***********************************************************************
724 :
725 1 : subroutine ice_timer_print_all(stats)
726 :
727 : ! Prints the accumulated time for a all timers and optional
728 : ! statistics for that timer. It is assumed that this routine
729 : ! is called outside of a block loop.
730 :
731 : logical (log_kind), intent(in), optional :: &
732 : stats ! if true, print statistics for node
733 : ! and block times for this timer
734 :
735 : !-----------------------------------------------------------------------
736 : !
737 : ! local variables
738 : !
739 : !-----------------------------------------------------------------------
740 :
741 : integer (int_kind) :: n ! dummy loop index
742 :
743 : character(len=*), parameter :: subname = '(ice_timer_print_all)'
744 :
745 : !-----------------------------------------------------------------------
746 : !
747 : ! loop through timers anc call timer_print for each defined timer
748 : !
749 : !-----------------------------------------------------------------------
750 :
751 1 : if (my_task == master_task) then
752 1 : write(nu_diag,'(/,a19,/)') 'Timing information:'
753 : endif
754 :
755 51 : do n=1,max_timers
756 51 : if (all_timers(n)%in_use) then
757 20 : if (present(stats)) then
758 20 : call ice_timer_print(n,stats)
759 : else
760 0 : call ice_timer_print(n)
761 : endif
762 : endif
763 : end do
764 :
765 : !-----------------------------------------------------------------------
766 :
767 1 : end subroutine ice_timer_print_all
768 :
769 : !***********************************************************************
770 :
771 0 : subroutine ice_timer_check(timer_id,block_id)
772 :
773 : ! This routine checks a given timer by stopping and restarting the
774 : ! timer. This is primarily used to periodically accumulate time in
775 : ! the timer to prevent timer cycles from wrapping around max_cycles.
776 :
777 : integer (int_kind), intent(in) :: &
778 : timer_id ! timer number
779 :
780 : integer (int_kind), intent(in), optional :: &
781 : block_id ! optional block id for this block
782 : ! this must be the actual local address
783 : ! of the block in the distribution
784 : ! from which it is called
785 : ! (if timer called outside of block
786 : ! region, no block info required)
787 :
788 : character(len=*), parameter :: subname = '(ice_timer_check)'
789 :
790 : !-----------------------------------------------------------------------
791 : !
792 : ! stop and restart the requested timer
793 : !
794 : !-----------------------------------------------------------------------
795 :
796 0 : if (present(block_id)) then
797 0 : call ice_timer_stop (timer_id,block_id)
798 0 : call ice_timer_start(timer_id,block_id)
799 : else
800 0 : call ice_timer_stop (timer_id)
801 0 : call ice_timer_start(timer_id)
802 : endif
803 :
804 : !-----------------------------------------------------------------------
805 :
806 0 : end subroutine ice_timer_check
807 :
808 : !***********************************************************************
809 :
810 0 : end module ice_timers
811 :
812 : !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|