WSJT-X/lib/timer.f90
Bill Somerville b16d510b0d First attempt at a thread safe lib/timer.f90
This  tries  to  account  for  function  calls  in  different  threads
separately by decorating  the function name with the  thread number it
is  running in.  This may  not be  the best  strategy for  performance
timing but it is  the easiest way of making it thread  safe that I can
see.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@4924 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
2015-02-02 14:08:17 +00:00

138 lines
3.5 KiB
Fortran

subroutine timer(dname,k)
! Times procedure number n between a call with k=0 (tstart) and with
! k=1 (tstop). Accumulates sums of these times in array ut (user time).
! Also traces all calls (for debugging purposes) if limtrace.gt.0
!$ interface
!$ integer function omp_get_thread_num()
!$ end function
!$ end interface
character*8 dname
!$ character thread
character*11 tname,ename
character*16 sname
character*11, save :: space
integer, save :: level, nmax
character*11, save :: name(50)
logical, save :: on(50)
real, save :: ut(50),ut0(50),dut(50)
integer, save :: ncall(50),nlevel(50),nparent(50)
integer, save :: onlevel(0:10)
common/tracer/ limtrace,lu
data eps/0.000001/,ntrace/0/
data level/0/,nmax/0/,space/' '/
data limtrace/0/,lu/-1/
!$omp threadprivate(level,space,onlevel)
tname=dname
!$ write(thread,'(i1)') omp_get_thread_num()
!$ tname=trim(dname)//'('//thread//')' ! decorate name with thread number
!$omp critical(timer)
if(limtrace.lt.0) go to 999
if(lu.lt.1) lu=6
if(k.gt.1) go to 40 !Check for "all done" (k>1)
onlevel(0)=0
do n=1,nmax !Check for existing name
if(name(n).eq.tname) go to 20
enddo
nmax=nmax+1 !This is a new one
n=nmax
ncall(n)=0
on(n)=.false.
ut(n)=eps
name(n)=tname
20 if(k.eq.0) then !Get start times (k=0)
if(on(n)) print*,'Error in timer: ',tname,' already on.'
level=level+1 !Increment the level
on(n)=.true.
! call system_clock(icount,irate)
! ut0(n)=float(icount)/irate
! call cpu_time(ut0(n))
ut0(n)=secnds(0.0)
ncall(n)=ncall(n)+1
if(ncall(n).gt.1.and.nlevel(n).ne.level) then
nlevel(n)=-1
else
nlevel(n)=level
endif
nparent(n)=onlevel(level-1)
onlevel(level)=n
else if(k.eq.1) then !Get stop times and accumulate sums. (k=1)
if(on(n)) then
on(n)=.false.
! call system_clock(icount,irate)
! ut1=float(icount)/irate
! call cpu_time(ut1)
ut1=secnds(0.0)
ut(n)=ut(n)+ut1-ut0(n)
endif
level=level-1
endif
ntrace=ntrace+1
if(ntrace.lt.limtrace) write(lu,1020) ntrace,tname,k,level,nparent(n)
1020 format(i8,': ',a11,3i5)
go to 998
! Write out the timer statistics
40 write(lu,1040)
1040 format(/' name time frac dtime', &
' dfrac calls level parent'/73('-'))
if(k.gt.100) then
ndiv=k-100
do i=1,nmax
ncall(i)=ncall(i)/ndiv
ut(i)=ut(i)/ndiv
enddo
endif
total=ut(1)
sum=0.
sumf=0.
do i=1,nmax
dut(i)=ut(i)
do j=i,nmax
if(nparent(j).eq.i) dut(i)=dut(i)-ut(j)
enddo
if(dut(i).lt.0.0) dut(i)=0.0
utf=ut(i)/total
dutf=dut(i)/total
sum=sum+dut(i)
sumf=sumf+dutf
kk=nlevel(i)
sname=space(1:kk)//name(i)//space(1:11-kk)
ename=space
if(nparent(i).ge.1) ename=name(nparent(i))
write(lu,1060) float(i),sname,ut(i),utf,dut(i),dutf, &
ncall(i),nlevel(i),ename
1060 format(f4.0,a16,2(f10.3,f6.2),i7,i5,2x,a11)
enddo
write(lu,1070) sum,sumf
1070 format(/36x,f10.2,f6.2)
nmax=0
eps=0.000001
ntrace=0
level=0
space=' '
onlevel(0)=0
998 flush(lu)
999 continue
!$omp end critical(timer)
return
end subroutine timer