LCOV - code coverage report
Current view: top level - src/common - timings.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:262480d) Lines: 135 178 75.8 %
Date: 2024-11-22 07:00:40 Functions: 11 12 91.7 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Timing routines for accounting
      10             : !> \par History
      11             : !>      02.2004 made a stacked version (of stacks...) [Joost VandeVondele]
      12             : !>      11.2004 storable timer_envs (for f77 interface) [fawzi]
      13             : !>      10.2005 binary search to speed up lookup in timeset [fawzi]
      14             : !>      12.2012 Complete rewrite based on dictionaries. [ole]
      15             : !> \author JGH
      16             : ! **************************************************************************************************
      17             : MODULE timings
      18             :    USE base_hooks,                      ONLY: timeset_hook,&
      19             :                                               timestop_hook
      20             :    USE callgraph,                       ONLY: callgraph_destroy,&
      21             :                                               callgraph_get,&
      22             :                                               callgraph_init,&
      23             :                                               callgraph_item_type,&
      24             :                                               callgraph_items,&
      25             :                                               callgraph_set
      26             :    USE kinds,                           ONLY: default_string_length,&
      27             :                                               dp,&
      28             :                                               int_8
      29             :    USE list,                            ONLY: &
      30             :         list_destroy, list_get, list_init, list_isready, list_peek, list_pop, list_push, &
      31             :         list_size, list_timerenv_type
      32             :    USE machine,                         ONLY: m_energy,&
      33             :                                               m_flush,&
      34             :                                               m_memory,&
      35             :                                               m_walltime
      36             :    USE offload_api,                     ONLY: offload_mem_info,&
      37             :                                               offload_timeset,&
      38             :                                               offload_timestop
      39             :    USE routine_map,                     ONLY: routine_map_destroy,&
      40             :                                               routine_map_get,&
      41             :                                               routine_map_init,&
      42             :                                               routine_map_set,&
      43             :                                               routine_map_size
      44             :    USE timings_base_type,               ONLY: call_stat_type,&
      45             :                                               callstack_entry_type,&
      46             :                                               routine_stat_type
      47             :    USE timings_types,                   ONLY: timer_env_type
      48             : #include "../base/base_uses.f90"
      49             : 
      50             :    IMPLICIT NONE
      51             :    PRIVATE
      52             : 
      53             :    PUBLIC :: print_stack, timings_register_hooks
      54             : 
      55             :    ! these routines are currently only used by environment.F and f77_interface.F
      56             :    PUBLIC :: add_timer_env, rm_timer_env, get_timer_env
      57             :    PUBLIC :: timer_env_retain, timer_env_release
      58             :    PUBLIC :: timings_setup_tracing
      59             : 
      60             :    ! global variables
      61             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'timings'
      62             :    TYPE(list_timerenv_type), SAVE, PRIVATE                  :: timers_stack
      63             : 
      64             :    !API (via pointer assignment to hook, PR67982, not meant to be called directly)
      65             :    PUBLIC :: timeset_handler, timestop_handler
      66             : 
      67             :    INTEGER, PUBLIC, PARAMETER :: default_timings_level = 1
      68             :    INTEGER, PUBLIC, SAVE :: global_timings_level = default_timings_level
      69             : 
      70             :    CHARACTER(LEN=default_string_length), PUBLIC, PARAMETER :: root_cp2k_name = 'CP2K'
      71             : 
      72             : CONTAINS
      73             : 
      74             : ! **************************************************************************************************
      75             : !> \brief Registers handlers with base_hooks.F
      76             : !> \author Ole Schuett
      77             : ! **************************************************************************************************
      78        8530 :    SUBROUTINE timings_register_hooks()
      79        8530 :       timeset_hook => timeset_handler
      80        8530 :       timestop_hook => timestop_handler
      81        8530 :    END SUBROUTINE timings_register_hooks
      82             : 
      83             : ! **************************************************************************************************
      84             : !> \brief adds the given timer_env to the top of the stack
      85             : !> \param timer_env ...
      86             : !> \par History
      87             : !>      02.2004 created [Joost VandeVondele]
      88             : !> \note
      89             : !>      for each init_timer_env there should be the symmetric call to
      90             : !>      rm_timer_env
      91             : ! **************************************************************************************************
      92      107841 :    SUBROUTINE add_timer_env(timer_env)
      93             :       TYPE(timer_env_type), OPTIONAL, POINTER            :: timer_env
      94             : 
      95             :       TYPE(timer_env_type), POINTER                      :: timer_env_
      96             : 
      97      107841 :       IF (PRESENT(timer_env)) timer_env_ => timer_env
      98       17657 :       IF (.NOT. PRESENT(timer_env)) CALL timer_env_create(timer_env_)
      99      107841 :       IF (.NOT. ASSOCIATED(timer_env_)) &
     100           0 :          CPABORT("add_timer_env: not associated")
     101             : 
     102      107841 :       CALL timer_env_retain(timer_env_)
     103      107841 :       IF (.NOT. list_isready(timers_stack)) CALL list_init(timers_stack)
     104      107841 :       CALL list_push(timers_stack, timer_env_)
     105      107841 :    END SUBROUTINE add_timer_env
     106             : 
     107             : ! **************************************************************************************************
     108             : !> \brief creates a new timer env
     109             : !> \param timer_env ...
     110             : !> \author fawzi
     111             : ! **************************************************************************************************
     112       17657 :    SUBROUTINE timer_env_create(timer_env)
     113             :       TYPE(timer_env_type), POINTER                      :: timer_env
     114             : 
     115       17657 :       ALLOCATE (timer_env)
     116       17657 :       timer_env%ref_count = 0
     117             :       timer_env%trace_max = -1 ! tracing disabled by default
     118             :       timer_env%trace_all = .FALSE.
     119       17657 :       CALL routine_map_init(timer_env%routine_names)
     120       17657 :       CALL callgraph_init(timer_env%callgraph)
     121       17657 :       CALL list_init(timer_env%routine_stats)
     122       17657 :       CALL list_init(timer_env%callstack)
     123       17657 :    END SUBROUTINE timer_env_create
     124             : 
     125             : ! **************************************************************************************************
     126             : !> \brief removes the current timer env from the stack
     127             : !> \par History
     128             : !>      02.2004 created [Joost VandeVondele]
     129             : !> \note
     130             : !>      for each rm_timer_env there should have been the symmetric call to
     131             : !>      add_timer_env
     132             : ! **************************************************************************************************
     133      107841 :    SUBROUTINE rm_timer_env()
     134             :       TYPE(timer_env_type), POINTER                      :: timer_env
     135             : 
     136      107841 :       timer_env => list_pop(timers_stack)
     137      107841 :       CALL timer_env_release(timer_env)
     138      107841 :       IF (list_size(timers_stack) == 0) CALL list_destroy(timers_stack)
     139      107841 :    END SUBROUTINE rm_timer_env
     140             : 
     141             : ! **************************************************************************************************
     142             : !> \brief returns the current timer env from the stack
     143             : !> \return ...
     144             : !> \author fawzi
     145             : ! **************************************************************************************************
     146      107919 :    FUNCTION get_timer_env() RESULT(timer_env)
     147             :       TYPE(timer_env_type), POINTER                      :: timer_env
     148             : 
     149      107919 :       timer_env => list_peek(timers_stack)
     150      107919 :    END FUNCTION get_timer_env
     151             : 
     152             : ! **************************************************************************************************
     153             : !> \brief retains the given timer env
     154             : !> \param timer_env the timer env to retain
     155             : !> \author fawzi
     156             : ! **************************************************************************************************
     157      116448 :    SUBROUTINE timer_env_retain(timer_env)
     158             :       TYPE(timer_env_type), POINTER                      :: timer_env
     159             : 
     160      116448 :       IF (.NOT. ASSOCIATED(timer_env)) &
     161           0 :          CPABORT("timer_env_retain: not associated")
     162      116448 :       IF (timer_env%ref_count < 0) &
     163           0 :          CPABORT("timer_env_retain: negativ ref_count")
     164      116448 :       timer_env%ref_count = timer_env%ref_count + 1
     165      116448 :    END SUBROUTINE timer_env_retain
     166             : 
     167             : ! **************************************************************************************************
     168             : !> \brief releases the given timer env
     169             : !> \param timer_env the timer env to release
     170             : !> \author fawzi
     171             : ! **************************************************************************************************
     172      116448 :    SUBROUTINE timer_env_release(timer_env)
     173             :       TYPE(timer_env_type), POINTER                      :: timer_env
     174             : 
     175             :       INTEGER                                            :: i
     176      116448 :       TYPE(callgraph_item_type), DIMENSION(:), POINTER   :: ct_items
     177             :       TYPE(routine_stat_type), POINTER                   :: r_stat
     178             : 
     179      116448 :       IF (.NOT. ASSOCIATED(timer_env)) &
     180           0 :          CPABORT("timer_env_release: not associated")
     181      116448 :       IF (timer_env%ref_count < 0) &
     182           0 :          CPABORT("timer_env_release: negativ ref_count")
     183      116448 :       timer_env%ref_count = timer_env%ref_count - 1
     184      116448 :       IF (timer_env%ref_count > 0) RETURN
     185             : 
     186             :       ! No more references left - let's tear down this timer_env...
     187             : 
     188     3835114 :       DO i = 1, list_size(timer_env%routine_stats)
     189     3817457 :          r_stat => list_get(timer_env%routine_stats, i)
     190     3835114 :          DEALLOCATE (r_stat)
     191             :       END DO
     192             : 
     193       17657 :       ct_items => callgraph_items(timer_env%callgraph)
     194     6414717 :       DO i = 1, SIZE(ct_items)
     195     6414717 :          DEALLOCATE (ct_items(i)%value)
     196             :       END DO
     197       17657 :       DEALLOCATE (ct_items)
     198             : 
     199       17657 :       CALL routine_map_destroy(timer_env%routine_names)
     200       17657 :       CALL callgraph_destroy(timer_env%callgraph)
     201       17657 :       CALL list_destroy(timer_env%callstack)
     202       17657 :       CALL list_destroy(timer_env%routine_stats)
     203       17657 :       DEALLOCATE (timer_env)
     204      116448 :    END SUBROUTINE timer_env_release
     205             : 
     206             : ! **************************************************************************************************
     207             : !> \brief Start timer
     208             : !> \param routineN ...
     209             : !> \param handle ...
     210             : !> \par History
     211             : !>      none
     212             : !> \author JGH
     213             : ! **************************************************************************************************
     214  1562563377 :    SUBROUTINE timeset_handler(routineN, handle)
     215             :       CHARACTER(LEN=*), INTENT(IN)                       :: routineN
     216             :       INTEGER, INTENT(OUT)                               :: handle
     217             : 
     218             :       CHARACTER(LEN=400)                                 :: line, mystring
     219             :       CHARACTER(LEN=60)                                  :: sformat
     220             :       CHARACTER(LEN=default_string_length)               :: routine_name_dsl
     221             :       INTEGER                                            :: routine_id, stack_size
     222             :       INTEGER(KIND=int_8)                                :: cpumem, gpumem_free, gpumem_total
     223             :       INTEGER, SAVE                                      :: root_cp2k_id
     224             :       TYPE(callstack_entry_type)                         :: cs_entry
     225             :       TYPE(routine_stat_type), POINTER                   :: r_stat
     226             :       TYPE(timer_env_type), POINTER                      :: timer_env
     227             : 
     228  1562563377 : !$OMP MASTER
     229             : 
     230             :       ! Default value, using a negative value when timing is not taken
     231  1562563377 :       cs_entry%walltime_start = -HUGE(1.0_dp)
     232  1562563377 :       cs_entry%energy_start = -HUGE(1.0_dp)
     233  1562563377 :       root_cp2k_id = routine_name2id(root_cp2k_name)
     234             :       !
     235  1562563377 :       routine_name_dsl = routineN ! converte to default_string_length
     236  1562563377 :       routine_id = routine_name2id(routine_name_dsl)
     237             :       !
     238             :       ! Take timings when the timings_level is appropriated
     239  1562563377 :       IF (global_timings_level .NE. 0 .OR. routine_id .EQ. root_cp2k_id) THEN
     240  1562563377 :          cs_entry%walltime_start = m_walltime()
     241  1562563377 :          cs_entry%energy_start = m_energy()
     242             :       END IF
     243  1562563377 :       timer_env => list_peek(timers_stack)
     244             : 
     245  1562563377 :       IF (LEN_TRIM(routineN) > default_string_length) THEN
     246           0 :          CPABORT('timings_timeset: routineN too long: "'//TRIM(routineN)//"'")
     247             :       END IF
     248             : 
     249             :       ! update routine r_stats
     250  1562563377 :       r_stat => list_get(timer_env%routine_stats, routine_id)
     251  1562563377 :       stack_size = list_size(timer_env%callstack)
     252  1562563377 :       r_stat%total_calls = r_stat%total_calls + 1
     253  1562563377 :       r_stat%active_calls = r_stat%active_calls + 1
     254  1562563377 :       r_stat%stackdepth_accu = r_stat%stackdepth_accu + stack_size + 1
     255             : 
     256             :       ! add routine to callstack
     257  1562563377 :       cs_entry%routine_id = routine_id
     258  1562563377 :       CALL list_push(timer_env%callstack, cs_entry)
     259             : 
     260             :       !..if debug mode echo the subroutine name
     261  1562563377 :       IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
     262             :           (r_stat%total_calls < timer_env%trace_max)) THEN
     263           0 :          WRITE (sformat, *) "(A,A,", MAX(1, 3*stack_size - 4), "X,I4,1X,I6,1X,A,A)"
     264           0 :          WRITE (mystring, sformat) timer_env%trace_str, ">>", stack_size + 1, &
     265           0 :             r_stat%total_calls, TRIM(r_stat%routineN), "       start"
     266           0 :          CALL offload_mem_info(gpumem_free, gpumem_total)
     267           0 :          CALL m_memory(cpumem)
     268           0 :          WRITE (line, '(A,A,I0,A,A,I0,A)') TRIM(mystring), &
     269           0 :             " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024), " MB", &
     270           0 :             " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024), " MB"
     271           0 :          WRITE (timer_env%trace_unit, *) TRIM(line)
     272           0 :          CALL m_flush(timer_env%trace_unit)
     273             :       END IF
     274             : 
     275  1562563377 :       handle = routine_id
     276             : 
     277  1562563377 :       CALL offload_timeset(routineN)
     278             : 
     279             : !$OMP END MASTER
     280             : 
     281  1562563377 :    END SUBROUTINE timeset_handler
     282             : 
     283             : ! **************************************************************************************************
     284             : !> \brief End timer
     285             : !> \param handle ...
     286             : !> \par History
     287             : !>      none
     288             : !> \author JGH
     289             : ! **************************************************************************************************
     290  1562563377 :    SUBROUTINE timestop_handler(handle)
     291             :       INTEGER, INTENT(in)                                :: handle
     292             : 
     293             :       CHARACTER(LEN=400)                                 :: line, mystring
     294             :       CHARACTER(LEN=60)                                  :: sformat
     295             :       INTEGER                                            :: routine_id, stack_size
     296             :       INTEGER(KIND=int_8)                                :: cpumem, gpumem_free, gpumem_total
     297             :       INTEGER, DIMENSION(2)                              :: routine_tuple
     298             :       REAL(KIND=dp)                                      :: en_elapsed, en_now, wt_elapsed, wt_now
     299             :       TYPE(call_stat_type), POINTER                      :: c_stat
     300             :       TYPE(callstack_entry_type)                         :: cs_entry, prev_cs_entry
     301             :       TYPE(routine_stat_type), POINTER                   :: prev_stat, r_stat
     302             :       TYPE(timer_env_type), POINTER                      :: timer_env
     303             : 
     304  1562563377 :       routine_id = handle
     305             : 
     306  1562563377 : !$OMP MASTER
     307             : 
     308  1562563377 :       CALL offload_timestop()
     309             : 
     310  1562563377 :       timer_env => list_peek(timers_stack)
     311  1562563377 :       cs_entry = list_pop(timer_env%callstack)
     312  1562563377 :       r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
     313             : 
     314  1562563377 :       IF (handle /= cs_entry%routine_id) THEN
     315           0 :          PRINT *, "list_size(timer_env%callstack) ", list_size(timer_env%callstack), &
     316           0 :             " handle ", handle, " list_size(timers_stack) ", list_size(timers_stack)
     317           0 :          CPABORT('mismatched timestop '//TRIM(r_stat%routineN)//' in routine timestop')
     318             :       END IF
     319             : 
     320  1562563377 :       wt_elapsed = 0
     321  1562563377 :       en_elapsed = 0
     322             :       ! Take timings only when the start time is >=0, i.e. the timings_level is appropriated
     323  1562563377 :       IF (cs_entry%walltime_start .GE. 0) THEN
     324  1562563377 :          wt_now = m_walltime()
     325  1562563377 :          en_now = m_energy()
     326             :          ! add the elapsed time for this timeset/timestop to the time accumulator
     327  1562563377 :          wt_elapsed = wt_now - cs_entry%walltime_start
     328  1562563377 :          en_elapsed = en_now - cs_entry%energy_start
     329             :       END IF
     330  1562563377 :       r_stat%active_calls = r_stat%active_calls - 1
     331             : 
     332             :       ! if we're the last instance in the stack, we do the accounting of the total time
     333  1562563377 :       IF (r_stat%active_calls == 0) THEN
     334  1559495735 :          r_stat%incl_walltime_accu = r_stat%incl_walltime_accu + wt_elapsed
     335  1559495735 :          r_stat%incl_energy_accu = r_stat%incl_energy_accu + en_elapsed
     336             :       END IF
     337             : 
     338             :       ! exclusive time we always sum, since children will correct this time with their total time
     339  1562563377 :       r_stat%excl_walltime_accu = r_stat%excl_walltime_accu + wt_elapsed
     340  1562563377 :       r_stat%excl_energy_accu = r_stat%excl_energy_accu + en_elapsed
     341             : 
     342  1562563377 :       stack_size = list_size(timer_env%callstack)
     343  1562563377 :       IF (stack_size > 0) THEN
     344  1529426957 :          prev_cs_entry = list_peek(timer_env%callstack)
     345  1529426957 :          prev_stat => list_get(timer_env%routine_stats, prev_cs_entry%routine_id)
     346             :          ! we fixup the clock of the caller
     347  1529426957 :          prev_stat%excl_walltime_accu = prev_stat%excl_walltime_accu - wt_elapsed
     348  1529426957 :          prev_stat%excl_energy_accu = prev_stat%excl_energy_accu - en_elapsed
     349             : 
     350             :          !update callgraph
     351  4588280871 :          routine_tuple = (/prev_cs_entry%routine_id, routine_id/)
     352  1529426957 :          c_stat => callgraph_get(timer_env%callgraph, routine_tuple, default_value=Null(c_stat))
     353  1529426957 :          IF (.NOT. ASSOCIATED(c_stat)) THEN
     354     6397060 :             ALLOCATE (c_stat)
     355             :             c_stat%total_calls = 0
     356             :             c_stat%incl_walltime_accu = 0.0_dp
     357             :             c_stat%incl_energy_accu = 0.0_dp
     358     6397060 :             CALL callgraph_set(timer_env%callgraph, routine_tuple, c_stat)
     359             :          END IF
     360  1529426957 :          c_stat%total_calls = c_stat%total_calls + 1
     361  1529426957 :          c_stat%incl_walltime_accu = c_stat%incl_walltime_accu + wt_elapsed
     362  1529426957 :          c_stat%incl_energy_accu = c_stat%incl_energy_accu + en_elapsed
     363             :       END IF
     364             : 
     365             :       !..if debug mode echo the subroutine name
     366  1562563377 :       IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
     367             :           (r_stat%total_calls < timer_env%trace_max)) THEN
     368           0 :          WRITE (sformat, *) "(A,A,", MAX(1, 3*stack_size - 4), "X,I4,1X,I6,1X,A,F12.3)"
     369           0 :          WRITE (mystring, sformat) timer_env%trace_str, "<<", stack_size + 1, &
     370           0 :             r_stat%total_calls, TRIM(r_stat%routineN), wt_elapsed
     371           0 :          CALL offload_mem_info(gpumem_free, gpumem_total)
     372           0 :          CALL m_memory(cpumem)
     373           0 :          WRITE (line, '(A,A,I0,A,A,I0,A)') TRIM(mystring), &
     374           0 :             " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024), " MB", &
     375           0 :             " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024), " MB"
     376           0 :          WRITE (timer_env%trace_unit, *) TRIM(line)
     377           0 :          CALL m_flush(timer_env%trace_unit)
     378             :       END IF
     379             : 
     380             : !$OMP END MASTER
     381             : 
     382  1562563377 :    END SUBROUTINE timestop_handler
     383             : 
     384             : ! **************************************************************************************************
     385             : !> \brief Set routine tracer
     386             : !> \param trace_max  maximum number of calls reported per routine.
     387             : !>           Setting this to zero disables tracing.
     388             : !> \param unit_nr output unit used for printing the trace-messages
     389             : !> \param trace_str short info-string which is printed along with every message
     390             : !> \param routine_names List of routine-names.
     391             : !>                     If provided only these routines will be traced.
     392             : !>                     If not present all routines will traced.
     393             : !> \par History
     394             : !>       12.2012  added ability to trace only certain routines [ole]
     395             : !> \author JGH
     396             : ! **************************************************************************************************
     397           0 :    SUBROUTINE timings_setup_tracing(trace_max, unit_nr, trace_str, routine_names)
     398             :       INTEGER, INTENT(IN)                                :: trace_max, unit_nr
     399             :       CHARACTER(len=13), INTENT(IN)                      :: trace_str
     400             :       CHARACTER(len=default_string_length), &
     401             :          DIMENSION(:), INTENT(IN), OPTIONAL              :: routine_names
     402             : 
     403             :       INTEGER                                            :: i, routine_id
     404             :       TYPE(routine_stat_type), POINTER                   :: r_stat
     405             :       TYPE(timer_env_type), POINTER                      :: timer_env
     406             : 
     407           0 :       timer_env => list_peek(timers_stack)
     408           0 :       timer_env%trace_max = trace_max
     409           0 :       timer_env%trace_unit = unit_nr
     410           0 :       timer_env%trace_str = trace_str
     411           0 :       timer_env%trace_all = .TRUE.
     412           0 :       IF (.NOT. PRESENT(routine_names)) RETURN
     413             : 
     414             :       ! setup routine-specific tracing
     415           0 :       timer_env%trace_all = .FALSE.
     416           0 :       DO i = 1, SIZE(routine_names)
     417           0 :          routine_id = routine_name2id(routine_names(i))
     418           0 :          r_stat => list_get(timer_env%routine_stats, routine_id)
     419           0 :          r_stat%trace = .TRUE.
     420             :       END DO
     421             : 
     422             :    END SUBROUTINE timings_setup_tracing
     423             : 
     424             : ! **************************************************************************************************
     425             : !> \brief Print current routine stack
     426             : !> \param unit_nr ...
     427             : !> \par History
     428             : !>      none
     429             : !> \author JGH
     430             : ! **************************************************************************************************
     431         246 :    SUBROUTINE print_stack(unit_nr)
     432             :       INTEGER, INTENT(IN)                                :: unit_nr
     433             : 
     434             :       INTEGER                                            :: i
     435             :       TYPE(callstack_entry_type)                         :: cs_entry
     436             :       TYPE(routine_stat_type), POINTER                   :: r_stat
     437             :       TYPE(timer_env_type), POINTER                      :: timer_env
     438             : 
     439             :       ! catch edge cases where timer_env is not yet/anymore available
     440         246 :       IF (.NOT. list_isready(timers_stack)) &
     441           0 :          RETURN
     442         246 :       IF (list_size(timers_stack) == 0) &
     443             :          RETURN
     444             : 
     445         246 :       timer_env => list_peek(timers_stack)
     446         246 :       WRITE (unit_nr, '(/,A,/)') " ===== Routine Calling Stack ===== "
     447        1431 :       DO i = list_size(timer_env%callstack), 1, -1
     448        1185 :          cs_entry = list_get(timer_env%callstack, i)
     449        1185 :          r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
     450        1431 :          WRITE (unit_nr, '(T10,I4,1X,A)') i, TRIM(r_stat%routineN)
     451             :       END DO
     452         246 :       CALL m_flush(unit_nr)
     453             : 
     454         246 :    END SUBROUTINE print_stack
     455             : 
     456             : ! **************************************************************************************************
     457             : !> \brief Internal routine used by timestet and timings_setup_tracing.
     458             : !>        If no routine with given name is found in timer_env%routine_names
     459             : !>        then a new entiry is created.
     460             : !> \param routineN ...
     461             : !> \return ...
     462             : !> \author Ole Schuett
     463             : ! **************************************************************************************************
     464  3125126754 :    FUNCTION routine_name2id(routineN) RESULT(routine_id)
     465             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: routineN
     466             :       INTEGER                                            :: routine_id
     467             : 
     468             :       TYPE(routine_stat_type), POINTER                   :: r_stat
     469             :       TYPE(timer_env_type), POINTER                      :: timer_env
     470             : 
     471  3125126754 :       timer_env => list_peek(timers_stack)
     472  3125126754 :       routine_id = routine_map_get(timer_env%routine_names, routineN, default_value=-1)
     473             : 
     474  3125126754 :       IF (routine_id /= -1) RETURN ! found an id - let's return it
     475             :       ! routine not found - let's create it
     476             : 
     477             :       ! enforce space free timer names, to make the output of trace/timings of a fixed number fields
     478     3817457 :       IF (INDEX(routineN(1:LEN_TRIM(routineN)), ' ') /= 0) THEN
     479           0 :          CPABORT("timings_name2id: routineN contains spaces: "//routineN)
     480             :       END IF
     481             : 
     482             :       ! register routine_name_dsl with new routine_id
     483     3817457 :       routine_id = routine_map_size(timer_env%routine_names) + 1
     484     3817457 :       CALL routine_map_set(timer_env%routine_names, routineN, routine_id)
     485             : 
     486     3817457 :       ALLOCATE (r_stat)
     487     3817457 :       r_stat%routine_id = routine_id
     488     3817457 :       r_stat%routineN = routineN
     489             :       r_stat%active_calls = 0
     490             :       r_stat%excl_walltime_accu = 0.0_dp
     491             :       r_stat%incl_walltime_accu = 0.0_dp
     492             :       r_stat%excl_energy_accu = 0.0_dp
     493             :       r_stat%incl_energy_accu = 0.0_dp
     494             :       r_stat%total_calls = 0
     495             :       r_stat%stackdepth_accu = 0
     496             :       r_stat%trace = .FALSE.
     497     3817457 :       CALL list_push(timer_env%routine_stats, r_stat)
     498     3817457 :       CPASSERT(list_size(timer_env%routine_stats) == routine_map_size(timer_env%routine_names))
     499             :    END FUNCTION routine_name2id
     500             : 
     501             : END MODULE timings
     502             : 

Generated by: LCOV version 1.15