C $Header: /u/gcmpack/MITgcm/eesupp/src/timers.F,v 1.19 2005/06/07 20:52:42 edhill Exp $
C $Name: $
#include "CPP_EEOPTIONS.h"
C-- File utils.F: General purpose support routines
C-- Contents
C-- TIMER_INDEX - Returns index associated with timer name.
C-- M TIMER_CONTROL - Implements timer functions for given machine.
C-- TIMER_PRINT - Print CPU timer statitics.
C-- TIMER_PRINTALL - Prints all CPU timers statistics.
C-- TIMER_START - Starts CPU timer for code section.
C-- TIMER_STOP - Stop CPU tier for code section.
C-- Routines marked "M" contain specific machine dependent code.
C-- Routines marked "U" contain UNIX OS calls.
CGG Modified following A. Biastoch for use with SP3. Is backwards
CGG compatible. G. Gebbie, gebbie@mit.edu, 20 Oct 2001, Scripps.
CBOP
C !ROUTINE: TIMER_INDEX
C !INTERFACE:
INTEGER FUNCTION TIMER_INDEX (
I name,timerNames,maxTimers,nTimers )
IMPLICIT NONE
C !DESCRIPTION:
C *==========================================================*
C | FUNCTION TIMER\_INDEX
C | o Timing support routine.
C *==========================================================*
C | Return index in timer data structure of timer named
C | by the function argument "name".
C *==========================================================*
C !INPUT/OUTPUT PARAMETERS:
C == Routine arguements ==
C maxTimers :: Total number of timers allowed
C nTimers :: Current number of timers
C name :: Name of timer to find
C timerNames :: List of valid timer names
INTEGER maxTimers
INTEGER nTimers
CHARACTER*(*) name
CHARACTER*(*) timerNames(maxTimers)
C !LOCAL VARIABLES:
C == Local variables ==
C I :: Index variable
INTEGER I
CEOP
C
TIMER_INDEX = 0
IF ( name .EQ. ' ' ) THEN
TIMER_INDEX = -1
ELSE
DO 10 I = 1, nTimers
IF ( name .NE. timerNames(I) ) GOTO 10
TIMER_INDEX = I
GOTO 11
10 CONTINUE
11 CONTINUE
ENDIF
RETURN
END
CBOP
C !ROUTINE: TIMER_CONTROL
C !INTERFACE:
SUBROUTINE TIMER_CONTROL ( name , action , callProc , myThreadId )
IMPLICIT NONE
C !DESCRIPTION:
C *==========================================================*
C | SUBROUTINE TIMER\_CONTROL |
C | o Timing routine. |
C *==========================================================*
C | User callable interface to timing routines. Timers are |
C | created, stopped, started and queried only through this |
C | rtouine. |
C *==========================================================*
C !USES:
#include "SIZE.h"
#include "EEPARAMS.h"
#include "EESUPPORT.h"
INTEGER TIMER_INDEX
INTEGER IFNBLNK
INTEGER ILNBLNK
EXTERNAL
EXTERNAL
EXTERNAL
C !INPUT/OUTPUT PARAMETERS:
C name :: name of the timer
C action :: operation to perform with this timer
C callProc :: procedure calling this routine
C myThreadId :: instance number of this thread
CHARACTER*(*) name
CHARACTER*(*) action
CHARACTER*(*) callProc
INTEGER myThreadId
C
C !LOCAL VARIABLES:
C maxTimers :: Total numer of timer allowed
C maxString :: Max length of a timer name
INTEGER maxTimers
INTEGER maxString
PARAMETER ( maxTimers = 40 )
PARAMETER ( maxString = 80 )
C timerStarts :: Timer counters for each timer and each thread
C timerStops
C timerUser
C timerWall
C timerSys
C timerT0User
C timerT0Wall
C timerT0Sys
C timerStatus :: START/STOP/RUNNING Status of the timer
C timerNameLen :: Length of timer name
C timerNames :: Table of timer names
C nTimers :: Number of active timers
INTEGER timerStarts( maxTimers , MAX_NO_THREADS)
SAVE timerStarts
INTEGER timerStops ( maxTimers , MAX_NO_THREADS)
SAVE timerStops
Real*8 timerUser ( maxTimers , MAX_NO_THREADS)
SAVE timerUser
Real*8 timerWall ( maxTimers , MAX_NO_THREADS)
SAVE timerWall
Real*8 timerSys ( maxTimers , MAX_NO_THREADS)
SAVE timerSys
Real*8 timerT0User( maxTimers , MAX_NO_THREADS)
SAVE timerT0User
Real*8 timerT0Wall( maxTimers , MAX_NO_THREADS)
SAVE timerT0Wall
Real*8 timerT0Sys ( maxTimers , MAX_NO_THREADS)
SAVE timerT0Sys
INTEGER timerStatus( maxTimers , MAX_NO_THREADS)
SAVE timerStatus
INTEGER timerNameLen( maxTimers , MAX_NO_THREADS)
SAVE timerNameLen
CHARACTER*(maxString) timerNames( maxTimers , MAX_NO_THREADS)
SAVE timerNames
INTEGER nTimers(MAX_NO_THREADS)
CHARACTER*(maxString) tmpName
CHARACTER*(maxString) tmpAction
INTEGER iTimer
INTEGER ISTART
INTEGER IEND
INTEGER STOPPED
PARAMETER ( STOPPED = 0 )
INTEGER RUNNING
PARAMETER ( RUNNING = 1 )
CHARACTER*(*) STOP
PARAMETER ( STOP = 'STOP' )
CHARACTER*(*) START
PARAMETER ( START = 'START' )
CHARACTER*(*) PRINT
PARAMETER ( PRINT = 'PRINT' )
CHARACTER*(*) PRINTALL
PARAMETER ( PRINTALL = 'PRINTALL' )
INTEGER I
Real*8 userTime
Real*8 systemTime
Real*8 wallClockTime
CHARACTER*(MAX_LEN_MBUF) msgBuffer
DATA nTimers /MAX_NO_THREADS*0/
SAVE nTimers
CEOP
C
ISTART = IFNBLNK(name)
IEND = ILNBLNK(name)
IF ( IEND - ISTART + 1 .GT. maxString ) GOTO 901
IF ( ISTART .NE. 0 ) THEN
tmpName = name(ISTART:IEND)
CALL UCASE( tmpName )
ELSE
tmpName = ' '
ENDIF
ISTART = IFNBLNK(action)
IEND = ILNBLNK(action)
IF ( ISTART .EQ. 0 ) GOTO 902
IF ( IEND - ISTART + 1 .GT. maxString ) GOTO 903
tmpAction = action(ISTART:IEND)
CALL UCASE( tmpAction )
C
iTimer=TIMER_INDEX(tmpName,timerNames(1,myThreadId),
& maxTimers,nTimers(myThreadId))
C
IF ( tmpAction .EQ. START ) THEN
IF ( iTimer .EQ. 0 ) THEN
IF ( nTimers(myThreadId) .EQ. maxTimers ) GOTO 904
nTimers(myThreadId) = nTimers(myThreadId) + 1
iTimer = nTimers(myThreadId)
timerNames(iTimer,myThreadId) = tmpName
timerNameLen(iTimer,myThreadId) =
& ILNBLNK(tmpName)-IFNBLNK(tmpName)+1
timerUser(iTimer,myThreadId) = 0.
timerSys (iTimer,myThreadId) = 0.
timerWall(iTimer,myThreadId) = 0.
timerStarts(iTimer,myThreadId) = 0
timerStops (iTimer,myThreadId) = 0
timerStatus(iTimer,myThreadId) = STOPPED
ENDIF
IF ( timerStatus(iTimer,myThreadId) .NE. RUNNING ) THEN
CALL TIMER_GET_TIME( userTime, systemTime, wallClockTime )
timerT0User(iTimer,myThreadId) = userTime
timerT0Sys(iTimer,myThreadId) = systemTime
timerT0Wall(iTimer,myThreadId) = wallClockTime
timerStatus(iTimer,myThreadId) = RUNNING
timerStarts(iTimer,myThreadId) =
& timerStarts(iTimer,myThreadId)+1
ENDIF
ELSEIF ( tmpAction .EQ. STOP ) THEN
IF ( iTimer .EQ. 0 ) GOTO 905
IF ( timerStatus(iTimer,myThreadId) .EQ. RUNNING ) THEN
CALL TIMER_GET_TIME( userTime, systemTime, wallClockTime )
timerUser(iTimer,myThreadId) =
& timerUser(iTimer,myThreadId) +
& userTime -
& timerT0User(iTimer,myThreadId)
timerSys (iTimer,myThreadId) =
& timerSys(iTimer,myThreadId) +
& systemTime -
& timerT0Sys(iTimer,myThreadId)
timerWall(iTimer,myThreadId) =
& timerWall(iTimer,myThreadId) +
& wallClockTime -
& timerT0Wall(iTimer,myThreadId)
timerStatus(iTimer,myThreadId) = STOPPED
timerStops (iTimer,myThreadId) =
& timerStops (iTimer,myThreadId)+1
ENDIF
ELSEIF ( tmpAction .EQ. PRINT ) THEN
IF ( iTimer .EQ. 0 ) GOTO 905
WRITE(msgBuffer,*)
& ' Seconds in section "',
& timerNames(iTimer,myThreadId)(1:timerNameLen(iTimer,myThreadId))
& ,'":'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' User time:',
& timerUser(iTimer,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' System time:',
& timerSys(iTimer,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' Wall clock time:',
& timerWall(iTimer,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' No. starts:',
& timerStarts(iTimer,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' No. stops:',
& timerStops(iTimer,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
ELSEIF ( tmpAction .EQ. PRINTALL ) THEN
DO 10 I = 1, nTimers(myThreadId)
WRITE(msgBuffer,*) ' Seconds in section "',
& timerNames(I,myThreadId)(1:timerNameLen(I,myThreadId))
& ,'":'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' User time:',
& timerUser(I,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' System time:',
& timerSys(I,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' Wall clock time:',
& timerWall(I,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' No. starts:',
& timerStarts(I,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*) ' No. stops:',
& timerStops(I,myThreadId)
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
10 CONTINUE
ELSE
GOTO 903
ENDIF
C
1000 CONTINUE
C
RETURN
901 CONTINUE
WRITE(msgBuffer,'(A)')
&' '
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*** WARNING WARNING WARNING WARNING WARNING WARNING ***'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'procedure: "',callProc,'".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'Timer name "',name(ISTART:IEND),'" is invalid.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' Names must have fewer than',maxString+1,' characters.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*******************************************************'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
GOTO 1000
902 CONTINUE
WRITE(msgBuffer,*)
&' '
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*** WARNING WARNING WARNING WARNING WARNING WARNING ***'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'procedure: "',callProc,'".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' No timer action specified.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' Valid actions are:'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' "START", "STOP", "PRINT" and "PRINTALL".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*******************************************************'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
GOTO 1000
903 CONTINUE
WRITE(msgBuffer,*)
&' '
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*** WARNING WARNING WARNING WARNING WARNING WARNING ***'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'procedure: "',callProc,'".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'Timer action"',name(ISTART:IEND),'" is invalid.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' Valid actions are:'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' "START", "STOP", "PRINT" and "PRINTALL".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*******************************************************'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
GOTO 1000
904 CONTINUE
WRITE(msgBuffer,*)
&' '
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*** WARNING WARNING WARNING WARNING WARNING WARNING ***'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'procedure: "',callProc,'".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'Timer "',name(ISTART:IEND),'" cannot be created.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' Only ',maxTimers,' timers are allowed.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*******************************************************'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
GOTO 1000
905 CONTINUE
WRITE(msgBuffer,*)
&' '
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*** WARNING WARNING WARNING WARNING WARNING WARNING ***'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'procedure: "',callProc,'".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'Timer name is blank.'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&' A name must be used with "START", "STOP" or "PRINT".'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
WRITE(msgBuffer,*)
&'*******************************************************'
CALL PRINT_MESSAGE(msgBuffer,standardMessageUnit,
& SQUEEZE_RIGHT,myThreadId)
GOTO 1000
END
CBOP
C !ROUTINE: TIMER_GET_TIME
C !INTERFACE:
SUBROUTINE TIMER_GET_TIME(
O userTime,
O systemTime,
O wallClockTime )
IMPLICIT NONE
C !DESCRIPTION:
C *==========================================================*
C | SUBROUTINE TIMER\_GET\_TIME
C | o Query system timer routines.
C *==========================================================*
C | Routine returns total elapsed time for program so far.
C | Three times are returned that conventionally are used as
C | user time, system time and wall-clock time. Not all these
C | numbers are available on all machines.
C *==========================================================*
C !INPUT/OUTPUT PARAMETERS:
C userTime :: User time returned
C systemTime :: System time returned
C wallClockTime :: Wall clock time returned
Real*8 userTime
Real*8 systemTime
Real*8 wallClockTime
C !USES:
CEH3 This needs to be further cleaned up using a HAVE_CLOC define
CEH3 that is diagnosed by genmake
CEH3 #ifndef HAVE_FDATE
Real*8 system_time, user_time, timenow
CEH3 #else
#ifdef TARGET_AIX
Real*4 ETIME_
EXTERNAL
#else
Real*4 ETIME
EXTERNAL
#endif
CEH3 #endif
C !LOCAL VARIABLES:
C ACTUAL, TARRAY, :: Temps. to hold times
C wTime
Real*4 ACTUAL, TARRAY(2)
Real*8 wtime
CEOP
C Real*8 MPI_Wtime
C EXTERNAL MPI_Wtime
#ifndef IGNORE_TIME
CCE107 Fixed for AIX and UNICOS
#ifdef TARGET_AIX
ACTUAL = ETIME_(TARRAY)
userTime = TARRAY(1)
systemTime = TARRAY(2)
wallClockTime = timenow()
#elif (defined (TARGET_T3E) defined (TARGET_CRAY_VECTOR))
userTime = SECOND()
systemTime = 0.
wallClockTime = SECONDR()
#else
#ifdef HAVE_ETIME
ACTUAL = ETIME(TARRAY)
#else
TARRAY(1) = user_time()
TARRAY(2) = system_time()
#endif
userTime = TARRAY(1)
systemTime = TARRAY(2)
#ifdef HAVE_CLOC
CALL CLOC(wTime)
#else
wtime = timenow()
#endif /* HAVE_CLOC */
wallClockTime = wtime
#endif /* CRAY defines */
CCE107 Sometimes MPI_Wtime has better resolution...
#if (defined (ALLOW_USE_MPI) defined (USE_MPI_WTIME))
wtime = MPI_Wtime()
wallClockTime = wtime
#endif /* ALLOW_USE_MPI && USE_MPI_WTIME */
#else /* IGNORE_TIME */
wtime = 0.0
#endif /* IGNORE_TIME */
RETURN
END
CBOP
C !ROUTINE: TIMER_PRINTALL
C !INTERFACE:
SUBROUTINE TIMER_PRINTALL( myThreadId )
IMPLICIT NONE
C !DESCRIPTION:
C *==========================================================*
C | SUBROUTINE TIMER\_PRINTALL
C | o Print timer information
C *==========================================================*
C | Request print out of table of timing from all timers.
C *==========================================================*
C !INPUT PARAMETERS:
C myThreadId :: This threads number
INTEGER myThreadId
CEOP
CALL TIMER_CONTROL( ' ', 'PRINTALL', 'TIMER_PRINTALL' ,
& myThreadId )
C
RETURN
END
CBOP
C !ROUTINE: TIMER_START
C !INTERFACE:
SUBROUTINE TIMER_START ( string , myThreadId )
IMPLICIT NONE
C !DESCRIPTION:
C Start timer named "string".
C !INPUT PARAMETERS:
C string :: Name of timer
C myThreadId :: My thread number
CHARACTER*(*) string
INTEGER myThreadId
CEOP
C
CALL TIMER_CONTROL( string, 'START', 'TIMER_START' , myThreadId)
C
RETURN
END
CBOP
C !ROUTINE: TIMER_STOP
C !INTERFACE:
SUBROUTINE TIMER_STOP ( string , myThreadId)
IMPLICIT NONE
C !DESCRIPTION:
C Stop timer named "string".
C !INPUT PARAMETERS:
C string :: Name of timer
C myThreadId :: My thread number
CHARACTER*(*) string
INTEGER myThreadId
CEOP
C
CALL TIMER_CONTROL( string, 'STOP', 'TIMER_STOP' , myThreadId )
C
RETURN
END
C***********************************************************************