LCOV - code coverage report
Current view: top level - src - mo_timer.f90 (source / functions) Hit Total Coverage
Test: forces coverage Lines: 29 49 59.2 %
Date: 2024-03-13 19:03:28 Functions: 5 7 71.4 %

          Line data    Source code
       1             : !> \file mo_timer.f90
       2             : !> \brief \copybrief mo_timer
       3             : !> \details \copydetails mo_timer
       4             : 
       5             : !> \brief Timing routines
       6             : !> \details This module uses F90 cpu time routines to allowing setting of
       7             : !!          multiple CPU timers.
       8             : !> \changelog
       9             : !! - Matthias Cuntz, Aug. 2012
      10             : !!   - adapted to UFZ library, called mo_timer.f90
      11             : !! - Matthias Cuntz, Jan. 2013
      12             : !!   - clear one or all timers
      13             : !> \authors Matthias Cuntz - from timers.f (c) the Regents of the University of Californi
      14             : !> \date Dec 2012
      15             : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
      16             : !! FORCES is released under the LGPLv3+ license \license_note
      17             : module mo_timer
      18             : 
      19             :   ! -----------------------------------------------------------------------
      20             : 
      21             :   !     This module uses F90 cpu time routines to allowing setting of
      22             :   !     multiple CPU timers.
      23             : 
      24             :   ! -----------------------------------------------------------------------
      25             : 
      26             :   !     CVS:$Id: timers.f,v 1.2 2000/04/19 21:56:26 pwjones Exp $
      27             : 
      28             :   !     Copyright (c) 1997, 1998 the Regents of the University of
      29             :   !       California.
      30             : 
      31             :   !     This software and ancillary information (herein called software)
      32             :   !     called SCRIP is made available under the terms described here.
      33             :   !     The software has been approved for release with associated
      34             :   !     LA-CC Number 98-45.
      35             : 
      36             :   !     Unless otherwise indicated, this software has been authored
      37             :   !     by an employee or employees of the University of California,
      38             :   !     operator of the Los Alamos National Laboratory under Contract
      39             :   !     No. W-7405-ENG-36 with the U.S. Department of Energy.  The U.S.
      40             :   !     Government has rights to use, reproduce, and distribute this
      41             :   !     software.  The public may copy and use this software without
      42             :   !     charge, provided that this Notice and any statement of authorship
      43             :   !     are reproduced on all copies.  Neither the Government nor the
      44             :   !     University makes any warranty, express or implied, or assumes
      45             :   !     any liability or responsibility for the use of this software.
      46             : 
      47             :   !     If software is modified to produce derivative works, such modified
      48             :   !     software should be clearly marked, so as not to confuse it with
      49             :   !     the version available from Los Alamos National Laboratory.
      50             : 
      51             :   ! -----------------------------------------------------------------------
      52             : 
      53             :   use mo_kind, only : i4, sp
      54             : 
      55             :   implicit none
      56             : 
      57             :   private
      58             : 
      59             :   ! Variables
      60             :   public :: max_timers    ! max number of timers allowed
      61             :   public :: cycles_max    ! max value of clock allowed by system
      62             :   public :: clock_rate    ! clock_rate in seconds for each cycle
      63             :   public :: cycles1       ! cycle number at start for each timer
      64             :   public :: cycles2       ! cycle number at stop  for each timer
      65             :   public :: cputime       ! accumulated cpu time in each timer
      66             :   public :: status        ! timer status string
      67             :   ! Routines
      68             :   public :: timer_check   ! Checks a given timer
      69             :   public :: timer_clear   ! Clears (a given) timer(s)
      70             :   public :: timer_get     ! Returns the result of a given timer
      71             :   public :: timer_print   ! Prints the accumulated cpu time of a given timer
      72             :   public :: timer_start   ! Stops a given timer
      73             :   public :: timer_stop    ! Starts a given timer
      74             :   public :: timers_init   ! Initialises the module
      75             : 
      76             :   ! Save variables
      77             :   !> max number of timers allowed
      78             :   integer(i4), parameter :: max_timers = 500
      79             :   !> max value of clock allowed by system
      80             :   integer(i4), save :: cycles_max
      81             :   !> clock_rate in seconds for each cycle
      82             :   real(sp), save :: clock_rate
      83             :   !> cycle number at start for each timer
      84             :   integer(i4), dimension(max_timers), save :: cycles1
      85             :   !> cycle number at stop  for each timer
      86             :   integer(i4), dimension(max_timers), save :: cycles2
      87             :   !> accumulated cpu time in each timer
      88             :   real(sp), dimension(max_timers), save :: cputime
      89             :   !>  timer status string
      90             :   character(len = 8), dimension(max_timers), save :: status
      91             : 
      92             :   ! -----------------------------------------------------------------------
      93             : 
      94             : contains
      95             : 
      96             :   ! ------------------------------------------------------------------
      97             : 
      98             :   !>        \brief Check a timer
      99             : 
     100             :   !>        \details
     101             :   !!        This routine checks a given timer. This is primarily used to
     102             :   !!        periodically accumulate time in the timer to prevent timer cycles
     103             :   !!        from wrapping around max_cycles.
     104             :   !!
     105             :   !!        \b Example
     106             :   !!
     107             :   !!        Check timer 3
     108             :   !!        \code{.f90}
     109             :   !!        call timer_check(3)
     110             :   !!        \endcode
     111             : 
     112             :   !>        \param[in] "integer(i4) :: timer"        timer number
     113             : 
     114             :   !>        \author Matthias Cuntz
     115             :   !>        \date Aug 2012
     116             : 
     117           0 :   subroutine timer_check(timer)
     118             : 
     119             :     implicit none
     120             : 
     121             :     integer(i4), intent(in) :: timer            ! timer number
     122             : 
     123           0 :     if (status(timer) .eq. 'running') then
     124           0 :       call timer_stop (timer)
     125           0 :       call timer_start(timer)
     126             :     end if
     127             : 
     128           0 :   end subroutine timer_check
     129             : 
     130             :   ! ------------------------------------------------------------------
     131             : 
     132             :   !>        \brief Reset a timer
     133             : 
     134             :   !>        \details
     135             :   !!        This routine resets a given timer or all timers to 0.
     136             :   !!
     137             :   !!        \b Example
     138             :   !!
     139             :   !!        ! Clear timer 3
     140             :   !!        \code{.f90}
     141             :   !!        call timer_clear(3)
     142             :   !!        \endcode
     143             :   !!
     144             :   !!        Clear all timers
     145             :   !!        \code{.f90}
     146             :   !!        call timer_clear()
     147             :   !!        \endcode
     148             : 
     149             :   !>        \param[in] "integer(i4), optional :: timer"        timer number if given.\n
     150             :   !!                                                           If missing, all timers will be reset.
     151             : 
     152             :   !>        \author Matthias Cuntz
     153             :   !>        \date Aug 2012
     154             : 
     155         501 :   subroutine timer_clear(timer)
     156             : 
     157             :     implicit none
     158             : 
     159             :     integer(i4), intent(in), optional :: timer            ! timer number
     160             : 
     161         501 :     if (present(timer)) then
     162         501 :       cputime(timer) = 0.0_sp ! clear the timer
     163             :     else
     164           0 :       cputime(:) = 0.0_sp ! clear all timers
     165             :     end if
     166             : 
     167           0 :   end subroutine timer_clear
     168             : 
     169             :   ! ------------------------------------------------------------------
     170             : 
     171             :   !>        \brief Return a timer
     172             : 
     173             :   !>        \details This routine returns the result of a given timer. This can be
     174             :   !!        called instead of timer_print so that the calling routine can
     175             :   !!        print it in desired format.
     176             :   !!
     177             :   !!        \b Example
     178             :   !!
     179             :   !!        Return timer 3
     180             :   !!        \code{.f90}
     181             :   !!        call timer_get(3)
     182             :   !!        \endcode
     183             : 
     184             :   !>        \param[in] "integer(i4) :: timer"        timer number
     185             : 
     186             :   !>        \author Matthias Cuntz
     187             :   !>        \date Aug 2012
     188             : 
     189         503 :   function timer_get(timer)
     190             : 
     191             :     implicit none
     192             : 
     193             :     integer(i4), intent(in) :: timer            ! timer number
     194             : 
     195             :     real(sp) :: timer_get   ! accumulated cputime in given timer
     196             : 
     197         503 :     if (status(timer) .eq. 'stopped') then
     198         503 :       timer_get = cputime(timer)
     199             :     else
     200           0 :       call timer_stop(timer)
     201           0 :       timer_get = cputime(timer)
     202           0 :       call timer_start(timer)
     203             :     end if
     204             : 
     205         501 :   end function timer_get
     206             : 
     207             :   ! ------------------------------------------------------------------
     208             : 
     209             :   !>        \brief Print a timer
     210             : 
     211             :   !>        \details This routine prints the accumulated cpu time in given timer.
     212             :   !!
     213             :   !!        \b Example
     214             :   !!
     215             :   !!        Prints timer 3
     216             :   !!        \code{.f90}
     217             :   !!        call timer_print(3)
     218             :   !!        \endcode
     219             : 
     220             :   !>        \param[in] "integer(i4) :: timer"        timer number
     221             : 
     222             :   !>        \author Matthias Cuntz
     223             :   !>        \date Aug 2012
     224             : 
     225           0 :   subroutine timer_print(timer)
     226             : 
     227             :     implicit none
     228             : 
     229             :     integer(i4), intent(in) :: timer            ! timer number
     230             : 
     231             :     !---
     232             :     !--- print the cputime accumulated for timer
     233             :     !--- make sure timer is stopped
     234             :     !---
     235             : 
     236           0 :     if (status(timer) .eq. 'stopped') then
     237             :       write(*, "(' CPU time for timer',i3,':',1p,e16.8)")   &
     238           0 :               timer, cputime(timer)
     239             :     else
     240           0 :       call timer_stop(timer)
     241             :       write(*, "(' CPU time for timer',i3,':',1p,e16.8)")   &
     242           0 :               timer, cputime(timer)
     243           0 :       call timer_start(timer)
     244             :     end if
     245             : 
     246         503 :   end subroutine timer_print
     247             : 
     248             :   ! ------------------------------------------------------------------
     249             : 
     250             :   !>        \brief Start a timer
     251             : 
     252             :   !>        \details This routine starts a given timer.
     253             :   !!
     254             :   !!        \b Example
     255             :   !!
     256             :   !!        Start timer 3
     257             :   !!        \code{.f90}
     258             :   !!        call timer_start(3)
     259             :   !!        \endcode
     260             : 
     261             :   !>        \param[in] "integer(i4) :: timer"        timer number
     262             : 
     263             :   !>        \author Matthias Cuntz
     264             :   !>        \date Aug 2012
     265             : 
     266           2 :   subroutine timer_start(timer)
     267             : 
     268             :     implicit none
     269             : 
     270             :     integer(i4), intent(in) :: timer            ! timer number
     271             : 
     272             :     !---
     273             :     !--- Start the timer and change timer status.
     274             :     !---
     275             : 
     276           2 :     if (status(timer) .eq. 'stopped') then
     277           2 :       call system_clock(count = cycles1(timer))
     278           2 :       status(timer) = 'running'
     279             :     end if
     280             : 
     281           0 :   end subroutine timer_start
     282             : 
     283             :   ! ------------------------------------------------------------------
     284             : 
     285             :   !>        \brief Stop a timer
     286             : 
     287             :   !>        \details This routine stops a given timer.
     288             :   !!        \b Example
     289             :   !!
     290             :   !!        Stop timer 3
     291             :   !!        \code{.f90}
     292             :   !!        call timer_stop(3)
     293             :   !!        \endcode
     294             : 
     295             :   !>        \param[in] "integer(i4) :: timer"        timer number
     296             : 
     297             :   !>        \author Matthias Cuntz
     298             :   !>        \date Aug 2012
     299             : 
     300           2 :   subroutine timer_stop(timer)
     301             : 
     302             :     implicit none
     303             : 
     304             :     integer(i4), intent(in) :: timer            ! timer number
     305             : 
     306           2 :     if (status(timer) .eq. 'running') then
     307             : 
     308             :       !---
     309             :       !--- Stop the desired timer.
     310             :       !---
     311             : 
     312           2 :       call system_clock(count = cycles2(timer))
     313             : 
     314             :       !---
     315             :       !--- check and correct for cycle wrapping
     316             :       !---
     317             : 
     318           2 :       if (cycles2(timer) .ge. cycles1(timer)) then
     319             :         cputime(timer) = cputime(timer) + clock_rate * &
     320           2 :                 (cycles2(timer) - cycles1(timer))
     321             :       else
     322             :         cputime(timer) = cputime(timer) + clock_rate * &
     323           0 :                 (cycles2(timer) - cycles1(timer) + cycles_max)
     324             :       end if
     325             : 
     326             :       !---
     327             :       !--- Change timer status.
     328             :       !---
     329             : 
     330           2 :       status(timer) = 'stopped'
     331             : 
     332             :     end if
     333             : 
     334           2 :   end subroutine timer_stop
     335             : 
     336             :   !-----------------------------------------------------------------------
     337             : 
     338             :   !     This routine initializes some machine parameters necessary for
     339             :   !     computing cpu time from F90 intrinsics.
     340             : 
     341             :   ! ------------------------------------------------------------------
     342             : 
     343             :   !>        \brief Initialise timer module
     344             : 
     345             :   !>        \details This routine initializes some machine parameters necessary for
     346             :   !!        computing cpu time from F90 intrinsics.
     347             :   !!
     348             :   !!        \b Example
     349             :   !!
     350             :   !!        Initialize timers (before running timers)
     351             :   !!        \code{.f90}
     352             :   !!        call timers_init()
     353             :   !!        \endcode
     354             : 
     355             :   !>        \author Matthias Cuntz
     356             :   !>        \date Aug 2012
     357             : 
     358           1 :   subroutine timers_init
     359             : 
     360             :     implicit none
     361             : 
     362             :     integer(i4) :: cycles ! count rate return by sys_clock
     363             : 
     364             :     !---
     365             :     !--- Initialize timer arrays and clock_rate.
     366             :     !---
     367             : 
     368           1 :     clock_rate = 0.0_sp
     369           1 :     cycles1(:) = 0
     370           1 :     cycles2(:) = 0
     371           1 :     cputime(:) = 0.0_sp
     372         501 :     status(:) = 'stopped'
     373             : 
     374             :     !---
     375             :     !--- Call F90 intrinsic system_clock to determine clock rate
     376             :     !--- and maximum cycles.  If no clock available, print message.
     377             :     !---
     378             : 
     379           1 :     call system_clock(count_rate = cycles, count_max = cycles_max)
     380             : 
     381           1 :     if (cycles /= 0) then
     382           1 :       clock_rate = 1.0_sp / real(cycles)
     383             :     else
     384           0 :       clock_rate = 0.0_sp
     385           0 :       print *, '--- No system clock available ---'
     386             :     end if
     387             : 
     388           2 :   end subroutine timers_init
     389             : 
     390             : end module mo_timer

Generated by: LCOV version 1.16