For performance tuning one would often like a timer that can be inserted to see how long a particular code segment takes to execute. Having identified with a profiler such as gprof which code segents are taking time, a typical timer works as
pretim = timefunction()
code segment
entim = timefucntion()
elapse = entim - pretim
Most Fortran compilers have high resolution timers that can be inserted in code to time code segments. High resolution timers are not standard across compilers. The Fortran standard timer in Fortran 90 typically has a resolution of about one second, which is an appropriate resolution for timing many billions of flops.
include
call MPI_Init()
...
pretim = MPI_Wtime()
code segment to be timed
entim = MPI_Wtime()
....
call MPI_Finalize()
See the sample code test4.f
compiled by
gcc -c timw.c g77 -c test.f g77 -o test timw.o test.oThe code also worked with pgf77 and pgcc (Portland group compilers) and with ifort and icc (intel compilers). On cygwin, gfort and gcc worked (as well as g77 and gcc)
c-------------------------------------------------------------
program testtimers
c
c This program measures wall clock time
c
c wdiff returns the time elapsed between the call to wdiff
c and the previous call to wtime.
c wdiff requires that the same vector time used in the
c call to wtime
c
c wdiff and wtime are C functions calling gettimeofday
c
real*8 sum, tim(2), elapsed , smax
integer i, ierr, ierr2
i = 1
sum = 0.d0
print*,' input max for sum'
print*,' suggest numbers around 10 to 20'
read*, smax
call wtime(tim, ierr)
do while (sum .lt. smax)
sum = sum + 1./i
i = i+1
end do
elapsed = wdiff(tim,ierr2)
print*,' elapsed time is ', elapsed,' seconds'
stop
end
c----------------------------------------------------------
#include#include /* This timer returns wall clock time. The first entry is current time in seconds. The second entry is microseconds. */ void wtime_(double tim[2], int *ierr2 ) { struct timeval time1; int ierr; double elap; ierr = gettimeofday(&time1, NULL) ; *ierr2 = ierr; if (ierr != 0 ) printf("bad return of gettimeofday, ierr = %d \n",ierr); tim[0] = time1.tv_sec; tim[1] = time1.tv_usec; } /* This timer returns the difference between current wall clock time and the one returned by wtime_ and returns a double precision number */ double wdiff_(double tim[2], int *ierr2 ) { struct timeval time1; int ierr; double wdiff; ierr = gettimeofday(&time1, NULL); *ierr2 = ierr; if (ierr != 0 ) printf("bad return of gettime of day, ierr = %d \n", ierr); tim[0] = time1.tv_sec - tim[0]; tim[1] = time1.tv_usec - tim[1]; wdiff = 1.e6*tim[0] + tim[1]; return ( wdiff/1.e6) ; }
For a further discussion of the MPI wall clock timer, see Porting Codes. Intrinsic timers and hazards of timing wrap-arounds in GNU Fortran are discussed in Intrinsic Timers. Fortran90 timers and sample codes are given in Fortran 90 Timers (from Florida State University). A University of Texas version of wrapping C functions to get Fortran timers is found at TACC User Guide Codes.