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 | |
---|
39 | module mod_oasis_timer |
---|
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 |
---|
61 | type timer_details |
---|
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) |
---|
134 | |
---|
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) |
---|
178 | |
---|
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) |
---|
222 | |
---|
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 | |
---|
262 | CALL oasis_unitget(output_unit) |
---|
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, & |
---|
301 | sum_wtime(n), mpi_rank_local, TIMER_COUNT(n), & |
---|
302 | sum_ctime(n), mpi_rank_local, TIMER_COUNT(n) |
---|
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, & |
---|
331 | sum_wtime(n), mpi_rank_local, TIMER_COUNT(n), & |
---|
332 | sum_ctime(n), mpi_rank_local, TIMER_COUNT(n) |
---|
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) |
---|
681 | |
---|
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 |
---|