mod_oasis_timer.F90 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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. module mod_oasis_timer
  39. use mod_oasis_kinds
  40. use mod_oasis_data
  41. use mod_oasis_sys
  42. implicit none
  43. private
  44. public oasis_timer_init
  45. public oasis_timer_start
  46. public oasis_timer_stop
  47. public oasis_timer_print
  48. ! name of the application
  49. character (len=ic_med) :: app_name
  50. ! name of the time statistics file
  51. character (len=ic_med) :: file_name
  52. character (len=ic_med) :: file_hold
  53. !> Storage for timer data
  54. type timer_details
  55. ! label of timer
  56. character (len=ic_med) :: label
  57. ! wall time values
  58. double precision :: start_wtime, end_wtime
  59. ! cpu time values
  60. double precision :: start_ctime, end_ctime
  61. ! is the timer running now
  62. character(len=1) :: runflag
  63. end type timer_details
  64. INTEGER :: mtimer
  65. TYPE (timer_details), POINTER :: timer(:)
  66. DOUBLE PRECISION, POINTER :: sum_ctime(:) ! these values are not part of timer details
  67. DOUBLE PRECISION, POINTER :: sum_wtime(:) ! because they are later used in an mpi call
  68. INTEGER, POINTER :: TIMER_COUNT(:) ! number of calls
  69. integer :: ntimer
  70. integer :: output_unit = 901
  71. logical,save :: single_timer_header
  72. character(len=1),parameter :: t_stopped = ' '
  73. character(len=1),parameter :: t_running = '*'
  74. contains
  75. ! --------------------------------------------------------------------------------
  76. !> Initializes the timer methods, called once in an application
  77. subroutine oasis_timer_init (app, file, nt)
  78. implicit none
  79. character (len=*), intent (in) :: app !< name of application
  80. character (len=*), intent (in) :: file !< output filename
  81. integer , intent (in) :: nt !< number of timers
  82. integer :: ierror,n
  83. character(len=*),parameter :: subname = '(oasis_timer_init)'
  84. app_name = trim (app)
  85. file_hold = trim (file)
  86. mtimer = nt
  87. ALLOCATE(timer(mtimer))
  88. ALLOCATE(sum_ctime(mtimer))
  89. ALLOCATE(sum_wtime(mtimer))
  90. ALLOCATE(timer_count(mtimer))
  91. ntimer = 0
  92. do n = 1,mtimer
  93. timer(n)%label = ' '
  94. timer(n)%start_wtime = 0
  95. timer(n)%end_wtime = 0
  96. timer(n)%start_ctime = 0
  97. timer(n)%end_ctime = 0
  98. timer(n)%runflag = t_stopped
  99. sum_wtime(n) = 0
  100. sum_ctime(n) = 0
  101. timer_count(n) = 0
  102. enddo
  103. single_timer_header = .false.
  104. end subroutine oasis_timer_init
  105. ! --------------------------------------------------------------------------------
  106. !> Start a timer
  107. subroutine oasis_timer_start (timer_label, barrier)
  108. implicit none
  109. character(len=*), intent (in) :: timer_label !< timer name
  110. logical, intent (in), optional :: barrier !< flag to barrier this timer
  111. integer :: ierr
  112. integer :: timer_id
  113. real :: cpu_time_arg
  114. character(len=*),parameter :: subname = '(oasis_timer_start)'
  115. IF (TIMER_Debug >=1) THEN
  116. call oasis_timer_c2i(timer_label,timer_id)
  117. if (timer_id < 0) then
  118. ntimer = ntimer + 1
  119. timer_id = ntimer
  120. timer(timer_id)%label = trim(timer_label)
  121. IF (ntimer+1 > mtimer) THEN
  122. WRITE(nulprt,*) subname,estr,'Timer number exceeded'
  123. WRITE(nulprt,*) subname,estr,'Increase nt oasis_timer_init interface'
  124. CALL oasis_abort()
  125. ENDIF
  126. endif
  127. if (present(barrier)) then
  128. if (barrier .and. mpi_comm_local /= MPI_COMM_NULL) then
  129. call MPI_BARRIER(mpi_comm_local, ierr)
  130. endif
  131. endif
  132. timer(timer_id)%start_wtime = MPI_WTIME()
  133. call cpu_time(cpu_time_arg)
  134. timer(timer_id)%start_ctime = cpu_time_arg
  135. timer_count(timer_id) = timer_count(timer_id) + 1
  136. timer(timer_id)%runflag = t_running
  137. ENDIF
  138. end subroutine oasis_timer_start
  139. ! --------------------------------------------------------------------------------
  140. !> Stop a timer
  141. subroutine oasis_timer_stop (timer_label)
  142. character(len=*), intent (in) :: timer_label !< timer name
  143. real :: cpu_time_arg
  144. integer :: timer_id
  145. character(len=*),parameter :: subname = '(oasis_timer_stop)'
  146. IF (TIMER_Debug >=1) THEN
  147. call oasis_timer_c2i(timer_label,timer_id)
  148. if (timer_id < 0) then
  149. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  150. WRITE(nulprt,*) subname,wstr,'timer_label does not exist ',&
  151. TRIM(timer_label)
  152. CALL oasis_flush(nulprt)
  153. RETURN
  154. endif
  155. if (timer(timer_id)%runflag == t_stopped) then
  156. WRITE(nulprt,*) subname,' model :',compid,' proc :',mpi_rank_local
  157. WRITE(nulprt,*) subname,wstr,'timer_id: ',trim(timer_label),' : not started'
  158. CALL oasis_flush(nulprt)
  159. RETURN
  160. endif
  161. timer(timer_id)%end_wtime = MPI_WTIME()
  162. call cpu_time(cpu_time_arg)
  163. timer(timer_id)%end_ctime = cpu_time_arg
  164. sum_wtime(timer_id) = sum_wtime(timer_id) + &
  165. timer(timer_id)%end_wtime - &
  166. timer(timer_id)%start_wtime
  167. sum_ctime(timer_id) = sum_ctime(timer_id) + &
  168. timer(timer_id)%end_ctime - &
  169. timer(timer_id)%start_ctime
  170. timer(timer_id)%runflag = t_stopped
  171. ENDIF
  172. end subroutine oasis_timer_stop
  173. ! --------------------------------------------------------------------------------
  174. !> Print timers
  175. subroutine oasis_timer_print(timer_label)
  176. implicit none
  177. character(len=*), optional, intent(in) :: timer_label !< if unset, print all timers
  178. integer :: timer_id
  179. real, allocatable :: sum_ctime_global_tmp(:,:)
  180. double precision, allocatable :: sum_wtime_global_tmp(:,:)
  181. integer, allocatable :: count_global_tmp(:,:)
  182. character(len=ic_med), allocatable :: label_global_tmp(:,:)
  183. real, allocatable :: sum_ctime_global(:,:)
  184. double precision, allocatable :: sum_wtime_global(:,:)
  185. integer, allocatable :: count_global(:,:)
  186. double precision, allocatable :: rarr(:)
  187. integer, allocatable :: iarr(:)
  188. character(len=ic_med), allocatable :: carr(:)
  189. character(len=ic_med), allocatable :: label_list(:)
  190. double precision :: rval
  191. integer :: ival
  192. character(len=ic_med) :: cval
  193. logical :: onetimer
  194. logical :: found
  195. integer, parameter :: root = 0
  196. integer :: k, n, m
  197. integer :: nlabels
  198. integer :: ierror
  199. integer :: ntimermax
  200. integer :: pe1,pe2
  201. integer :: minpe,maxpe,mcnt
  202. double precision :: mintime,maxtime,meantime
  203. character(len=*),parameter :: subname = '(oasis_timer_print)'
  204. IF (TIMER_Debug < 1) then
  205. return
  206. ENDIF
  207. IF ((TIMER_debug == 1) .AND. (mpi_rank_local == 0)) TIMER_Debug=2
  208. IF (TIMER_Debug >= 2) THEN
  209. CALL oasis_unitget(output_unit)
  210. WRITE(file_name,'(a,i4.4)') TRIM(file_hold)//'_',mpi_rank_local
  211. OPEN(output_unit, file=TRIM(file_name), form="FORMATTED", &
  212. status="UNKNOWN")
  213. WRITE(output_unit,*) ''
  214. CLOSE(output_unit)
  215. ENDIF
  216. onetimer = .false.
  217. if (present(timer_label)) then
  218. onetimer = .true.
  219. call oasis_timer_c2i(timer_label,timer_id)
  220. if (timer_id < 1) then
  221. WRITE(nulprt,*) subname,' model :',compid,&
  222. ' proc :',mpi_rank_local
  223. WRITE(nulprt,*) subname,wstr,'invalid timer_label',&
  224. TRIM(timer_label)
  225. CALL oasis_flush(nulprt)
  226. RETURN
  227. endif
  228. endif
  229. !-----------------------------------------------------
  230. ! one timer output
  231. !-----------------------------------------------------
  232. if (TIMER_Debug >= 2 .and. onetimer) then
  233. OPEN(output_unit, file=TRIM(file_name), form="FORMATTED", &
  234. status="UNKNOWN", position="APPEND")
  235. IF (.NOT.single_timer_header) THEN
  236. WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
  237. ' wtime ','on pe','count',' ctime ','on pe','count'
  238. single_timer_header = .TRUE.
  239. ENDIF
  240. n = timer_id
  241. WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f10.4,i8,i12,4x))') &
  242. n, timer(n)%label, timer(n)%runflag, &
  243. sum_wtime(n), mpi_rank_local, TIMER_COUNT(n), &
  244. sum_ctime(n), mpi_rank_local, TIMER_COUNT(n)
  245. CLOSE(output_unit)
  246. !----------
  247. return
  248. !----------
  249. endif
  250. !-----------------------------------------------------
  251. ! local output
  252. !-----------------------------------------------------
  253. IF (TIMER_Debug >= 2) THEN
  254. OPEN(output_unit, file=TRIM(file_name), form="FORMATTED", &
  255. status="UNKNOWN", position="APPEND")
  256. WRITE(output_unit,*)''
  257. WRITE(output_unit,*)' =================================='
  258. WRITE(output_unit,*)' ', TRIM(app_name)
  259. WRITE(output_unit,*)' Local processor times '
  260. WRITE(output_unit,*)' =================================='
  261. WRITE(output_unit,*)''
  262. do n = 1,ntimer
  263. IF (.NOT.single_timer_header) THEN
  264. WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
  265. ' wtime ','on pe','count',' ctime ','on pe','count'
  266. single_timer_header = .TRUE.
  267. ENDIF
  268. WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f10.4,i8,i12,4x))') &
  269. n, timer(n)%label, timer(n)%runflag, &
  270. sum_wtime(n), mpi_rank_local, TIMER_COUNT(n), &
  271. sum_ctime(n), mpi_rank_local, TIMER_COUNT(n)
  272. enddo
  273. CLOSE(output_unit)
  274. ENDIF
  275. !-----------------------------------------------------
  276. ! gather global output on mpi_comm_local pes
  277. !-----------------------------------------------------
  278. if (mpi_size_local > 0) then
  279. call MPI_ALLREDUCE(ntimer,ntimermax,1,MPI_INTEGER,MPI_MAX,mpi_comm_local,ierror)
  280. allocate (sum_ctime_global_tmp(ntimermax, mpi_size_local), &
  281. sum_wtime_global_tmp(ntimermax, mpi_size_local), stat=ierror)
  282. IF ( ierror /= 0 ) WRITE(nulprt,*) subname,' model :',compid,' proc :',&
  283. mpi_rank_local,':',wstr,'allocate error sum_global_tmp'
  284. allocate (count_global_tmp(ntimermax, mpi_size_local), stat=ierror)
  285. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  286. mpi_rank_local,':',wstr,'allocate error count_global_tmp'
  287. allocate (label_global_tmp(ntimermax, mpi_size_local), stat=ierror)
  288. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  289. mpi_rank_local,':',wstr,'allocate error label_global_tmp'
  290. sum_ctime_global_tmp = 0.0
  291. sum_wtime_global_tmp = 0.0
  292. count_global_tmp = 0
  293. label_global_tmp = ' '
  294. ! gathering of timer values on root process
  295. ! tcraig, causes memory failure on corail for some reason
  296. ! call MPI_Gather(sum_ctime(1), ntimermax, MPI_DOUBLE_PRECISION, sum_ctime_global_tmp(1,1), &
  297. ! ntimermax, MPI_DOUBLE_PRECISION, root, mpi_comm_local, ierror)
  298. ! call MPI_Gather(sum_wtime(1), ntimermax, MPI_DOUBLE_PRECISION, sum_wtime_global_tmp(1,1), &
  299. ! ntimermax, MPI_DOUBLE_PRECISION, root, mpi_comm_local, ierror)
  300. ! call MPI_Gather(count(1), ntimermax, MPI_INTEGER, count_global_tmp(1,1), &
  301. ! ntimermax, MPI_INTEGER, root, mpi_comm_local, ierror)
  302. ! tcraig, this doesn't work either
  303. ! allocate(rarr(ntimermax),stat=ierror)
  304. ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'allocate error rarr'
  305. ! rarr(1:ntimermax) = sum_ctime(1:ntimermax)
  306. ! call MPI_Gather(rarr,ntimermax,MPI_DOUBLE_PRECISION,sum_ctime_global_tmp,ntimermax,MPI_DOUBLE_PRECISION,root,mpi_comm_local,ierror)
  307. ! rarr(1:ntimermax) = sum_wtime(1:ntimermax)
  308. ! call MPI_Gather(rarr,ntimermax,MPI_DOUBLE_PRECISION,sum_wtime_global_tmp,ntimermax,MPI_DOUBLE_PRECISION,root,mpi_comm_local,ierror)
  309. ! deallocate(rarr,stat=ierror)
  310. ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'deallocate error rarr'
  311. !
  312. ! allocate(iarr(ntimermax),stat=ierror)
  313. ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'allocate error iarr'
  314. ! iarr(1:ntimermax) = count(1:ntimermax)
  315. ! call MPI_Gather(iarr,ntimermax,MPI_INTEGER,count_global_tmp,ntimermax,MPI_INTEGER,root,mpi_comm_local,ierror)
  316. ! deallocate(iarr,stat=ierror)
  317. ! if ( ierror /= 0 ) write(nulprt,*) subname,wstr,'deallocate error iarr'
  318. ! tcraig this works but requires lots of gather calls, could be better
  319. allocate(rarr(mpi_size_local),iarr(mpi_size_local),carr(mpi_size_local),stat=ierror)
  320. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  321. mpi_rank_local,':',wstr,'allocate error rarr'
  322. do n = 1,ntimermax
  323. cval = timer(n)%label
  324. carr(:) = ' '
  325. call MPI_Gather(cval,len(cval),MPI_CHARACTER,carr(1),len(cval),&
  326. MPI_CHARACTER,root,mpi_comm_local,ierror)
  327. if (mpi_rank_local == root) then
  328. do m = 1,mpi_size_local
  329. label_global_tmp(n,m) = trim(carr(m))
  330. enddo
  331. endif
  332. rval = sum_ctime(n)
  333. call MPI_Gather(rval,1,MPI_DOUBLE_PRECISION,rarr(1),1,MPI_DOUBLE_PRECISION,&
  334. root,mpi_comm_local,ierror)
  335. if (mpi_rank_local == root) then
  336. sum_ctime_global_tmp(n,1:mpi_size_local) = rarr(1:mpi_size_local)
  337. endif
  338. rval = sum_wtime(n)
  339. call MPI_Gather(rval,1,MPI_DOUBLE_PRECISION,rarr(1),1,MPI_DOUBLE_PRECISION,&
  340. root,mpi_comm_local,ierror)
  341. if (mpi_rank_local == root) then
  342. sum_wtime_global_tmp(n,1:mpi_size_local) = rarr(1:mpi_size_local)
  343. endif
  344. ival = timer_count(n)
  345. call MPI_Gather(ival,1,MPI_INTEGER,iarr(1),1,MPI_INTEGER,root,&
  346. mpi_comm_local,ierror)
  347. if (mpi_rank_local == root) then
  348. count_global_tmp(n,1:mpi_size_local) = iarr(1:mpi_size_local)
  349. endif
  350. enddo
  351. deallocate(rarr,iarr,carr,stat=ierror)
  352. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  353. mpi_rank_local,':',wstr,'deallocate error rarr'
  354. ! now sort all the timers out by names
  355. allocate(carr(ntimermax*mpi_size_local),stat=ierror)
  356. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  357. mpi_rank_local,':',wstr,'allocate error carr'
  358. nlabels = 0
  359. do n = 1,ntimermax
  360. do m = 1,mpi_size_local
  361. found = .false.
  362. if (trim(label_global_tmp(n,m)) == '') then
  363. found = .true.
  364. else
  365. do k = 1,nlabels
  366. if (trim(label_global_tmp(n,m)) == trim(carr(k))) found = .true.
  367. enddo
  368. endif
  369. if (.not.found) then
  370. nlabels = nlabels + 1
  371. carr(nlabels) = trim(label_global_tmp(n,m))
  372. endif
  373. enddo
  374. enddo
  375. allocate(label_list(nlabels),stat=ierror)
  376. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  377. mpi_rank_local,':',wstr,'allocate error label_list'
  378. do k = 1,nlabels
  379. label_list(k) = trim(carr(k))
  380. enddo
  381. deallocate(carr,stat=ierror)
  382. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  383. mpi_rank_local,':',wstr,'deallocate error carr'
  384. allocate(sum_ctime_global(nlabels,mpi_size_local),stat=ierror)
  385. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  386. mpi_rank_local,':',wstr,'allocate error sum_ctime_global'
  387. allocate(sum_wtime_global(nlabels,mpi_size_local),stat=ierror)
  388. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  389. mpi_rank_local,':',wstr,'allocate error sum_wtime_global'
  390. allocate(count_global(nlabels,mpi_size_local),stat=ierror)
  391. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  392. mpi_rank_local,':',wstr,'allocate error count_global'
  393. sum_ctime_global = 0
  394. sum_wtime_global = 0
  395. count_global = 0
  396. do k = 1,nlabels
  397. do m = 1,ntimermax
  398. do n = 1,mpi_size_local
  399. if (trim(label_list(k)) == trim(label_global_tmp(m,n))) then
  400. sum_ctime_global(k,n) = sum_ctime_global_tmp(m,n)
  401. sum_wtime_global(k,n) = sum_wtime_global_tmp(m,n)
  402. count_global(k,n) = count_global_tmp(m,n)
  403. endif
  404. enddo
  405. enddo
  406. enddo
  407. deallocate(label_global_tmp,stat=ierror)
  408. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  409. mpi_rank_local,':',wstr,'deallocate error label_global_tmp'
  410. deallocate(sum_ctime_global_tmp,stat=ierror)
  411. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  412. mpi_rank_local,':',wstr,'deallocate error sum_ctime_global_tmp'
  413. deallocate(sum_wtime_global_tmp,stat=ierror)
  414. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  415. mpi_rank_local,':',wstr,'deallocate error sum_wtime_global_tmp'
  416. deallocate(count_global_tmp,stat=ierror)
  417. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  418. mpi_rank_local,':',wstr,'deallocate error count_global'
  419. endif ! (mpi_size_local > 1)
  420. !-----------------------------------------------------
  421. ! write global output on root of mpi_comm_local
  422. !-----------------------------------------------------
  423. if (TIMER_Debug >= 2 .and. mpi_rank_local == root) then
  424. OPEN(output_unit, file=TRIM(file_name), form="FORMATTED", &
  425. status="UNKNOWN", position="APPEND")
  426. if (onetimer) then
  427. IF (.NOT.single_timer_header) THEN
  428. WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x))') &
  429. 'mintime','on pe','count','maxtime','on pe','count'
  430. single_timer_header = .TRUE.
  431. ENDIF
  432. n = 0
  433. do k = 1,nlabels
  434. if (trim(timer_label) == trim(label_list(k))) n = k
  435. enddo
  436. if (n < 1) then
  437. write(nulprt,*) subname,' model :',compid,' proc :',&
  438. mpi_rank_local,':',wstr,'invalid timer_label',trim(timer_label)
  439. CALL oasis_flush(nulprt)
  440. return
  441. endif
  442. mintime = sum_ctime_global(n,1)
  443. minpe = 1
  444. maxtime = sum_ctime_global(n,1)
  445. maxpe = 1
  446. do k = 1,mpi_size_local
  447. if (sum_ctime_global(n,k) < mintime) then
  448. mintime = sum_ctime_global(n,k)
  449. minpe = k
  450. endif
  451. if (sum_ctime_global(n,k) > maxtime) then
  452. maxtime = sum_ctime_global(n,k)
  453. maxpe = k
  454. endif
  455. enddo
  456. WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f10.4,i8,i12,4x))') &
  457. n, label_list(n), timer(n)%runflag, &
  458. sum_ctime_global(n,minpe), minpe, count_global(n,minpe), &
  459. sum_ctime_global(n,maxpe), maxpe, count_global(n,maxpe)
  460. else
  461. single_timer_header = .FALSE.
  462. WRITE(output_unit,*)''
  463. WRITE(output_unit,*)' =================================='
  464. WRITE(output_unit,*)' ', TRIM(app_name)
  465. WRITE(output_unit,*)' Overall Elapsed Min/Max statistics'
  466. WRITE(output_unit,*)' =================================='
  467. WRITE(output_unit,*)''
  468. WRITE(output_unit,'(32x,2(2x,a,5x,a,6x,a,4x),a,3x)') &
  469. 'mintime','on pe','count','maxtime','on pe','count','meantime'
  470. DO n = 1,nlabels
  471. mintime = 1.0e36
  472. minpe = -1
  473. maxtime = -1.0e36
  474. maxpe = -1
  475. meantime = 0.0
  476. mcnt = 0
  477. do k = 1,mpi_size_local
  478. if (count_global(n,k) > 0) then
  479. meantime = meantime + sum_wtime_global(n,k)
  480. mcnt = mcnt + 1
  481. if (sum_wtime_global(n,k) < mintime) then
  482. mintime = sum_wtime_global(n,k)
  483. minpe = k
  484. endif
  485. if (sum_wtime_global(n,k) > maxtime) then
  486. maxtime = sum_wtime_global(n,k)
  487. maxpe = k
  488. endif
  489. endif
  490. enddo
  491. if (mcnt > 0) then
  492. meantime = meantime / float(mcnt)
  493. WRITE(output_unit,'(1x,i4,2x,a24,a1,1x,2(f10.4,i8,i12,4x),f10.4)') &
  494. n, label_list(n), timer(n)%runflag, &
  495. sum_wtime_global(n,minpe), minpe-1, count_global(n,minpe), &
  496. sum_wtime_global(n,maxpe), maxpe-1, count_global(n,maxpe), &
  497. meantime
  498. endif
  499. ENDDO
  500. IF (TIMER_Debug >= 3) THEN
  501. WRITE(output_unit,*)''
  502. WRITE(output_unit,*)' =================================='
  503. WRITE(output_unit,*)' ', TRIM(app_name)
  504. WRITE(output_unit,*)' Overall Count statistics'
  505. WRITE(output_unit,*)' =================================='
  506. WRITE(output_unit,*)''
  507. DO k=1,mpi_size_local
  508. WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
  509. WRITE(output_unit,'(3x,i8,5x)')(k-1)
  510. DO n = 1, nlabels
  511. WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(i10))') n, label_list(n), &
  512. timer(n)%runflag, (count_global(n,k))
  513. ENDDO
  514. ENDDO
  515. WRITE(output_unit,*)''
  516. WRITE(output_unit,*)' =================================='
  517. WRITE(output_unit,*)' ', TRIM(app_name)
  518. WRITE(output_unit,*)' Overall CPU time statistics'
  519. WRITE(output_unit,*)' =================================='
  520. WRITE(output_unit,*)''
  521. DO k=1,mpi_size_local
  522. WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
  523. WRITE(output_unit,'(3x,i8,5x)')(k-1)
  524. DO n = 1, nlabels
  525. WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(f10.4))') n, label_list(n), timer(n)%runflag, &
  526. (sum_ctime_global(n,k))
  527. ENDDO
  528. ENDDO
  529. WRITE(output_unit,*)''
  530. WRITE(output_unit,*)' ======================================'
  531. WRITE(output_unit,*)' ', TRIM(app_name)
  532. WRITE(output_unit,*)' Overall Elapsed time statistics'
  533. WRITE(output_unit,*)' ======================================'
  534. WRITE(output_unit,*)''
  535. DO k=1,mpi_size_local
  536. WRITE(output_unit,'(a)',advance="NO") " P r o c e s s o r ----------> "
  537. WRITE(output_unit,'(3x,i8,5x)')(k-1)
  538. DO n = 1, nlabels
  539. WRITE(output_unit,'(1x,i8,2x,a24,a1,1x,(f10.4))') n, label_list(n), timer(n)%runflag, &
  540. (sum_wtime_global(n,k))
  541. ENDDO
  542. ENDDO
  543. WRITE(output_unit,*)''
  544. WRITE(output_unit,*)' ======================================'
  545. ENDIF
  546. endif ! (onetimer)
  547. CLOSE(output_unit)
  548. deallocate (sum_ctime_global, stat=ierror)
  549. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  550. mpi_rank_local,':',wstr,'deallocate error sum_ctime_global'
  551. deallocate (sum_wtime_global, stat=ierror)
  552. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  553. mpi_rank_local,':',wstr,'deallocate error sum_wtime_global'
  554. deallocate (count_global,stat=ierror)
  555. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  556. mpi_rank_local,':',wstr,'deallocate error count_global'
  557. deallocate (label_list,stat=ierror)
  558. if ( ierror /= 0 ) write(nulprt,*) subname,' model :',compid,' proc :',&
  559. mpi_rank_local,':',wstr,'deallocate error label_list'
  560. endif ! (mpi_rank_local == root)
  561. end subroutine oasis_timer_print
  562. ! --------------------------------------------------------------------------------
  563. !> Convert a timer name to the timer id number
  564. subroutine oasis_timer_c2i(tname,tid)
  565. character(len=*),intent(in) :: tname !< timer name
  566. integer ,intent(out) :: tid !< timer id
  567. integer :: n
  568. tid = -1
  569. do n = 1,ntimer
  570. if (trim(tname) == trim(timer(n)%label)) tid = n
  571. enddo
  572. end subroutine oasis_timer_c2i
  573. ! --------------------------------------------------------------------------------
  574. end module mod_oasis_timer