m_zeit.F90 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_zeit.F90,v 1.10 2004-04-21 22:54:49 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !-----------------------------------------------------------------------
  7. !BOP
  8. !
  9. ! !MODULE: m_zeit - a multi-timer of process times and wall-clock times
  10. !
  11. ! !DESCRIPTION:
  12. !
  13. ! !INTERFACE:
  14. module m_zeit
  15. implicit none
  16. private ! except
  17. public :: zeit_ci ! push a new name to the timer
  18. public :: zeit_co ! pop the current name on the timer
  19. public :: zeit_flush ! print per PE timing
  20. public :: zeit_allflush ! print all PE timing
  21. public :: zeit_reset ! reset the timers to its initial state
  22. ! Flags of all printable timers
  23. public :: MWTIME ! MPI_Wtime() wall-clock time
  24. public :: XWTIME ! times() wall-clock time
  25. public :: PUTIME ! times() process user time
  26. public :: PSTIME ! times() process system time
  27. public :: CUTIME ! times() user time of all child-processes
  28. public :: CSTIME ! times() system time of all child-processes
  29. public :: ALLTIME ! all of above
  30. public :: UWRATE ! (putime+cutime)/xwtime
  31. interface zeit_ci; module procedure ci_; end interface
  32. interface zeit_co; module procedure co_; end interface
  33. interface zeit_flush; module procedure flush_; end interface
  34. interface zeit_allflush; module procedure allflush_; end interface
  35. interface zeit_reset; module procedure reset_; end interface
  36. ! !REVISION HISTORY:
  37. !
  38. ! 22Jan01 - Jay Larson <larson@mcs.anl.gov> - Minor correction in
  39. ! write statements in the routines sp_balances_() and
  40. ! mp_balances_(): replaced x (single-space) descriptor
  41. ! with 1x. This is apparently strict adherance to the
  42. ! f90 standard (though the first of many, many compilers
  43. ! where it has arisen). This was for the SunOS platform.
  44. ! 05Mar98 - Jing Guo <guo@thunder> -
  45. ! . rewritten for possible MPI applications, with
  46. ! additional functionalities and new performance
  47. ! analysis information.
  48. ! . Interface names have been redefined to ensure all
  49. ! use cases to be verified.
  50. ! . removed the type(pzeit) data structure, therefore,
  51. ! limited to single _instance_ applications.
  52. ! . added additional data components for more detailed
  53. ! timing analysis.
  54. ! . used times() for the XPG4 standard conforming
  55. ! timing functions.
  56. ! . used MPI_Wtime() for the MPI standard conforming
  57. ! high-resolution timing functions.
  58. !
  59. ! 20Feb97 - Jing Guo <guo@eramus> -
  60. ! . rewritten in Fortran 90 as the first modular
  61. ! version, with a type(pzeit) data structure.
  62. !
  63. ! 10may96 - Jing G. - Add _TZEITS macro for the testing code
  64. ! 09may96 - Jing G. - Changed output format also modifed
  65. ! comments
  66. ! 11Oct95 - Jing G. - Removed earlier way of letting clock
  67. ! timing (clkknt and clktot) to be no less
  68. ! then the CPU timing, following a
  69. ! suggestion by James Abeles from Cray.
  70. ! This way, users may use the routings to
  71. ! timing multitasking speedup as well.
  72. ! 12May95 - Jing G. - Merged zeitCRAY.f and zeitIRIS.f.
  73. ! Before - ? - See zeitCRAY.f and zeitIRIS.f for more
  74. ! information. Authors of those files are
  75. ! not known to me.
  76. !
  77. ! !DESIGN ISSUES:
  78. !
  79. ! 05Mar98 - Jing Guo <guo@thunder> -
  80. ! . Removing the data structure may be consider as a
  81. ! limitation to future changes to multiple _instance_
  82. ! applications. However, it is unlikely there will be
  83. ! any neccessary multi-_intance_ application soon, if
  84. ! ever for this module.
  85. ! . Without an additional layer with the derived
  86. ! datatype, one may worry less the tricky performance
  87. ! issues associated with ci_/co_.
  88. ! . Performance issue with the flush_() calls are not
  89. ! considered.
  90. !
  91. ! 20Feb97 - Jing Guo <guo@eramus> -
  92. ! . Currently a single threaded module. May be easily
  93. ! extended to multi-threaded module by adding the name
  94. ! of an instance of the class to the argument list. It
  95. ! requires some but very limited interface extensions.
  96. ! Right now, the backward compatibility is the main
  97. ! issue.
  98. !
  99. ! 10may96 - Jing Guo <guo@eramus> -
  100. !
  101. ! + This zeit subroutine collection replaces original zeit files
  102. ! used in PSAS on both systems, UNICOS and IRIX, with following
  103. ! changes:
  104. !
  105. ! + Removed the some bugs in zeitCRAY.f that overite the
  106. ! first user defined name entry in a special situation
  107. ! (but not being able to correct in zeitCRAY.f).
  108. !
  109. ! + Unified both zeitCRAY.f and zeitIRIS.f in to one file
  110. ! (this file), that handles system dependency in only
  111. ! one subroutine syszeit_() with a couple of lines of
  112. ! differences.
  113. !
  114. ! + Added system CPU time counts for system supporting
  115. ! the function.
  116. !
  117. ! + Added some error checking and reporting functions.
  118. !
  119. ! + According to zeitCRAY.f, "zeit" is "time" in Germen.
  120. ! The name is used through the code as another name for
  121. ! "time".
  122. !
  123. ! + This version does not work for parallelized processes.
  124. !
  125. ! + Elapsed time records since the first call are used. Although
  126. ! it may loose accuracy when the values of the time records
  127. ! become large, it will keep the total time values conserved.
  128. !
  129. ! + The accuracy of the elapsed times at a IEEE real*4 accuracy
  130. ! (ffrac = 2^23 ~= 1.19e-7) should be no worse than +- 1 second
  131. ! in 97 days, if only the numerical accuracy is considered.
  132. !
  133. ! + The precision of "wall clock" time returned by syszeit_() is
  134. ! only required to be reliable upto seconds.
  135. !
  136. ! + The wall clock time for individual name tag (clkknt) is
  137. ! accumulated by adding the differences between two integer
  138. ! values, iclk and iclksv. Care must be taken to compute the
  139. ! differences of iclk and iclksv first. That is, doing
  140. !
  141. ! clkknt()=clkknt() + (iclk-iclksv)
  142. !
  143. ! not
  144. !
  145. ! clkknt()=clkknt() + iclk-iclksv
  146. !
  147. ! The latter statement may ignore the difference between the two
  148. ! integer values (iclk and iclksv).
  149. !
  150. !EOP
  151. !_______________________________________________________________________
  152. character(len=*),parameter :: myname='MCT(MPEU)::m_zeit'
  153. integer,parameter :: MWTIME = 1
  154. integer,parameter :: XWTIME = 2
  155. integer,parameter :: PUTIME = 4
  156. integer,parameter :: PSTIME = 8
  157. integer,parameter :: CUTIME = 16
  158. integer,parameter :: CSTIME = 32
  159. integer,parameter :: ALLTIME = MWTIME + XWTIME + PUTIME + &
  160. PSTIME + CUTIME + CSTIME
  161. integer,parameter :: UWRATE = 64
  162. integer,parameter :: MASKS(0:5) = &
  163. (/ MWTIME,XWTIME,PUTIME,PSTIME,CUTIME,CSTIME /)
  164. character(len=*),parameter :: ZEIT='.zeit.'
  165. character(len=8),parameter :: HEADER(0:5) = &
  166. (/ '[MWTIME]','[XWTIME]','[PUTIME]', &
  167. '[PSTIME]','[CUTIME]','[CSTIME]' /)
  168. character(len=8),parameter :: UWRHDR = '[UWRATE]'
  169. integer,parameter :: MXN= 250 ! the size of a name list
  170. ! integer,parameter :: NSZ= 32 ! the size of a name
  171. ! LPC jun/6/2000
  172. integer,parameter :: NSZ= 36 ! the size of a name
  173. integer,parameter :: MXS= 64 ! the depth of the timer stack
  174. integer,save :: nreset=0
  175. logical,save :: started=.false.
  176. logical,save :: balanced=.false.
  177. character(len=NSZ), &
  178. save :: ciname=' '
  179. character(len=NSZ), &
  180. save :: coname=' '
  181. integer,save :: mxdep=0 ! the maximum ndep value recorded
  182. integer,save :: ndep=-1 ! depth, number of net ci_()
  183. integer,save :: lnk_n(0:MXS) ! name index of the depth
  184. integer,save :: nname=-1 ! number of accounts
  185. character(len=NSZ), &
  186. save,dimension(0:MXN) :: name_l ! the accounts
  187. integer,save,dimension(0:MXN) :: knt_l ! counts of ci_() calls
  188. integer,save,dimension(0:MXN) :: level_l ! remaining ci_() counts
  189. real*8,save,dimension(0:5) :: zts_sv ! the last timings
  190. real*8,save,dimension(0:5,0:MXN) :: zts_l ! credited to a name
  191. real*8,save,dimension(0:5,0:MXN) :: szts_l ! all under the name
  192. real*8,save,dimension(0:5,0:MXN) :: szts_sv ! the last ci_ timings
  193. !=======================================================================
  194. contains
  195. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  196. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  197. !-----------------------------------------------------------------------
  198. !BOP
  199. !
  200. ! !IROUTINE: ci_ - push an entry into the timer
  201. !
  202. ! !DESCRIPTION:
  203. !
  204. ! !INTERFACE:
  205. subroutine ci_(name)
  206. use m_stdio, only : stderr
  207. use m_die, only : die
  208. use m_mpif90,only : MP_wtime
  209. implicit none
  210. character(len=*), intent(in) :: name
  211. ! !REVISION HISTORY:
  212. ! 05Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  213. !EOP
  214. !_______________________________________________________________________
  215. character(len=*),parameter :: myname_=myname//'::ci_'
  216. ! Local variables
  217. real*8,dimension(0:5) :: zts
  218. integer :: lname,iname
  219. integer :: i
  220. ! Encountered a limitation. Programming is required
  221. if(ndep >= MXS) then
  222. write(stderr,'(2a,i4)') myname_, &
  223. ': stack overflow with "'//trim(name)//'", ndep =',ndep
  224. call die(myname_)
  225. endif
  226. !--------------------------------------------------------
  227. ! Initialize the stack if it is called the first time.
  228. if(.not.started) call reset_()
  229. ! Get the current _zeits_
  230. call get_zeits(zts(1))
  231. zts(0)=MP_wtime()
  232. !--------------------------------------------------------
  233. ! Charge the ticks since the last co_() to the current level
  234. lname=lnk_n(ndep)
  235. do i=0,5
  236. zts_l(i,lname)=zts_l(i,lname) + zts(i)-zts_sv(i)
  237. end do
  238. do i=0,5
  239. zts_sv(i)=zts(i) ! update the record
  240. end do
  241. !--------------------------------------------------------
  242. ! Is the name already in the list? Case sensitive and
  243. ! space maybe sensitive if they are inbeded between non-
  244. ! space characters.
  245. !
  246. ! If the name is already in the list, the index of the
  247. ! table entry is given.
  248. !
  249. ! If the name is not in the list, a new entry will be added
  250. ! to the list, if 1) there is room, and 2)
  251. iname=lookup_(name)
  252. !--------------------------------------------------------
  253. ! push up the stack level
  254. ndep=ndep+1
  255. if(mxdep <= ndep) mxdep=ndep
  256. lnk_n(ndep)=iname
  257. knt_l(iname)=knt_l(iname)+1
  258. ! Recording the check-in time, if there is no remaining
  259. ! levels for the same name. This is used to handle
  260. ! recursive ci_() calls for the same name.
  261. if(level_l(iname) == 0) then
  262. do i=0,5
  263. szts_sv(i,iname)=zts_sv(i)
  264. end do
  265. endif
  266. ! open a level
  267. level_l(iname)=level_l(iname)+1
  268. end subroutine ci_
  269. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  270. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  271. !-----------------------------------------------------------------------
  272. !BOP
  273. !
  274. ! !IROUTINE: co_ - pop the current level
  275. !
  276. ! !DESCRIPTION:
  277. !
  278. ! !INTERFACE:
  279. subroutine co_(name,tms)
  280. use m_stdio, only : stderr
  281. use m_die, only : die
  282. use m_mpif90,only : MP_wtime
  283. implicit none
  284. character(len=*), intent(in) :: name ! account name
  285. real*8,optional,dimension(0:5,0:1),intent(out) :: tms ! timings
  286. ! The returned variable tms(0:5,0:1) contains two sets of timing
  287. ! information. tms(0:5,0) is the NET timing data charged under the
  288. ! account name only, and tms(0:5,1) is the SCOPE timing data since
  289. ! the last ci() with the same account name and at the out most level.
  290. !
  291. ! !REVISION HISTORY:
  292. ! 11Oct99 - J.W. Larson - <jlarson@dao> explicit definition of
  293. ! tms as real*8
  294. ! 05Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  295. !EOP
  296. !_______________________________________________________________________
  297. character(len=*),parameter :: myname_=myname//'::co_'
  298. real*8 :: tms0,tms1
  299. real*8,dimension(0:5) :: zts
  300. integer :: lname
  301. integer :: i
  302. ! Encountered a limitation. Programming is required
  303. if(ndep <= 0) then
  304. write(stderr,'(2a,i4)') myname_, &
  305. ': stack underflow with "'//trim(name)//'", ndep =',ndep
  306. call die(myname_)
  307. endif
  308. !--------------------------------------------------------
  309. ! Initialize the stack if it is called the first time.
  310. if(.not.started) call reset_()
  311. ! Get the current _zeits_
  312. call get_zeits(zts(1))
  313. zts(0)=MP_wtime()
  314. ! need special handling if ndep is too large or too small.
  315. lname=lnk_n(ndep)
  316. level_l(lname)=level_l(lname)-1 ! close a level
  317. do i=0,5
  318. tms0=zts(i)- zts_sv(i) ! NET by the _account_
  319. tms1=zts(i)-szts_sv(i,lname) ! within its SCOPE
  320. zts_l(i,lname)= zts_l(i,lname) + tms0
  321. if(level_l(lname) == 0) &
  322. szts_l(i,lname)=szts_l(i,lname) + tms1
  323. zts_sv(i)=zts(i)
  324. if(present(tms)) then
  325. ! Return the timings of the current call segment
  326. !
  327. ! tms(:,0) is for the NET timing data, that have been charged
  328. ! to this account.
  329. !
  330. ! tms(:,1) is for the SCOPE timing data since the ci() of the
  331. ! same account name at the out most level.
  332. !
  333. tms(i,0)=tms0
  334. tms(i,1)=tms1 ! only the sub-segments
  335. endif
  336. end do
  337. ! Record the unbalanced ci/co. Name .void. is supplied for
  338. ! backward compartible calls of pzeitend()
  339. if(name /= '.void.'.and.balanced) then
  340. balanced = lname == MXN .or. name == name_l(lname)
  341. if(.not.balanced) then
  342. ciname=name_l(lname)
  343. coname=name
  344. endif
  345. endif
  346. ! pop (need special handling of ndep too large or too small.
  347. ndep=ndep-1
  348. end subroutine co_
  349. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  350. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  351. !-----------------------------------------------------------------------
  352. !BOP
  353. !
  354. ! !IROUTINE: reset_ - reset module m_zeit to an initial state
  355. !
  356. ! !DESCRIPTION:
  357. !
  358. ! !INTERFACE:
  359. subroutine reset_()
  360. use m_mpif90,only : MP_wtime
  361. implicit none
  362. ! !REVISION HISTORY:
  363. ! 04Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  364. !EOP
  365. !_______________________________________________________________________
  366. character(len=*),parameter :: myname_=myname//'::reset_'
  367. integer :: i
  368. ! keep tracking the number of reset_() calls
  369. nreset=nreset+1
  370. started=.true.
  371. balanced=.true.
  372. ! Start timing
  373. call get_zeits(zts_sv(1))
  374. zts_sv(0)=MP_wtime()
  375. ! Sign in the module name for the overheads (.eqv. ci_(ZEIT))
  376. nname=0
  377. name_l(nname)=ZEIT
  378. knt_l(nname)=1
  379. ndep =0
  380. lnk_n(ndep)=nname
  381. ! Initialize the timers.
  382. do i=0,5
  383. zts_l(i,nname)=0.
  384. szts_l(i,nname)=0.
  385. szts_sv(i,nname)=zts_sv(i)
  386. end do
  387. level_l(nname)=1
  388. end subroutine reset_
  389. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  390. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  391. !-----------------------------------------------------------------------
  392. !BOP
  393. !
  394. ! !IROUTINE: lookup_ search/insert a name
  395. !
  396. ! !DESCRIPTION:
  397. !
  398. ! !INTERFACE:
  399. function lookup_(name)
  400. implicit none
  401. character(len=*),intent(in) :: name
  402. integer :: lookup_
  403. ! !REVISION HISTORY:
  404. ! 04Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  405. !EOP
  406. !_______________________________________________________________________
  407. character(len=*),parameter :: myname_=myname//'::lookup_'
  408. logical :: found
  409. integer :: ith
  410. integer :: i
  411. ith=-1
  412. found=.false.
  413. do while(.not.found.and. ith < min(nname,MXN))
  414. ith=ith+1
  415. found = name == name_l(ith)
  416. end do
  417. if(.not.found) then
  418. found = nname >= MXN ! Can not handle too many accounts?
  419. ith=MXN ! Then use the account for ".foo."
  420. if(.not.found) then ! Otherwise, add a new account.
  421. nname=nname+1
  422. ith=nname
  423. name_l(ith)=name
  424. if(ith==MXN) name_l(ith)='.foo.'
  425. ! Initialize a new account
  426. do i=0,5
  427. zts_l(i,ith)=0.
  428. szts_l(i,ith)=0.
  429. end do
  430. level_l(ith)=0
  431. endif
  432. endif
  433. lookup_=ith
  434. end function lookup_
  435. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  436. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  437. !-----------------------------------------------------------------------
  438. !BOP
  439. !
  440. ! !IROUTINE: flush_ - print the timing data
  441. !
  442. ! !DESCRIPTION:
  443. !
  444. ! !INTERFACE:
  445. subroutine flush_(lu,umask)
  446. use m_stdio, only : stderr
  447. use m_ioutil, only : luflush
  448. use m_die, only : die
  449. use m_mpif90,only : MP_wtime
  450. implicit none
  451. integer,intent(in) :: lu ! logical unit for the output
  452. integer,optional,intent(in) :: umask
  453. ! !REVISION HISTORY:
  454. ! 05Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  455. !EOP
  456. !_______________________________________________________________________
  457. character(len=*),parameter :: myname_=myname//'::flush_'
  458. integer :: imask
  459. real*8,dimension(0:5) :: zts
  460. integer :: i,ier
  461. ! specify which timer to print
  462. imask=MWTIME
  463. if(present(umask)) imask=umask
  464. ! write a <newline>
  465. write(lu,*,iostat=ier)
  466. if(ier /= 0) then
  467. write(stderr,'(2a,i3)') myname_,': can not write(), unit =',lu
  468. call die(myname_)
  469. endif
  470. if(.not.balanced) write(lu,'(5a)') myname_, &
  471. ': ci/co unbalanced, ',trim(ciname),'/',trim(coname)
  472. call luflush(lu)
  473. ! latest times, but not closing on any entry
  474. call get_zeits(zts(1))
  475. zts(0)=MP_wtime()
  476. ! Print selected tables
  477. do i=0,5
  478. if(iand(MASKS(i),imask) /= 0) &
  479. call sp_balances_(lu,i,zts(i))
  480. end do
  481. #ifdef TODO
  482. if(iand(UWRATE,imask) /= 0) call sp_rate_(lu,zts)
  483. #endif
  484. call luflush(lu)
  485. end subroutine flush_
  486. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  487. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  488. !-----------------------------------------------------------------------
  489. !BOP
  490. !
  491. ! !IROUTINE: sp_balances_ - print a table of a given timer
  492. !
  493. ! !DESCRIPTION:
  494. !
  495. ! !INTERFACE:
  496. subroutine sp_balances_(lu,itm,zti)
  497. implicit none
  498. integer,intent(in) :: lu
  499. integer,intent(in) :: itm
  500. real*8,intent(in) :: zti
  501. ! !REVISION HISTORY:
  502. ! 06Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  503. ! 22Jan01 - Jay Larson <larson@mcs.anl.gov> - Minor correction in
  504. ! A write statement: replaced x (single-space) descriptor
  505. ! with 1x. This is apparently strict adherance to the
  506. ! f90 standard (though the first of many, many compilers
  507. ! where it has arisen). This was for the SunOS platform.
  508. ! 24Feb01 - Jay Larson <larson@mcs.anl.gov> - Extra decimal place in
  509. ! timing numbers (some reformatting will be necessary).
  510. !EOP
  511. !_______________________________________________________________________
  512. character(len=*),parameter :: myname_=myname//'::sp_balances_'
  513. real*8,parameter :: res=.001 ! (sec)
  514. integer,parameter :: lnmax=12
  515. character(len=max(NSZ,lnmax)) :: name
  516. character(len=1) :: tag
  517. character(len=4) :: num
  518. integer :: zt_min,zt_sec
  519. integer :: sz_min,sz_sec
  520. integer :: l,i,ln
  521. real*8 :: sz0
  522. real*8 :: zt,zt_percent,zt_percall
  523. real*8 :: sz,sz_percent
  524. ! The total time is given in the ZEIT bin
  525. sz0=szts_l(itm,0)
  526. if(level_l(0) /= 0) sz0=sz0 + zti - szts_sv(itm,0)
  527. sz0=max(res,sz0)
  528. write(lu,'(a,t14,a,t21,a,t31,a,t52,a)') &
  529. HEADER(itm), 'counts','period', &
  530. 'NET m:s %', &
  531. 'SCOPE m:s %'
  532. !23.|....1....|....2....|....3....|....4....|....5....|....6....|....7..
  533. ![MWTIME] counts period NET m:s % SCOPE m:s %
  534. !-----------------------------------------------------------------------
  535. !zeit. ( 3s 3d 3) 333.3 33:33 3.3+ 333.3 33:33 3.3+
  536. !sub 333 33.3 333.3 33:33 3.3% 333.3 33:33 3.3%
  537. write(lu,'(80a)') ('-',i=1,72)
  538. do l=0,min(MXN,nname)
  539. zt= zts_l(itm,l)
  540. sz=szts_l(itm,l)
  541. tag='%'
  542. if(level_l(l) /= 0) then
  543. zt=zt + zti - zts_sv(itm)
  544. sz=sz + zti - szts_sv(itm,l)
  545. tag='+'
  546. endif
  547. zt_percall=zt/max(1,knt_l(l))
  548. zt_percent=100.*zt/sz0
  549. sz_percent=100.*sz/sz0
  550. zt_sec=nint(zt)
  551. zt_min= zt_sec/60
  552. zt_sec=mod(zt_sec,60)
  553. sz_sec=nint(sz)
  554. sz_min= sz_sec/60
  555. sz_sec=mod(sz_sec,60)
  556. name=name_l(l)
  557. ln=max(len_trim(name),lnmax)
  558. select case(l)
  559. case(0)
  560. write(num,'(i4)') mxdep
  561. ! write(lu,'(2(a,i3),2a,t26,2(1x,f7.1,1x,i4.2,a,i2.2,1x,f5.1,a))')&
  562. write(lu,'(2(a,i3),2a,t26,2(1x,f8.2,1x,i4.2,a,i2.2,1x,f6.2,a))')&
  563. name(1:ln),nreset,'s',ndep,'/',num, &
  564. zt,zt_min,':',zt_sec,zt_percent,tag, &
  565. sz,sz_min,':',sz_sec,sz_percent,tag
  566. ! write(lu,'(2a,3(i3,a),t26,2(x,f7.1,x,i4.2,a,i2.2,x,f5.1,a))')&
  567. ! name(1:ln),'(',nreset,'s',ndep,'d',mxdep,')', &
  568. case default
  569. if(len_trim(name) < lnmax)then
  570. ! write(lu,'(a,1x,i5,1x,f6.1,2(1x,f7.1,1x,i4.2,a,i2.2,1x,f5.1,a))') &
  571. write(lu,'(a,1x,i5,1x,f7.2,2(1x,f8.2,1x,i4.2,a,i2.2,1x,f6.2,a))') &
  572. name(1:ln),knt_l(l),zt_percall, &
  573. zt,zt_min,':',zt_sec,zt_percent,tag, &
  574. sz,sz_min,':',sz_sec,sz_percent,tag
  575. else
  576. write(lu,'(a)')name(1:ln)
  577. ! write(lu,'(13x,i5,1x,f6.1,2(1x,f7.1,1x,i4.2,a,i2.2,1x,f5.1,a))') &
  578. write(lu,'(13x,i5,1x,f7.2,2(1x,f8.2,1x,i4.2,a,i2.2,1x,f6.2,a))') &
  579. knt_l(l),zt_percall, &
  580. zt,zt_min,':',zt_sec,zt_percent,tag, &
  581. sz,sz_min,':',sz_sec,sz_percent,tag
  582. endif
  583. end select
  584. end do
  585. write(lu,'(80a)') ('-',i=1,72)
  586. end subroutine sp_balances_
  587. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  588. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  589. !-----------------------------------------------------------------------
  590. !BOP
  591. !
  592. ! !IROUTINE: allflush_ - print a summary of all PEs.
  593. !
  594. ! !DESCRIPTION:
  595. !
  596. ! !INTERFACE:
  597. subroutine allflush_(comm,root,lu,umask)
  598. use m_stdio, only : stderr
  599. use m_ioutil, only : luflush
  600. use m_die, only : die
  601. use m_mpif90,only : MP_wtime,MP_type
  602. use m_mpif90,only : MP_comm_size,MP_comm_rank
  603. use m_SortingTools,only : IndexSet,IndexSort
  604. implicit none
  605. integer,intent(in) :: comm
  606. integer,intent(in) :: root
  607. integer,intent(in) :: lu
  608. integer,optional,intent(in) :: umask
  609. ! !REVISION HISTORY:
  610. ! 09Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  611. !EOP
  612. !_______________________________________________________________________
  613. character(len=*),parameter :: myname_=myname//'::allflush_'
  614. integer myID,nPE
  615. integer :: imask
  616. real*8,dimension(0:5) :: zts
  617. real*8,dimension(0:5,0:1,0:MXN) :: ztbf
  618. real*8,dimension(:,:,:,:),allocatable :: ztmp
  619. integer,dimension(0:MXN) :: indx_
  620. integer :: mnm
  621. integer :: i,l
  622. integer :: nbf,ier
  623. integer :: mp_Type_ztbf
  624. mp_Type_ztbf=MP_type(ztbf(0,0,0))
  625. imask=MWTIME
  626. if(present(umask)) imask=umask
  627. if(imask==0) return
  628. call get_zeits(zts(1))
  629. zts(0)=MP_wtime()
  630. ! Update the accounts and prepare for the messages
  631. mnm=min(MXN,nname)
  632. do l=0,mnm
  633. do i=0,5
  634. ztbf(i,0,l)= zts_l(i,l)
  635. ztbf(i,1,l)=szts_l(i,l)
  636. end do
  637. if(level_l(l) /= 0) then
  638. ! Update the current accounts.
  639. do i=0,5
  640. ztbf(i,0,l)=ztbf(i,0,l) + zts(i) - zts_sv(i )
  641. ztbf(i,1,l)=ztbf(i,1,l) + zts(i) -szts_sv(i,l)
  642. end do
  643. endif
  644. end do
  645. nbf=size(ztbf(0:5,0:1,0:mnm))
  646. call MP_comm_rank(comm,myID,ier)
  647. if(ier /= 0) then
  648. write(stderr,'(2a,i3)') myname_, &
  649. ': MP_comm_rank() error, ier =',ier
  650. call die(myname_)
  651. endif
  652. ! An urgent hack for now. Need to be fixed later. J.G.
  653. indx_(0)=0
  654. call IndexSet( nname,indx_(1:mnm))
  655. call IndexSort(nname,indx_(1:mnm),name_l(1:mnm))
  656. if(myID /= root) then
  657. call MPI_gather((ztbf(0:5,0:1,indx_(0:mnm))),nbf,mp_Type_ztbf, &
  658. ztbf,nbf,mp_Type_ztbf,root,comm,ier )
  659. if(ier /= 0) then
  660. write(stderr,'(2a,i3)') myname_, &
  661. ': MPI_gather(!root) error, ier =',ier
  662. call die(myname_)
  663. endif
  664. else
  665. call MP_comm_size(comm,nPE,ier)
  666. if(ier /= 0) then
  667. write(stderr,'(2a,i3)') myname_, &
  668. ': MP_comm_size() error, ier =',ier
  669. call die(myname_)
  670. endif
  671. allocate(ztmp(0:5,0:1,0:mnm,0:nPE-1),stat=ier)
  672. if(ier /= 0) then
  673. write(stderr,'(2a,i4)') myname_, &
  674. ': allocate(zts) error, stat =',ier
  675. call die(myname_)
  676. endif
  677. call MPI_gather((ztbf(0:5,0:1,indx_(0:mnm))),nbf,mp_Type_ztbf, &
  678. ztmp,nbf,mp_Type_ztbf,root,comm,ier )
  679. if(ier /= 0) then
  680. write(stderr,'(2a,i3)') myname_, &
  681. ': MPI_gather(root) error, ier =',ier
  682. call die(myname_)
  683. endif
  684. ! write a <newline>
  685. write(lu,*,iostat=ier)
  686. if(ier /= 0) then
  687. write(stderr,'(2a,i3)') myname_,': can not write(), unit =',lu
  688. call die(myname_)
  689. endif
  690. call luflush(lu)
  691. do i=0,5
  692. if(iand(MASKS(i),imask) /= 0) &
  693. call mp_balances_(lu,i,nPE,ztmp,indx_)
  694. end do
  695. #ifdef TODO
  696. if(iand(UWRATE,imask) /= 0) call mp_rate_(lu,nPE,ztmp)
  697. #endif
  698. deallocate(ztmp,stat=ier)
  699. if(ier /= 0) then
  700. write(stderr,'(2a,i4)') myname_, &
  701. ': deallocate(zts) error, stat =',ier
  702. call die(myname_)
  703. endif
  704. endif
  705. call luflush(lu)
  706. end subroutine allflush_
  707. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  708. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  709. !-----------------------------------------------------------------------
  710. !BOP
  711. !
  712. ! !IROUTINE: mp_balances_ - summarize the timing data of all PEs
  713. !
  714. ! !DESCRIPTION:
  715. !
  716. ! \newcommand{\tb}{\overline{t}}
  717. !
  718. ! \verb"mp_balances_"() summarizes the timing data of all PEs
  719. ! with quantified load balancing measures:
  720. ! \begin{eqnarray*}
  721. ! x &=& \frac{\max(t) - \tb}{N\tb} \times 100\% \\
  722. ! i &=& \frac{\max(t) - \tb}{\max(t)} \times 100\% \\
  723. ! r &=& \frac{1}{N\tb} \sum^{t>\tb}{(t-\tb)}
  724. ! \times 100\%
  725. ! \end{eqnarray*}
  726. ! where
  727. ! \begin{center}
  728. ! \begin{tabular}{rl}
  729. ! $t$: & time by any process element \\
  730. ! $\tb$: & mean time by all process elements \\
  731. ! $x$: & the ma{\bf x}imum percentage load deviation \\
  732. ! $i$: & percentage {\bf i}dle process-time or
  733. ! load {\bf i}mbalance \\
  734. ! $r$: & percentage {\bf r}elocatable loads \\
  735. ! $N$: & {\bf n}umber of process elements
  736. ! \end{tabular}
  737. ! \end{center}
  738. !
  739. ! !INTERFACE:
  740. subroutine mp_balances_(lu,itm,nPE,ztmp,indx)
  741. implicit none
  742. integer,intent(in) :: lu
  743. integer,intent(in) :: itm
  744. integer,intent(in) :: nPE
  745. real*8,dimension(0:,0:,0:,0:),intent(in) :: ztmp
  746. integer,dimension(0:),intent(in) :: indx
  747. ! !REVISION HISTORY:
  748. ! 10Mar98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
  749. ! 22Jan01 - Jay Larson <larson@mcs.anl.gov> - Minor correction in
  750. ! A write statement: replaced x (single-space) descriptor
  751. ! with 1x. This is apparently strict adherance to the
  752. ! f90 standard (though the first of many, many compilers
  753. ! where it has arisen). This was for the SunOS platform.
  754. ! 25Feb01 - R. Jacob <jacob@mcs.anl.gov> change number of
  755. ! decimal places from 1 to 4.
  756. !EOP
  757. !_______________________________________________________________________
  758. character(len=*),parameter :: myname_=myname//'::mp_balances_'
  759. real*8,parameter :: res=.001 ! (sec)
  760. integer,parameter :: lnmax=12
  761. character(len=max(NSZ,lnmax)) :: name
  762. character(len=4) :: num
  763. integer :: i,k,l,ln,lx
  764. ! NET times
  765. integer :: ix_o
  766. real*8 :: zts_o,zta_o,ztm_o,ztr_o
  767. integer :: x_o,i_o,r_o
  768. ! SCOPE times
  769. integer :: ix_s
  770. real*8 :: zts_s,zta_s,ztm_s,ztr_s
  771. integer :: x_s,i_s,r_s
  772. write(num,'(i4)') nPE
  773. write(lu,'(3a,t18,a,t58,a)') &
  774. HEADER(itm),'x',adjustl(num), &
  775. 'NET avg max imx x% r% i%', &
  776. 'SCP avg max imx x% r% i%'
  777. !23.|....1....|....2....|....3....|....4....|....5....|....6....|....7..
  778. !MWTIME]x3 NET avg max imx x% r% i% SCP avg max imx x% r% i%
  779. !-----------------------------------------------------------------------
  780. !zeit. 333333.3 33333.3 333 33 33 33 333333.3 33333.3 333 33 33 33
  781. write(lu,'(91a)') ('-',i=1,91)
  782. do l=0,min(MXN,nname)
  783. ! sum() of all processes
  784. zts_o=0.
  785. zts_s=0.
  786. ! indices of max() of all processes
  787. ix_o=0
  788. ix_s=0
  789. do k=0,nPE-1
  790. zts_o=zts_o+ztmp(itm,0,l,k) ! compute sum()
  791. zts_s=zts_s+ztmp(itm,1,l,k) ! compute sum()
  792. if(ztmp(itm,0,l,ix_o) < ztmp(itm,0,l,k)) ix_o=k
  793. if(ztmp(itm,1,l,ix_s) < ztmp(itm,1,l,k)) ix_s=k
  794. end do
  795. zta_o=zts_o/max(1,nPE) ! compute mean()
  796. zta_s=zts_s/max(1,nPE) ! compute mean()
  797. ztr_o=0.
  798. ztr_s=0.
  799. do k=0,nPE-1
  800. if(ztmp(itm,0,l,k) > zta_o) ztr_o=ztr_o+ztmp(itm,0,l,k)-zta_o
  801. if(ztmp(itm,1,l,k) > zta_s) ztr_s=ztr_s+ztmp(itm,1,l,k)-zta_s
  802. end do
  803. ztm_o=ztmp(itm,0,l,ix_o)
  804. ztm_s=ztmp(itm,1,l,ix_s)
  805. lx=indx(l)
  806. name=name_l(lx)
  807. ln=max(len_trim(name),lnmax)
  808. x_o=nint(100.*(ztm_o-zta_o)/max(zts_o,res))
  809. r_o=nint(100.* ztr_o /max(zts_o,res))
  810. i_o=nint(100.*(ztm_o-zta_o)/max(ztm_o,res))
  811. x_s=nint(100.*(ztm_s-zta_s)/max(zts_s,res))
  812. r_s=nint(100.* ztr_s /max(zts_s,res))
  813. i_s=nint(100.*(ztm_s-zta_s)/max(ztm_s,res))
  814. write(lu,'(a,2(3x,f10.6,3x,f10.6,1x,z3.3,3i3,1x))') &
  815. name(1:ln), &
  816. zta_o,ztm_o,ix_o,x_o,r_o,i_o, &
  817. zta_s,ztm_s,ix_s,x_s,r_s,i_s
  818. end do
  819. write(lu,'(91a)') ('-',i=1,91)
  820. end subroutine mp_balances_
  821. !=======================================================================
  822. end module m_zeit
  823. !.