30 list_destroy, list_get, list_init, list_isready, list_peek, list_pop, list_push, &
31 list_size, list_timerenv_type
45 callstack_entry_type,&
48 #include "../base/base_uses.f90"
61 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'timings'
62 TYPE(list_timerenv_type),
SAVE,
PRIVATE :: timers_stack
70 CHARACTER(LEN=default_string_length),
PUBLIC,
PARAMETER ::
root_cp2k_name =
'CP2K'
93 TYPE(timer_env_type),
OPTIONAL,
POINTER :: timer_env
95 TYPE(timer_env_type),
POINTER :: timer_env_
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_)) &
100 cpabort(
"add_timer_env: not associated")
103 IF (.NOT. list_isready(timers_stack))
CALL list_init(timers_stack)
104 CALL list_push(timers_stack, timer_env_)
112 SUBROUTINE timer_env_create(timer_env)
113 TYPE(timer_env_type),
POINTER :: timer_env
116 timer_env%ref_count = 0
117 timer_env%trace_max = -1
118 timer_env%trace_all = .false.
121 CALL list_init(timer_env%routine_stats)
122 CALL list_init(timer_env%callstack)
123 END SUBROUTINE timer_env_create
134 TYPE(timer_env_type),
POINTER :: timer_env
136 timer_env => list_pop(timers_stack)
138 IF (list_size(timers_stack) == 0)
CALL list_destroy(timers_stack)
147 TYPE(timer_env_type),
POINTER :: timer_env
149 timer_env => list_peek(timers_stack)
158 TYPE(timer_env_type),
POINTER :: timer_env
160 IF (.NOT.
ASSOCIATED(timer_env)) &
161 cpabort(
"timer_env_retain: not associated")
162 IF (timer_env%ref_count < 0) &
163 cpabort(
"timer_env_retain: negativ ref_count")
164 timer_env%ref_count = timer_env%ref_count + 1
173 TYPE(timer_env_type),
POINTER :: timer_env
176 TYPE(callgraph_item_type),
DIMENSION(:),
POINTER :: ct_items
177 TYPE(routine_stat_type),
POINTER :: r_stat
179 IF (.NOT.
ASSOCIATED(timer_env)) &
180 cpabort(
"timer_env_release: not associated")
181 IF (timer_env%ref_count < 0) &
182 cpabort(
"timer_env_release: negativ ref_count")
183 timer_env%ref_count = timer_env%ref_count - 1
184 IF (timer_env%ref_count > 0)
RETURN
188 DO i = 1, list_size(timer_env%routine_stats)
189 r_stat => list_get(timer_env%routine_stats, i)
194 DO i = 1,
SIZE(ct_items)
195 DEALLOCATE (ct_items(i)%value)
197 DEALLOCATE (ct_items)
201 CALL list_destroy(timer_env%callstack)
202 CALL list_destroy(timer_env%routine_stats)
203 DEALLOCATE (timer_env)
215 CHARACTER(LEN=*),
INTENT(IN) :: routinen
216 INTEGER,
INTENT(OUT) :: handle
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
231 cs_entry%walltime_start = -huge(1.0_dp)
232 cs_entry%energy_start = -huge(1.0_dp)
235 routine_name_dsl = routinen
236 routine_id = routine_name2id(routine_name_dsl)
243 timer_env => list_peek(timers_stack)
246 cpabort(
'timings_timeset: routineN too long: "'//trim(routinen)//
"'")
250 r_stat => list_get(timer_env%routine_stats, routine_id)
251 stack_size = list_size(timer_env%callstack)
252 r_stat%total_calls = r_stat%total_calls + 1
253 r_stat%active_calls = r_stat%active_calls + 1
254 r_stat%stackdepth_accu = r_stat%stackdepth_accu + stack_size + 1
257 cs_entry%routine_id = routine_id
258 CALL list_push(timer_env%callstack, cs_entry)
261 IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
262 (r_stat%total_calls < timer_env%trace_max))
THEN
263 WRITE (sformat, *)
"(A,A,", max(1, 3*stack_size - 4),
"X,I4,1X,I6,1X,A,A)"
264 WRITE (mystring, sformat) timer_env%trace_str,
">>", stack_size + 1, &
265 r_stat%total_calls, trim(r_stat%routineN),
" start"
268 WRITE (line,
'(A,A,I0,A,A,I0,A)') trim(mystring), &
269 " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024),
" MB", &
270 " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024),
" MB"
271 WRITE (timer_env%trace_unit, *) trim(line)
272 CALL m_flush(timer_env%trace_unit)
291 INTEGER,
INTENT(in) :: handle
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
310 timer_env => list_peek(timers_stack)
311 cs_entry = list_pop(timer_env%callstack)
312 r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
314 IF (handle /= cs_entry%routine_id)
THEN
315 print *,
"list_size(timer_env%callstack) ", list_size(timer_env%callstack), &
316 " handle ", handle,
" list_size(timers_stack) ", list_size(timers_stack)
317 cpabort(
'mismatched timestop '//trim(r_stat%routineN)//
' in routine timestop')
323 IF (cs_entry%walltime_start .GE. 0)
THEN
327 wt_elapsed = wt_now - cs_entry%walltime_start
328 en_elapsed = en_now - cs_entry%energy_start
330 r_stat%active_calls = r_stat%active_calls - 1
333 IF (r_stat%active_calls == 0)
THEN
334 r_stat%incl_walltime_accu = r_stat%incl_walltime_accu + wt_elapsed
335 r_stat%incl_energy_accu = r_stat%incl_energy_accu + en_elapsed
339 r_stat%excl_walltime_accu = r_stat%excl_walltime_accu + wt_elapsed
340 r_stat%excl_energy_accu = r_stat%excl_energy_accu + en_elapsed
342 stack_size = list_size(timer_env%callstack)
343 IF (stack_size > 0)
THEN
344 prev_cs_entry = list_peek(timer_env%callstack)
345 prev_stat => list_get(timer_env%routine_stats, prev_cs_entry%routine_id)
347 prev_stat%excl_walltime_accu = prev_stat%excl_walltime_accu - wt_elapsed
348 prev_stat%excl_energy_accu = prev_stat%excl_energy_accu - en_elapsed
351 routine_tuple = (/prev_cs_entry%routine_id, routine_id/)
352 c_stat =>
callgraph_get(timer_env%callgraph, routine_tuple, default_value=null(c_stat))
353 IF (.NOT.
ASSOCIATED(c_stat))
THEN
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 CALL callgraph_set(timer_env%callgraph, routine_tuple, c_stat)
360 c_stat%total_calls = c_stat%total_calls + 1
361 c_stat%incl_walltime_accu = c_stat%incl_walltime_accu + wt_elapsed
362 c_stat%incl_energy_accu = c_stat%incl_energy_accu + en_elapsed
366 IF ((timer_env%trace_all .OR. r_stat%trace) .AND. &
367 (r_stat%total_calls < timer_env%trace_max))
THEN
368 WRITE (sformat, *)
"(A,A,", max(1, 3*stack_size - 4),
"X,I4,1X,I6,1X,A,F12.3)"
369 WRITE (mystring, sformat) timer_env%trace_str,
"<<", stack_size + 1, &
370 r_stat%total_calls, trim(r_stat%routineN), wt_elapsed
373 WRITE (line,
'(A,A,I0,A,A,I0,A)') trim(mystring), &
374 " Hostmem: ", (cpumem + 1024*1024 - 1)/(1024*1024),
" MB", &
375 " GPUmem: ", (gpumem_total - gpumem_free)/(1024*1024),
" MB"
376 WRITE (timer_env%trace_unit, *) trim(line)
377 CALL m_flush(timer_env%trace_unit)
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
403 INTEGER :: i, routine_id
404 TYPE(routine_stat_type),
POINTER :: r_stat
405 TYPE(timer_env_type),
POINTER :: timer_env
407 timer_env => list_peek(timers_stack)
408 timer_env%trace_max = trace_max
409 timer_env%trace_unit = unit_nr
410 timer_env%trace_str = trace_str
411 timer_env%trace_all = .true.
412 IF (.NOT.
PRESENT(routine_names))
RETURN
415 timer_env%trace_all = .false.
416 DO i = 1,
SIZE(routine_names)
417 routine_id = routine_name2id(routine_names(i))
418 r_stat => list_get(timer_env%routine_stats, routine_id)
419 r_stat%trace = .true.
432 INTEGER,
INTENT(IN) :: unit_nr
435 TYPE(callstack_entry_type) :: cs_entry
436 TYPE(routine_stat_type),
POINTER :: r_stat
437 TYPE(timer_env_type),
POINTER :: timer_env
440 IF (.NOT. list_isready(timers_stack)) &
442 IF (list_size(timers_stack) == 0) &
445 timer_env => list_peek(timers_stack)
446 WRITE (unit_nr,
'(/,A,/)')
" ===== Routine Calling Stack ===== "
447 DO i = list_size(timer_env%callstack), 1, -1
448 cs_entry = list_get(timer_env%callstack, i)
449 r_stat => list_get(timer_env%routine_stats, cs_entry%routine_id)
450 WRITE (unit_nr,
'(T10,I4,1X,A)') i, trim(r_stat%routineN)
464 FUNCTION routine_name2id(routineN)
RESULT(routine_id)
465 CHARACTER(LEN=default_string_length),
INTENT(IN) :: routinen
466 INTEGER :: routine_id
468 TYPE(routine_stat_type),
POINTER :: r_stat
469 TYPE(timer_env_type),
POINTER :: timer_env
471 timer_env => list_peek(timers_stack)
472 routine_id =
routine_map_get(timer_env%routine_names, routinen, default_value=-1)
474 IF (routine_id /= -1)
RETURN
478 IF (index(routinen(1:len_trim(routinen)),
' ') /= 0)
THEN
479 cpabort(
"timings_name2id: routineN contains spaces: "//routinen)
487 r_stat%routine_id = routine_id
488 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 CALL list_push(timer_env%routine_stats, r_stat)
498 cpassert(list_size(timer_env%routine_stats) ==
routine_map_size(timer_env%routine_names))
499 END FUNCTION routine_name2id
Central dispatch for basic hooks.
procedure(timeset_interface), pointer, public timeset_hook
procedure(timestop_interface), pointer, public timestop_hook
subroutine, public callgraph_destroy(hash_map)
Deallocated the internal data-structures if the given hash map. Caution: If the stored keys or values...
subroutine, public callgraph_init(hash_map, initial_capacity)
Allocates the internal data-structures of the given hash map.
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...
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...
subroutine, public callgraph_set(hash_map, key, value)
Stores, and possibly overwrites, a given value under a given key.
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
integer, parameter, public default_string_length
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_energy()
returns the energy used since some time in the past. The precise meaning depends on the infrastructur...
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Fortran API for the offload package, which is written in C.
subroutine, public offload_timeset(routineN)
Starts a timing range.
subroutine, public offload_timestop()
Ends 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.
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.
subroutine, public timings_register_hooks()
Registers handlers with base_hooks.F.
subroutine, public print_stack(unit_nr)
Print current routine stack.
type(timer_env_type) function, pointer, public get_timer_env()
returns the current timer env from the stack
integer, save, public global_timings_level
subroutine, public timings_setup_tracing(trace_max, unit_nr, trace_str, routine_names)
Set routine tracer.
subroutine, public timeset_handler(routineN, handle)
Start timer.
subroutine, public add_timer_env(timer_env)
adds the given timer_env to the top of the stack
subroutine, public rm_timer_env()
removes the current timer env from the stack
subroutine, public timer_env_release(timer_env)
releases the given timer env
subroutine, public timestop_handler(handle)
End timer.
subroutine, public timer_env_retain(timer_env)
retains the given timer env
integer, parameter, public default_timings_level
character(len=default_string_length), parameter, public root_cp2k_name