(git:21ef868)
Loading...
Searching...
No Matches
timings.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 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! **************************************************************************************************
17MODULE timings
18 USE base_hooks, ONLY: timeset_hook,&
20 USE callgraph, ONLY: callgraph_destroy,&
26 USE kinds, ONLY: default_string_length,&
27 dp,&
28 int_8
29 USE list, ONLY: &
31 list_size, list_timerenv_type
32 USE machine, ONLY: m_energy,&
33 m_flush,&
34 m_memory,&
36 USE offload_api, ONLY: offload_mem_info,&
48#include "../base/base_uses.f90"
49
50 IMPLICIT NONE
51 PRIVATE
52
54
55 ! these routines are currently only used by environment.F and f77_interface.F
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)
66
67 INTEGER, PUBLIC, PARAMETER :: default_timings_level = 1
69
70 CHARACTER(LEN=default_string_length), PUBLIC, PARAMETER :: root_cp2k_name = 'CP2K'
71
72CONTAINS
73
74! **************************************************************************************************
75!> \brief Registers handlers with base_hooks.F
76!> \author Ole Schuett
77! **************************************************************************************************
81 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 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 IF (PRESENT(timer_env)) timer_env_ => timer_env
98 IF (.NOT. PRESENT(timer_env)) CALL timer_env_create(timer_env_)
99 IF (.NOT. ASSOCIATED(timer_env_)) THEN
100 cpabort("add_timer_env: not associated")
101 END IF
102
103 CALL timer_env_retain(timer_env_)
104 IF (.NOT. list_isready(timers_stack)) CALL list_init(timers_stack)
105 CALL list_push(timers_stack, timer_env_)
106 END SUBROUTINE add_timer_env
107
108! **************************************************************************************************
109!> \brief creates a new timer env
110!> \param timer_env ...
111!> \author fawzi
112! **************************************************************************************************
113 SUBROUTINE timer_env_create(timer_env)
114 TYPE(timer_env_type), POINTER :: timer_env
115
116 ALLOCATE (timer_env)
117 timer_env%ref_count = 0
118 timer_env%trace_max = -1 ! tracing disabled by default
119 timer_env%trace_all = .false.
120 CALL routine_map_init(timer_env%routine_names)
121 CALL callgraph_init(timer_env%callgraph)
122 CALL list_init(timer_env%routine_stats)
123 CALL list_init(timer_env%callstack)
124 END SUBROUTINE timer_env_create
125
126! **************************************************************************************************
127!> \brief removes the current timer env from the stack
128!> \par History
129!> 02.2004 created [Joost VandeVondele]
130!> \note
131!> for each rm_timer_env there should have been the symmetric call to
132!> add_timer_env
133! **************************************************************************************************
134 SUBROUTINE rm_timer_env()
135 TYPE(timer_env_type), POINTER :: timer_env
136
137 timer_env => list_pop(timers_stack)
138 CALL timer_env_release(timer_env)
139 IF (list_size(timers_stack) == 0) CALL list_destroy(timers_stack)
140 END SUBROUTINE rm_timer_env
141
142! **************************************************************************************************
143!> \brief returns the current timer env from the stack
144!> \return ...
145!> \author fawzi
146! **************************************************************************************************
147 FUNCTION get_timer_env() RESULT(timer_env)
148 TYPE(timer_env_type), POINTER :: timer_env
149
150 timer_env => list_peek(timers_stack)
151 END FUNCTION get_timer_env
152
153! **************************************************************************************************
154!> \brief retains the given timer env
155!> \param timer_env the timer env to retain
156!> \author fawzi
157! **************************************************************************************************
158 SUBROUTINE timer_env_retain(timer_env)
159 TYPE(timer_env_type), POINTER :: timer_env
160
161 IF (.NOT. ASSOCIATED(timer_env)) THEN
162 cpabort("timer_env_retain: not associated")
163 END IF
164 IF (timer_env%ref_count < 0) THEN
165 cpabort("timer_env_retain: negativ ref_count")
166 END IF
167 timer_env%ref_count = timer_env%ref_count + 1
168 END SUBROUTINE timer_env_retain
169
170! **************************************************************************************************
171!> \brief releases the given timer env
172!> \param timer_env the timer env to release
173!> \author fawzi
174! **************************************************************************************************
175 SUBROUTINE timer_env_release(timer_env)
176 TYPE(timer_env_type), POINTER :: timer_env
177
178 INTEGER :: i
179 TYPE(callgraph_item_type), DIMENSION(:), POINTER :: ct_items
180 TYPE(routine_stat_type), POINTER :: r_stat
181
182 IF (.NOT. ASSOCIATED(timer_env)) THEN
183 cpabort("timer_env_release: not associated")
184 END IF
185 IF (timer_env%ref_count < 0) THEN
186 cpabort("timer_env_release: negativ ref_count")
187 END IF
188 timer_env%ref_count = timer_env%ref_count - 1
189 IF (timer_env%ref_count > 0) RETURN
190
191 ! No more references left - let's tear down this timer_env...
192
193 DO i = 1, list_size(timer_env%routine_stats)
194 r_stat => list_get(timer_env%routine_stats, i)
195 DEALLOCATE (r_stat)
196 END DO
197
198 ct_items => callgraph_items(timer_env%callgraph)
199 DO i = 1, SIZE(ct_items)
200 DEALLOCATE (ct_items(i)%value)
201 END DO
202 DEALLOCATE (ct_items)
203
204 CALL routine_map_destroy(timer_env%routine_names)
205 CALL callgraph_destroy(timer_env%callgraph)
206 CALL list_destroy(timer_env%callstack)
207 CALL list_destroy(timer_env%routine_stats)
208 DEALLOCATE (timer_env)
209 END SUBROUTINE timer_env_release
210
211! **************************************************************************************************
212!> \brief Start timer
213!> \param routineN ...
214!> \param handle ...
215!> \par History
216!> none
217!> \author JGH
218! **************************************************************************************************
219 SUBROUTINE timeset_handler(routineN, handle)
220 CHARACTER(LEN=*), INTENT(IN) :: routinen
221 INTEGER, INTENT(OUT) :: handle
222
223 CHARACTER(LEN=400) :: line, mystring
224 CHARACTER(LEN=60) :: sformat
225 CHARACTER(LEN=default_string_length) :: routine_name_dsl
226 INTEGER :: routine_id, stack_size
227 INTEGER(KIND=int_8) :: cpumem, gpumem_free, gpumem_total
228 INTEGER, SAVE :: root_cp2k_id
229 TYPE(callstack_entry_type) :: cs_entry
230 TYPE(routine_stat_type), POINTER :: r_stat
231 TYPE(timer_env_type), POINTER :: timer_env
232
233!$OMP MASTER
234
235 ! Default value, using a negative value when timing is not taken
236 cs_entry%walltime_start = -huge(1.0_dp)
237 cs_entry%energy_start = -huge(1.0_dp)
238 root_cp2k_id = routine_name2id(root_cp2k_name)
239 !
240 routine_name_dsl = routinen ! converte to default_string_length
241 routine_id = routine_name2id(routine_name_dsl)
242 !
243 ! Take timings when the timings_level is appropriated
244 IF (global_timings_level /= 0 .OR. routine_id == root_cp2k_id) THEN
245 cs_entry%walltime_start = m_walltime()
246 cs_entry%energy_start = m_energy()
247 END IF
248 timer_env => list_peek(timers_stack)
249
250 IF (len_trim(routinen) > default_string_length) THEN
251 cpabort('timings_timeset: routineN too long: "'//trim(routinen)//"'")
252 END IF
253
254 ! update routine r_stats
255 r_stat => list_get(timer_env%routine_stats, routine_id)
256 stack_size = list_size(timer_env%callstack)
257 r_stat%total_calls = r_stat%total_calls + 1
258 r_stat%active_calls = r_stat%active_calls + 1
259 r_stat%stackdepth_accu = r_stat%stackdepth_accu + stack_size + 1
260
261 ! add routine to callstack
262 cs_entry%routine_id = routine_id
263 CALL list_push(timer_env%callstack, cs_entry)
264
265 !..if debug mode echo the subroutine name
266 IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
267 (r_stat%total_calls < timer_env%trace_max)) THEN
268 WRITE (sformat, *) "(A,A,", max(1, 3*stack_size - 4), "X,I4,1X,I6,1X,A,A)"
269 WRITE (mystring, sformat) timer_env%trace_str, ">>", stack_size + 1, &
270 r_stat%total_calls, trim(r_stat%routineN), " start"
271 CALL offload_mem_info(gpumem_free, gpumem_total)
272 CALL m_memory(cpumem)
273 WRITE (line, '(A,A,I0,A,A,I0,A)') trim(mystring), &
274 " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024), " MB", &
275 " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024), " MB"
276 WRITE (timer_env%trace_unit, *) trim(line)
277 CALL m_flush(timer_env%trace_unit)
278 END IF
279
280 handle = routine_id
281
282 CALL offload_timeset(routinen)
283
284!$OMP END MASTER
285
286 END SUBROUTINE timeset_handler
287
288! **************************************************************************************************
289!> \brief End timer
290!> \param handle ...
291!> \par History
292!> none
293!> \author JGH
294! **************************************************************************************************
295 SUBROUTINE timestop_handler(handle)
296 INTEGER, INTENT(in) :: handle
297
298 CHARACTER(LEN=400) :: line, mystring
299 CHARACTER(LEN=60) :: sformat
300 INTEGER :: routine_id, stack_size
301 INTEGER(KIND=int_8) :: cpumem, gpumem_free, gpumem_total
302 INTEGER, DIMENSION(2) :: routine_tuple
303 REAL(kind=dp) :: en_elapsed, en_now, wt_elapsed, wt_now
304 TYPE(call_stat_type), POINTER :: c_stat
305 TYPE(callstack_entry_type) :: cs_entry, prev_cs_entry
306 TYPE(routine_stat_type), POINTER :: prev_stat, r_stat
307 TYPE(timer_env_type), POINTER :: timer_env
308
309 routine_id = handle
310
311!$OMP MASTER
312
313 CALL offload_timestop()
314
315 timer_env => list_peek(timers_stack)
316 cs_entry = list_pop(timer_env%callstack)
317 r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
318
319 IF (handle /= cs_entry%routine_id) THEN
320 print *, "list_size(timer_env%callstack) ", list_size(timer_env%callstack), &
321 " handle ", handle, " list_size(timers_stack) ", list_size(timers_stack)
322 cpabort('mismatched timestop '//trim(r_stat%routineN)//' in routine timestop')
323 END IF
324
325 wt_elapsed = 0
326 en_elapsed = 0
327 ! Take timings only when the start time is >=0, i.e. the timings_level is appropriated
328 IF (cs_entry%walltime_start >= 0) THEN
329 wt_now = m_walltime()
330 en_now = m_energy()
331 ! add the elapsed time for this timeset/timestop to the time accumulator
332 wt_elapsed = wt_now - cs_entry%walltime_start
333 en_elapsed = en_now - cs_entry%energy_start
334 END IF
335 r_stat%active_calls = r_stat%active_calls - 1
336
337 ! if we're the last instance in the stack, we do the accounting of the total time
338 IF (r_stat%active_calls == 0) THEN
339 r_stat%incl_walltime_accu = r_stat%incl_walltime_accu + wt_elapsed
340 r_stat%incl_energy_accu = r_stat%incl_energy_accu + en_elapsed
341 END IF
342
343 ! exclusive time we always sum, since children will correct this time with their total time
344 r_stat%excl_walltime_accu = r_stat%excl_walltime_accu + wt_elapsed
345 r_stat%excl_energy_accu = r_stat%excl_energy_accu + en_elapsed
346
347 stack_size = list_size(timer_env%callstack)
348 IF (stack_size > 0) THEN
349 prev_cs_entry = list_peek(timer_env%callstack)
350 prev_stat => list_get(timer_env%routine_stats, prev_cs_entry%routine_id)
351 ! we fixup the clock of the caller
352 prev_stat%excl_walltime_accu = prev_stat%excl_walltime_accu - wt_elapsed
353 prev_stat%excl_energy_accu = prev_stat%excl_energy_accu - en_elapsed
354
355 !update callgraph
356 routine_tuple = [prev_cs_entry%routine_id, routine_id]
357 c_stat => callgraph_get(timer_env%callgraph, routine_tuple, default_value=null(c_stat))
358 IF (.NOT. ASSOCIATED(c_stat)) THEN
359 ALLOCATE (c_stat)
360 c_stat%total_calls = 0
361 c_stat%incl_walltime_accu = 0.0_dp
362 c_stat%incl_energy_accu = 0.0_dp
363 CALL callgraph_set(timer_env%callgraph, routine_tuple, c_stat)
364 END IF
365 c_stat%total_calls = c_stat%total_calls + 1
366 c_stat%incl_walltime_accu = c_stat%incl_walltime_accu + wt_elapsed
367 c_stat%incl_energy_accu = c_stat%incl_energy_accu + en_elapsed
368 END IF
369
370 !..if debug mode echo the subroutine name
371 IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
372 (r_stat%total_calls < timer_env%trace_max)) THEN
373 WRITE (sformat, *) "(A,A,", max(1, 3*stack_size - 4), "X,I4,1X,I6,1X,A,F12.3)"
374 WRITE (mystring, sformat) timer_env%trace_str, "<<", stack_size + 1, &
375 r_stat%total_calls, trim(r_stat%routineN), wt_elapsed
376 CALL offload_mem_info(gpumem_free, gpumem_total)
377 CALL m_memory(cpumem)
378 WRITE (line, '(A,A,I0,A,A,I0,A)') trim(mystring), &
379 " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024), " MB", &
380 " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024), " MB"
381 WRITE (timer_env%trace_unit, *) trim(line)
382 CALL m_flush(timer_env%trace_unit)
383 END IF
384
385!$OMP END MASTER
386
387 END SUBROUTINE timestop_handler
388
389! **************************************************************************************************
390!> \brief Set routine tracer
391!> \param trace_max maximum number of calls reported per routine.
392!> Setting this to zero disables tracing.
393!> \param unit_nr output unit used for printing the trace-messages
394!> \param trace_str short info-string which is printed along with every message
395!> \param routine_names List of routine-names.
396!> If provided only these routines will be traced.
397!> If not present all routines will traced.
398!> \par History
399!> 12.2012 added ability to trace only certain routines [ole]
400!> \author JGH
401! **************************************************************************************************
402 SUBROUTINE timings_setup_tracing(trace_max, unit_nr, trace_str, routine_names)
403 INTEGER, INTENT(IN) :: trace_max, unit_nr
404 CHARACTER(len=13), INTENT(IN) :: trace_str
405 CHARACTER(len=default_string_length), &
406 DIMENSION(:), INTENT(IN), OPTIONAL :: routine_names
407
408 INTEGER :: i, routine_id
409 TYPE(routine_stat_type), POINTER :: r_stat
410 TYPE(timer_env_type), POINTER :: timer_env
411
412 timer_env => list_peek(timers_stack)
413 timer_env%trace_max = trace_max
414 timer_env%trace_unit = unit_nr
415 timer_env%trace_str = trace_str
416 timer_env%trace_all = .true.
417 IF (.NOT. PRESENT(routine_names)) RETURN
418
419 ! setup routine-specific tracing
420 timer_env%trace_all = .false.
421 DO i = 1, SIZE(routine_names)
422 routine_id = routine_name2id(routine_names(i))
423 r_stat => list_get(timer_env%routine_stats, routine_id)
424 r_stat%trace = .true.
425 END DO
426
427 END SUBROUTINE timings_setup_tracing
428
429! **************************************************************************************************
430!> \brief Print current routine stack
431!> \param unit_nr ...
432!> \par History
433!> none
434!> \author JGH
435! **************************************************************************************************
436 SUBROUTINE print_stack(unit_nr)
437 INTEGER, INTENT(IN) :: unit_nr
438
439 INTEGER :: i
440 TYPE(callstack_entry_type) :: cs_entry
441 TYPE(routine_stat_type), POINTER :: r_stat
442 TYPE(timer_env_type), POINTER :: timer_env
443
444 ! catch edge cases where timer_env is not yet/anymore available
445 IF (.NOT. list_isready(timers_stack)) THEN
446 RETURN
447 END IF
448 IF (list_size(timers_stack) == 0) THEN
449 RETURN
450 END IF
451
452 timer_env => list_peek(timers_stack)
453 WRITE (unit_nr, '(/,A,/)') " ===== Routine Calling Stack ===== "
454 DO i = list_size(timer_env%callstack), 1, -1
455 cs_entry = list_get(timer_env%callstack, i)
456 r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
457 WRITE (unit_nr, '(T10,I4,1X,A)') i, trim(r_stat%routineN)
458 END DO
459 CALL m_flush(unit_nr)
460
461 END SUBROUTINE print_stack
462
463! **************************************************************************************************
464!> \brief Internal routine used by timestet and timings_setup_tracing.
465!> If no routine with given name is found in timer_env%routine_names
466!> then a new entiry is created.
467!> \param routineN ...
468!> \return ...
469!> \author Ole Schuett
470! **************************************************************************************************
471 FUNCTION routine_name2id(routineN) RESULT(routine_id)
472 CHARACTER(LEN=default_string_length), INTENT(IN) :: routinen
473 INTEGER :: routine_id
474
475 TYPE(routine_stat_type), POINTER :: r_stat
476 TYPE(timer_env_type), POINTER :: timer_env
477
478 timer_env => list_peek(timers_stack)
479 routine_id = routine_map_get(timer_env%routine_names, routinen, default_value=-1)
480
481 IF (routine_id /= -1) RETURN ! found an id - let's return it
482 ! routine not found - let's create it
483
484 ! enforce space free timer names, to make the output of trace/timings of a fixed number fields
485 IF (index(routinen(1:len_trim(routinen)), ' ') /= 0) THEN
486 cpabort("timings_name2id: routineN contains spaces: "//routinen)
487 END IF
488
489 ! register routine_name_dsl with new routine_id
490 routine_id = routine_map_size(timer_env%routine_names) + 1
491 CALL routine_map_set(timer_env%routine_names, routinen, routine_id)
492
493 ALLOCATE (r_stat)
494 r_stat%routine_id = routine_id
495 r_stat%routineN = routinen
496 r_stat%active_calls = 0
497 r_stat%excl_walltime_accu = 0.0_dp
498 r_stat%incl_walltime_accu = 0.0_dp
499 r_stat%excl_energy_accu = 0.0_dp
500 r_stat%incl_energy_accu = 0.0_dp
501 r_stat%total_calls = 0
502 r_stat%stackdepth_accu = 0
503 r_stat%trace = .false.
504 CALL list_push(timer_env%routine_stats, r_stat)
505 cpassert(list_size(timer_env%routine_stats) == routine_map_size(timer_env%routine_names))
506 END FUNCTION routine_name2id
507
508END MODULE timings
509
Central dispatch for basic hooks.
Definition base_hooks.F:12
procedure(timeset_interface), pointer, public timeset_hook
Definition base_hooks.F:61
procedure(timestop_interface), pointer, public timestop_hook
Definition base_hooks.F:62
subroutine, public callgraph_destroy(hash_map)
Deallocated the internal data-structures if the given hash map. Caution: If the stored keys or values...
Definition callgraph.F:122
subroutine, public callgraph_init(hash_map, initial_capacity)
Allocates the internal data-structures of the given hash map.
Definition callgraph.F:78
type(callgraph_item_type) function, dimension(:), pointer, public callgraph_items(hash_map)
Returns a pointer to an array of all key/value-items stored in the hash map. Caution: The caller is r...
Definition callgraph.F:385
type(call_stat_type) function, pointer, public callgraph_get(hash_map, key, default_value)
Gets a value for a given key from the hash map. If the key is not found the default_value will be ret...
Definition callgraph.F:257
subroutine, public callgraph_set(hash_map, key, value)
Stores, and possibly overwrites, a given value under a given key.
Definition callgraph.F:149
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition list.F:24
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
Definition machine.F:440
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:124
real(kind=dp) function, public m_energy()
returns the energy used since some time in the past. The precise meaning depends on the infrastructur...
Definition machine.F:329
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:141
Fortran API for the offload package, which is written in C.
Definition offload_api.F:12
subroutine, public offload_timestop()
Ends a timing range.
subroutine, public offload_timeset(routinen)
Starts a timing range.
subroutine, public offload_mem_info(free, total)
Gets free and total device memory.
integer(kind=int_4) function, public routine_map_get(hash_map, key, default_value)
Gets a value for a given key from the hash map. If the key is not found the default_value will be ret...
integer function, public routine_map_size(hash_map)
Returns the number of key/value-items currently stored in the hash map.
subroutine, public routine_map_init(hash_map, initial_capacity)
Allocates the internal data-structures of the given hash map.
Definition routine_map.F:77
subroutine, public routine_map_destroy(hash_map)
Deallocated the internal data-structures if the given hash map. Caution: If the stored keys or values...
subroutine, public routine_map_set(hash_map, key, value)
Stores, and possibly overwrites, a given value under a given key.
Types used by timings.F and timings_report.F The types in this module are used within dict or list,...
Types used by timings.F and timings_report.F Due to the fortran restriction on cicular module-depende...
Timing routines for accounting.
Definition timings.F:17
subroutine, public timings_register_hooks()
Registers handlers with base_hooks.F.
Definition timings.F:79
subroutine, public print_stack(unit_nr)
Print current routine stack.
Definition timings.F:437
type(timer_env_type) function, pointer, public get_timer_env()
returns the current timer env from the stack
Definition timings.F:148
subroutine, public timeset_handler(routinen, handle)
Start timer.
Definition timings.F:220
integer, save, public global_timings_level
Definition timings.F:68
subroutine, public timings_setup_tracing(trace_max, unit_nr, trace_str, routine_names)
Set routine tracer.
Definition timings.F:403
subroutine, public add_timer_env(timer_env)
adds the given timer_env to the top of the stack
Definition timings.F:93
subroutine, public rm_timer_env()
removes the current timer env from the stack
Definition timings.F:135
subroutine, public timer_env_release(timer_env)
releases the given timer env
Definition timings.F:176
subroutine, public timestop_handler(handle)
End timer.
Definition timings.F:296
subroutine, public timer_env_retain(timer_env)
retains the given timer env
Definition timings.F:159
integer, parameter, public default_timings_level
Definition timings.F:67
character(len=default_string_length), parameter, public root_cp2k_name
Definition timings.F:70