Oasis3-MCT
mod_oasis_timer.F90
Go to the documentation of this file.
1 !-----------------------------------------------------------------------
2 ! Copyright 2010, CERFACS, Toulouse, France.
3 ! Copyright 2010, DKRZ, Hamburg, Germany.
4 ! All rights reserved. Use is subject to OASIS4 license terms.
5 !-----------------------------------------------------------------------
6 !
7 ! !DESCRIPTION:
8 !
9 !> Performance timer methods
10 !
11 !> This is used to measure the time consumed in specific parts of the code.
12 !> Timers are defined by character strings that are stored in an internal datatype.
13 !
14 ! Available routines:
15 ! oasis_timer_init allocates timers
16 ! oasis_timer_start starts specific timer
17 ! oasis_timer_stop stops specific timer and sums up measured time intervals
18 ! oasis_timer_print root process prints all timers of all processes sharing
19 ! the same mpi communicator provided to oasis_timer_init
20 ! in addition it frees all memory allocated by timers
21 !
22 !
23 ! !REVISION HISTORY:
24 !
25 ! Date Programmer Description
26 ! ---------- ---------- -----------
27 ! 03.01.11 M. Hanke created (based on psmile_timer.F90 and
28 ! prismdrv_timer.F90 from SV and JL)
29 ! 20.09.11 T. Craig extended
30 ! 16.04.13 T. Craig use mpi comm from mod_oasis_data
31 !
32 !----------------------------------------------------------------------
33 !
34 ! $Id: oasis_timer.F90 2849 2011-01-05 08:14:13Z hanke $
35 ! $Author: hanke $
36 !
37 !----------------------------------------------------------------------
38 
40 
41  use mod_oasis_kinds
42  use mod_oasis_data
43  use mod_oasis_sys
44 
45  implicit none
46  private
47 
48  public oasis_timer_init
49  public oasis_timer_start
50  public oasis_timer_stop
51  public oasis_timer_print
52 
53  ! name of the application
54  character (len=ic_med) :: app_name
55 
56  ! name of the time statistics file
57  character (len=ic_med) :: file_name
58  character (len=ic_med) :: file_hold
59 
60  !> Storage for timer data
62  ! label of timer
63  character (len=ic_med) :: label
64  ! wall time values
65  double precision :: start_wtime, end_wtime
66  ! cpu time values
67  double precision :: start_ctime, end_ctime
68  ! is the timer running now
69  character(len=1) :: runflag
70  end type timer_details
71 
72  INTEGER :: mtimer
73  type(timer_details), POINTER :: timer(:)
74  DOUBLE PRECISION, POINTER :: sum_ctime(:) ! these values are not part of timer details
75  DOUBLE PRECISION, POINTER :: sum_wtime(:) ! because they are later used in an mpi call
76  INTEGER, POINTER :: timer_count(:) ! number of calls
77 
78  integer :: ntimer
79 
80  integer :: output_unit = 901
81  logical,save :: single_timer_header
82  character(len=1),parameter :: t_stopped = ' '
83  character(len=1),parameter :: t_running = '*'
84 
85  contains
86 
87 ! --------------------------------------------------------------------------------
88 
89 !> Initializes the timer methods, called once in an application
90 
91  subroutine oasis_timer_init (app, file, nt)
92 
93  implicit none
94 
95  character (len=*), intent (in) :: app !< name of application
96  character (len=*), intent (in) :: file !< output filename
97  integer , intent (in) :: nt !< number of timers
98 
99  integer :: ierror,n
100  character(len=*),parameter :: subname = '(oasis_timer_init)'
101 
102  app_name = trim(app)
103  file_hold = trim(file)
104 
105  mtimer = nt
106  ALLOCATE(timer(mtimer))
107  ALLOCATE(sum_ctime(mtimer))
108  ALLOCATE(sum_wtime(mtimer))
109  ALLOCATE(timer_count(mtimer))
110 
111  ntimer = 0
112  do n = 1,mtimer
113  timer(n)%label = ' '
114  timer(n)%start_wtime = 0
115  timer(n)%end_wtime = 0
116  timer(n)%start_ctime = 0
117  timer(n)%end_ctime = 0
118  timer(n)%runflag = t_stopped
119 
120  sum_wtime(n) = 0
121  sum_ctime(n) = 0
122  timer_count(n) = 0
123  enddo
124 
125  single_timer_header = .false.
126 
127  end subroutine oasis_timer_init
128 
129 ! --------------------------------------------------------------------------------
130 
131 !> Start a timer
132 
133  subroutine oasis_timer_start (timer_label, barrier)
135  implicit none
136 
137  character(len=*), intent (in) :: timer_label !< timer name
138  logical, intent (in), optional :: barrier !< flag to barrier this timer
139 
140  integer :: ierr
141  integer :: timer_id
142  real :: cpu_time_arg
143  character(len=*),parameter :: subname = '(oasis_timer_start)'
144 
145  IF (timer_debug >=1) THEN
146  call oasis_timer_c2i(timer_label,timer_id)
147  if (timer_id < 0) then
148  ntimer = ntimer + 1
149  timer_id = ntimer
150  timer(timer_id)%label = trim(timer_label)
151  IF (ntimer+1 > mtimer) THEN
152  WRITE(nulprt,*) subname,estr,'Timer number exceeded'
153  WRITE(nulprt,*) subname,estr,'Increase nt oasis_timer_init interface'
154  call oasis_abort(file=__file__,line=__line__)
155  ENDIF
156  endif
157 
158  if (present(barrier)) then
159  if (barrier .and. mpi_comm_local /= mpi_comm_null) then
160  call mpi_barrier(mpi_comm_local, ierr)
161  endif
162  endif
163 
164  timer(timer_id)%start_wtime = mpi_wtime()
165  call cpu_time(cpu_time_arg)
166  timer(timer_id)%start_ctime = cpu_time_arg
167  timer_count(timer_id) = timer_count(timer_id) + 1
168  timer(timer_id)%runflag = t_running
169  ENDIF
170 
171  end subroutine oasis_timer_start
172 
173 ! --------------------------------------------------------------------------------
174 
175 !> Stop a timer
176 
177  subroutine oasis_timer_stop (timer_label)
179  character(len=*), intent (in) :: timer_label !< timer name
180 
181  real :: cpu_time_arg
182  integer :: timer_id
183  character(len=*),parameter :: subname = '(oasis_timer_stop)'
184 
185  IF (timer_debug >=1) THEN
186  call oasis_timer_c2i(timer_label,timer_id)
187  if (timer_id < 0) then
188  WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
189  WRITE(nulprt,*) subname,wstr,'timer_label does not exist ',&
190  trim(timer_label)
191  CALL oasis_flush(nulprt)
192  RETURN
193  endif
194 
195  if (timer(timer_id)%runflag == t_stopped) then
196  WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
197  WRITE(nulprt,*) subname,wstr,'timer_id: ',trim(timer_label),' : not started'
198  CALL oasis_flush(nulprt)
199  RETURN
200  endif
201 
202  timer(timer_id)%end_wtime = mpi_wtime()
203  call cpu_time(cpu_time_arg)
204  timer(timer_id)%end_ctime = cpu_time_arg
205 
206  sum_wtime(timer_id) = sum_wtime(timer_id) + &
207  timer(timer_id)%end_wtime - &
208  timer(timer_id)%start_wtime
209  sum_ctime(timer_id) = sum_ctime(timer_id) + &
210  timer(timer_id)%end_ctime - &
211  timer(timer_id)%start_ctime
212  timer(timer_id)%runflag = t_stopped
213  ENDIF
214 
215  end subroutine oasis_timer_stop
216 
217 ! --------------------------------------------------------------------------------
218 
219 !> Print timers
220 
221  subroutine oasis_timer_print(timer_label)
223  implicit none
224 
225  character(len=*), optional, intent(in) :: timer_label !< if unset, print all timers
226 
227  integer :: timer_id
228  real, allocatable :: sum_ctime_global_tmp(:,:)
229  double precision, allocatable :: sum_wtime_global_tmp(:,:)
230  integer, allocatable :: count_global_tmp(:,:)
231  character(len=ic_med), allocatable :: label_global_tmp(:,:)
232  real, allocatable :: sum_ctime_global(:,:)
233  double precision, allocatable :: sum_wtime_global(:,:)
234  integer, allocatable :: count_global(:,:)
235  double precision, allocatable :: rarr(:)
236  integer, allocatable :: iarr(:)
237  character(len=ic_med), allocatable :: carr(:)
238  character(len=ic_med), allocatable :: label_list(:)
239  double precision :: rval
240  integer :: ival
241  character(len=ic_med) :: cval
242  logical :: onetimer
243  logical :: found
244  integer, parameter :: root = 0
245  integer :: k, n, m
246  integer :: nlabels
247  integer :: ierror
248  integer :: ntimermax
249  integer :: pe1,pe2
250  integer :: minpe,maxpe,mcnt
251  double precision :: mintime,maxtime,meantime
252  character(len=*),parameter :: subname = '(oasis_timer_print)'
253 
254  IF (timer_debug < 1) then
255  return
256  ENDIF
257 
258  IF ((timer_debug == 1) .AND. (mpi_rank_local == 0)) timer_debug=2
259 
260  IF (timer_debug >= 2) THEN
261 
263  WRITE(file_name,'(a,i4.4)') trim(file_hold)//'_',mpi_rank_local
264 
265  OPEN(output_unit, file=trim(file_name), form="FORMATTED", &
266  status="UNKNOWN")
267  WRITE(output_unit,*) ''
268  CLOSE(output_unit)
269 
270  ENDIF
271 
272  onetimer = .false.
273  if (present(timer_label)) then
274  onetimer = .true.
275  call oasis_timer_c2i(timer_label,timer_id)
276  if (timer_id < 1) then
277  WRITE(nulprt,*) subname,' model :',compid,&
278  ' proc :',mpi_rank_local
279  WRITE(nulprt,*) subname,wstr,'invalid timer_label',&
280  trim(timer_label)
281  CALL oasis_flush(nulprt)
282  RETURN
283  endif
284  endif
285 
286 !-----------------------------------------------------
287 ! one timer output
288 !-----------------------------------------------------
289  if (timer_debug >= 2 .and. onetimer) then
290 
291  OPEN(output_unit, file=trim(file_name), form="FORMATTED", &
292  status="UNKNOWN", position="APPEND")
293  IF (.NOT.single_timer_header) THEN
294  WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
295  ' wtime ','on pe','count',' ctime ','on pe','count'
296  single_timer_header = .true.
297  ENDIF
298  n = timer_id
299  WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f11.4,i8,i13,4x))') &
300  n, timer(n)%label, timer(n)%runflag, &
303  CLOSE(output_unit)
304 !----------
305  return
306 !----------
307  endif
308 
309 !-----------------------------------------------------
310 ! local output
311 !-----------------------------------------------------
312  IF (timer_debug >= 2) THEN
313  OPEN(output_unit, file=trim(file_name), form="FORMATTED", &
314  status="UNKNOWN", position="APPEND")
315 
316  WRITE(output_unit,*)''
317  WRITE(output_unit,*)' =================================='
318  WRITE(output_unit,*)' ', trim(app_name)
319  WRITE(output_unit,*)' Local processor times '
320  WRITE(output_unit,*)' =================================='
321  WRITE(output_unit,*)''
322 
323  do n = 1,ntimer
324  IF (.NOT.single_timer_header) THEN
325  WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
326  ' wtime ','on pe','count',' ctime ','on pe','count'
327  single_timer_header = .true.
328  ENDIF
329  WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f11.4,i8,i13,4x))') &
330  n, timer(n)%label, timer(n)%runflag, &
333  enddo
334 
335  CLOSE(output_unit)
336  ENDIF
337 
338 !-----------------------------------------------------
339 ! gather global output on mpi_comm_local pes
340 !-----------------------------------------------------
341  if (mpi_size_local > 0) then
342 
343  call mpi_allreduce(ntimer,ntimermax,1,mpi_integer,mpi_max,mpi_comm_local,ierror)
344 
345  allocate (sum_ctime_global_tmp(ntimermax, mpi_size_local), &
346  sum_wtime_global_tmp(ntimermax, mpi_size_local), stat=ierror)
347  IF ( ierror /= 0 ) WRITE(nulprt,*) subname,' model :',compid,' proc :',&
348  mpi_rank_local,':',wstr,'allocate error sum_global_tmp'
349  allocate (count_global_tmp(ntimermax, mpi_size_local), stat=ierror)
350  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
351  mpi_rank_local,':',wstr,'allocate error count_global_tmp'
352  allocate (label_global_tmp(ntimermax, mpi_size_local), stat=ierror)
353  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
354  mpi_rank_local,':',wstr,'allocate error label_global_tmp'
355 
356  sum_ctime_global_tmp = 0.0
357  sum_wtime_global_tmp = 0.0
358  count_global_tmp = 0
359  label_global_tmp = ' '
360 
361  ! gathering of timer values on root process
362 
363 ! tcraig, causes memory failure on corail for some reason
364 #if (1 == 0)
365  allocate(carr(ntimermax))
366  do n = 1,ntimermax
367  carr(n) = timer(n)%label
368  enddo
369  call mpi_barrier(mpi_comm_local, ierror)
370  call mpi_gather(carr(1), ntimermax, mpi_character, label_global_tmp(1,1), &
371  ntimermax, mpi_character, root, mpi_comm_local, ierror)
372  call mpi_barrier(mpi_comm_local, ierror)
373  call mpi_gather(sum_ctime(1), ntimermax, mpi_double_precision, sum_ctime_global_tmp(1,1), &
374  ntimermax, mpi_double_precision, root, mpi_comm_local, ierror)
375  call mpi_barrier(mpi_comm_local, ierror)
376  call mpi_gather(sum_wtime(1), ntimermax, mpi_double_precision, sum_wtime_global_tmp(1,1), &
377  ntimermax, mpi_double_precision, root, mpi_comm_local, ierror)
378  call mpi_barrier(mpi_comm_local, ierror)
379  call mpi_gather(timer_count(1), ntimermax, mpi_integer, count_global_tmp(1,1), &
380  ntimermax, mpi_integer, root, mpi_comm_local, ierror)
381  deallocate(carr)
382 #endif
383 
384 ! tcraig, this doesn't work either
385 #if (1 == 0)
386 ! allocate(rarr(ntimermax),stat=ierror)
387 ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'allocate error rarr'
388 ! rarr(1:ntimermax) = sum_ctime(1:ntimermax)
389 ! call MPI_Gather(rarr,ntimermax,MPI_DOUBLE_PRECISION,sum_ctime_global_tmp,ntimermax,MPI_DOUBLE_PRECISION,root,mpi_comm_local,ierror)
390 ! rarr(1:ntimermax) = sum_wtime(1:ntimermax)
391 ! call MPI_Gather(rarr,ntimermax,MPI_DOUBLE_PRECISION,sum_wtime_global_tmp,ntimermax,MPI_DOUBLE_PRECISION,root,mpi_comm_local,ierror)
392 ! deallocate(rarr,stat=ierror)
393 ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'deallocate error rarr'
394 !
395 ! allocate(iarr(ntimermax),stat=ierror)
396 ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'allocate error iarr'
397 ! iarr(1:ntimermax) = count(1:ntimermax)
398 ! call MPI_Gather(iarr,ntimermax,MPI_INTEGER,count_global_tmp,ntimermax,MPI_INTEGER,root,mpi_comm_local,ierror)
399 ! deallocate(iarr,stat=ierror)
400 ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'deallocate error iarr'
401 #endif
402 
403 ! tcraig this works but requires lots of gather calls, could be better
404 #if (1 == 1)
405  allocate(rarr(mpi_size_local),iarr(mpi_size_local),carr(mpi_size_local),stat=ierror)
406  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
407  mpi_rank_local,':',wstr,'allocate error rarr'
408 
409  do n = 1,ntimermax
410  cval = timer(n)%label
411  carr(:) = ' '
412  call mpi_barrier(mpi_comm_local, ierror)
413  call mpi_gather(cval,len(cval),mpi_character,carr(1),len(cval),&
414  mpi_character,root,mpi_comm_local,ierror)
415  if (mpi_rank_local == root) then
416  do m = 1,mpi_size_local
417  label_global_tmp(n,m) = trim(carr(m))
418  enddo
419  endif
420 
421  rval = sum_ctime(n)
422  call mpi_barrier(mpi_comm_local, ierror)
423  call mpi_gather(rval,1,mpi_double_precision,rarr(1),1,mpi_double_precision,&
424  root,mpi_comm_local,ierror)
425  if (mpi_rank_local == root) then
426  sum_ctime_global_tmp(n,1:mpi_size_local) = rarr(1:mpi_size_local)
427  endif
428 
429  rval = sum_wtime(n)
430  call mpi_barrier(mpi_comm_local, ierror)
431  call mpi_gather(rval,1,mpi_double_precision,rarr(1),1,mpi_double_precision,&
432  root,mpi_comm_local,ierror)
433  if (mpi_rank_local == root) then
434  sum_wtime_global_tmp(n,1:mpi_size_local) = rarr(1:mpi_size_local)
435  endif
436 
437  ival = timer_count(n)
438  call mpi_barrier(mpi_comm_local, ierror)
439  call mpi_gather(ival,1,mpi_integer,iarr(1),1,mpi_integer,root,&
440  mpi_comm_local,ierror)
441  if (mpi_rank_local == root) then
442  count_global_tmp(n,1:mpi_size_local) = iarr(1:mpi_size_local)
443  endif
444  enddo
445  deallocate(rarr,iarr,carr,stat=ierror)
446  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
447  mpi_rank_local,':',wstr,'deallocate error rarr'
448 #endif
449 
450  ! now sort all the timers out by names
451 
452  allocate(carr(ntimermax*mpi_size_local),stat=ierror)
453  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
454  mpi_rank_local,':',wstr,'allocate error carr'
455  nlabels = 0
456  do n = 1,ntimermax
457  do m = 1,mpi_size_local
458  found = .false.
459  if (trim(label_global_tmp(n,m)) == '') then
460  found = .true.
461  else
462  do k = 1,nlabels
463  if (trim(label_global_tmp(n,m)) == trim(carr(k))) found = .true.
464  enddo
465  endif
466  if (.not.found) then
467  nlabels = nlabels + 1
468  carr(nlabels) = trim(label_global_tmp(n,m))
469  endif
470  enddo
471  enddo
472 
473  allocate(label_list(nlabels),stat=ierror)
474  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
475  mpi_rank_local,':',wstr,'allocate error label_list'
476  do k = 1,nlabels
477  label_list(k) = trim(carr(k))
478  enddo
479  deallocate(carr,stat=ierror)
480  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
481  mpi_rank_local,':',wstr,'deallocate error carr'
482  allocate(sum_ctime_global(nlabels,mpi_size_local),stat=ierror)
483  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
484  mpi_rank_local,':',wstr,'allocate error sum_ctime_global'
485  allocate(sum_wtime_global(nlabels,mpi_size_local),stat=ierror)
486  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
487  mpi_rank_local,':',wstr,'allocate error sum_wtime_global'
488  allocate(count_global(nlabels,mpi_size_local),stat=ierror)
489  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
490  mpi_rank_local,':',wstr,'allocate error count_global'
491 
492  sum_ctime_global = 0
493  sum_wtime_global = 0
494  count_global = 0
495 
496  do k = 1,nlabels
497  do m = 1,ntimermax
498  do n = 1,mpi_size_local
499  if (trim(label_list(k)) == trim(label_global_tmp(m,n))) then
500  sum_ctime_global(k,n) = sum_ctime_global_tmp(m,n)
501  sum_wtime_global(k,n) = sum_wtime_global_tmp(m,n)
502  count_global(k,n) = count_global_tmp(m,n)
503  endif
504  enddo
505  enddo
506  enddo
507 
508  deallocate(label_global_tmp,stat=ierror)
509  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
510  mpi_rank_local,':',wstr,'deallocate error label_global_tmp'
511  deallocate(sum_ctime_global_tmp,stat=ierror)
512  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
513  mpi_rank_local,':',wstr,'deallocate error sum_ctime_global_tmp'
514  deallocate(sum_wtime_global_tmp,stat=ierror)
515  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
516  mpi_rank_local,':',wstr,'deallocate error sum_wtime_global_tmp'
517  deallocate(count_global_tmp,stat=ierror)
518  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
519  mpi_rank_local,':',wstr,'deallocate error count_global'
520 
521  endif ! (mpi_size_local > 1)
522 
523 !-----------------------------------------------------
524 ! write global output on root of mpi_comm_local
525 !-----------------------------------------------------
526  if (timer_debug >= 2 .and. mpi_rank_local == root) then
527  OPEN(output_unit, file=trim(file_name), form="FORMATTED", &
528  status="UNKNOWN", position="APPEND")
529 
530  if (onetimer) then
531  IF (.NOT.single_timer_header) THEN
532  WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
533  'mintime','on pe','count','maxtime','on pe','count'
534  single_timer_header = .true.
535  ENDIF
536  n = 0
537  do k = 1,nlabels
538  if (trim(timer_label) == trim(label_list(k))) n = k
539  enddo
540  if (n < 1) then
541  write(nulprt,*) subname,' model :',compid,' proc :',&
542  mpi_rank_local,':',wstr,'invalid timer_label',trim(timer_label)
543  CALL oasis_flush(nulprt)
544  return
545  endif
546  mintime = sum_ctime_global(n,1)
547  minpe = 1
548  maxtime = sum_ctime_global(n,1)
549  maxpe = 1
550  do k = 1,mpi_size_local
551  if (sum_ctime_global(n,k) < mintime) then
552  mintime = sum_ctime_global(n,k)
553  minpe = k
554  endif
555  if (sum_ctime_global(n,k) > maxtime) then
556  maxtime = sum_ctime_global(n,k)
557  maxpe = k
558  endif
559  enddo
560  WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f11.4,i8,i13,4x))') &
561  n, label_list(n), timer(n)%runflag, &
562  sum_ctime_global(n,minpe), minpe, count_global(n,minpe), &
563  sum_ctime_global(n,maxpe), maxpe, count_global(n,maxpe)
564 
565  else
566  single_timer_header = .false.
567 
568  WRITE(output_unit,*)''
569  WRITE(output_unit,*)' =================================='
570  WRITE(output_unit,*)' ', trim(app_name)
571  WRITE(output_unit,*)' Overall Elapsed Min/Max statistics'
572  WRITE(output_unit,*)' =================================='
573  WRITE(output_unit,*)''
574  WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x),a,3x)') &
575  'mintime','on pe','count','maxtime','on pe','count','meantime'
576 
577  DO n = 1,nlabels
578  mintime = 1.0e36
579  minpe = -1
580  maxtime = -1.0e36
581  maxpe = -1
582  meantime = 0.0
583  mcnt = 0
584  do k = 1,mpi_size_local
585  if (count_global(n,k) > 0) then
586  meantime = meantime + sum_wtime_global(n,k)
587  mcnt = mcnt + 1
588  if (sum_wtime_global(n,k) < mintime) then
589  mintime = sum_wtime_global(n,k)
590  minpe = k
591  endif
592  if (sum_wtime_global(n,k) > maxtime) then
593  maxtime = sum_wtime_global(n,k)
594  maxpe = k
595  endif
596  endif
597  enddo
598  if (mcnt > 0) then
599  meantime = meantime / float(mcnt)
600  WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f11.4,i8,i13,4x),f11.4)') &
601  n, label_list(n), timer(n)%runflag, &
602  sum_wtime_global(n,minpe), minpe-1, count_global(n,minpe), &
603  sum_wtime_global(n,maxpe), maxpe-1, count_global(n,maxpe), &
604  meantime
605  endif
606  ENDDO
607 
608  IF (timer_debug >= 3) THEN
609  WRITE(output_unit,*)''
610  WRITE(output_unit,*)' =================================='
611  WRITE(output_unit,*)' ', trim(app_name)
612  WRITE(output_unit,*)' Overall Count statistics'
613  WRITE(output_unit,*)' =================================='
614  WRITE(output_unit,*)''
615  DO k=1,mpi_size_local
616  WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
617  WRITE(output_unit,'(3x,i8,5x)')(k-1)
618  DO n = 1, nlabels
619  WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(i10))') n, label_list(n), &
620  timer(n)%runflag, (count_global(n,k))
621  ENDDO
622  ENDDO
623  WRITE(output_unit,*)''
624  WRITE(output_unit,*)' =================================='
625  WRITE(output_unit,*)' ', trim(app_name)
626  WRITE(output_unit,*)' Overall CPU time statistics'
627  WRITE(output_unit,*)' =================================='
628  WRITE(output_unit,*)''
629  DO k=1,mpi_size_local
630  WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
631  WRITE(output_unit,'(3x,i8,5x)')(k-1)
632  DO n = 1, nlabels
633  WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(f11.4))') n, label_list(n), timer(n)%runflag, &
634  (sum_ctime_global(n,k))
635  ENDDO
636  ENDDO
637  WRITE(output_unit,*)''
638  WRITE(output_unit,*)' ======================================'
639  WRITE(output_unit,*)' ', trim(app_name)
640  WRITE(output_unit,*)' Overall Elapsed time statistics'
641  WRITE(output_unit,*)' ======================================'
642  WRITE(output_unit,*)''
643  DO k=1,mpi_size_local
644  WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
645  WRITE(output_unit,'(3x,i8,5x)')(k-1)
646  DO n = 1, nlabels
647  WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(f11.4))') n, label_list(n), timer(n)%runflag, &
648  (sum_wtime_global(n,k))
649  ENDDO
650  ENDDO
651  WRITE(output_unit,*)''
652  WRITE(output_unit,*)' ======================================'
653  ENDIF
654 
655  endif ! (onetimer)
656 
657  CLOSE(output_unit)
658 
659  deallocate (sum_ctime_global, stat=ierror)
660  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
661  mpi_rank_local,':',wstr,'deallocate error sum_ctime_global'
662  deallocate (sum_wtime_global, stat=ierror)
663  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
664  mpi_rank_local,':',wstr,'deallocate error sum_wtime_global'
665  deallocate (count_global,stat=ierror)
666  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
667  mpi_rank_local,':',wstr,'deallocate error count_global'
668  deallocate (label_list,stat=ierror)
669  if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
670  mpi_rank_local,':',wstr,'deallocate error label_list'
671 
672  endif ! (mpi_rank_local == root)
673 
674  end subroutine oasis_timer_print
675 
676 ! --------------------------------------------------------------------------------
677 
678 !> Convert a timer name to the timer id number
679 
680  subroutine oasis_timer_c2i(tname,tid)
682  character(len=*),intent(in) :: tname !< timer name
683  integer ,intent(out) :: tid !< timer id
684 
685  integer :: n
686 
687  tid = -1
688  do n = 1,ntimer
689  if (trim(tname) == trim(timer(n)%label)) tid = n
690  enddo
691 
692  end subroutine oasis_timer_c2i
693 
694 ! --------------------------------------------------------------------------------
695 end module mod_oasis_timer
System type methods.
type(timer_details), dimension(:), pointer timer
Provides a common location for several OASIS variables.
character(len=1), parameter t_stopped
integer(kind=ip_i4_p) mpi_size_local
integer(kind=ip_intwp_p) nulprt
subroutine, public oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
OASIS abort method, publically available to users.
integer(kind=ip_i4_p) compid
subroutine, public oasis_timer_init(app, file, nt)
Initializes the timer methods, called once in an application.
Storage for timer data.
integer(kind=ip_i4_p) mpi_rank_local
Defines kinds for OASIS.
character(len=ic_med) file_hold
logical, save single_timer_header
subroutine oasis_timer_c2i(tname, tid)
Convert a timer name to the timer id number.
subroutine, public oasis_timer_print(timer_label)
Print timers.
double precision, dimension(:), pointer sum_ctime
subroutine, public oasis_timer_start(timer_label, barrier)
Start a timer.
subroutine, public oasis_timer_stop(timer_label)
Stop a timer.
character(len= *), parameter, public estr
integer(kind=ip_i4_p) mpi_comm_local
subroutine, public oasis_unitget(uio)
Get a free unit number.
double precision, dimension(:), pointer sum_wtime
integer, dimension(:), pointer timer_count
character(len=1), parameter t_running
subroutine, public oasis_flush(nu)
Flushes output to file.
character(len=ic_med) file_name
character(len=ic_med) app_name
Performance timer methods.
integer(kind=ip_i4_p) timer_debug
character(len= *), parameter, public wstr