Octopus
profiling.F90
Go to the documentation of this file.
1!! Copyright (C) 2005-2009 Heiko Appel, Florian Lorenzen, Xavier Andrade
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
49 !*/
50module profiling_oct_m
51 use debug_oct_m
52 use global_oct_m
53 use io_oct_m
54 use, intrinsic :: iso_fortran_env
55 use loct_oct_m
57 use mpi_oct_m
58 use parser_oct_m
60 use nvtx_oct_m
61 use sort_oct_m
62 use sphash_oct_m
63 use string_oct_m
64 use types_oct_m
66
67 implicit none
68 private
69
70 public :: &
80
81 integer, parameter :: &
82 LABEL_LENGTH = 40, & !< Max. number of characters of tag label.
83 max_profiles = 300
84
85 type profile_t
86 private
87 character(LABEL_LENGTH) :: label
88 real(real64) :: entry_time
89 real(real64) :: total_time
90 real(real64) :: min_time
91 real(real64) :: self_time
92 real(real64) :: op_count_current
93 real(real64) :: op_count
94 real(real64) :: op_count_child
95 real(real64) :: op_count_child_current
96 real(real64) :: tr_count_current
97 real(real64) :: tr_count
98 real(real64) :: tr_count_child
99 real(real64) :: tr_count_child_current
100 type(profile_t), pointer :: parent
101 integer :: count
102 logical :: initialized = .false.
103 logical :: active = .false.
104 logical :: exclude
105 logical :: likwid
106 integer :: index
107 logical :: has_child(MAX_PROFILES)
108 real(real64) :: timings(MAX_PROFILES)
109 end type profile_t
110
112 private
113 type(profile_t), pointer :: p
114 end type profile_pointer_t
115
117 module procedure &
125 module procedure &
133 end interface profiling_count_transfers
134
136 module procedure iprofiling_count_operations
137 module procedure rprofiling_count_operations
138 module procedure dprofiling_count_operations
139 end interface profiling_count_operations
140
141 integer, parameter, public :: &
142 PROFILING_TIME = 1, &
145 profiling_likwid = 8, &
146 profiling_io = 16
147
148 integer, parameter :: MAX_MEMORY_VARS = 25
149
150 type profile_vars_t
151 private
152 integer, public :: mode
153
154 type(profile_pointer_t) :: current
155 type(profile_pointer_t) :: profile_list(MAX_PROFILES)
156 integer :: last_profile
157
158 integer(int64) :: alloc_count
159 integer(int64) :: dealloc_count
160
161 integer(int64) :: memory_limit = -1
162 integer(int64) :: total_memory
163 integer(int64) :: max_memory
164 character(len=256) :: max_memory_location
165
166 integer(int64) :: large_vars_size(MAX_MEMORY_VARS)
167 character(len=256) :: large_vars(MAX_MEMORY_VARS)
168
169 real(real64) :: start_time
170 integer :: mem_iunit
171
172 character(len=256) :: output_dir
173 character(len=6) :: file_number
175 logical :: all_nodes
176
177 logical :: output_yaml
178 logical :: output_tree
179
180 character(LABEL_LENGTH), allocatable :: likwid_regions(:)
183 type(profile_vars_t), target, save, public :: prof_vars
185 type(sphash_t), save :: profiling_map
187contains
189 ! ---------------------------------------------------------
191 subroutine profiling_init(namespace)
192 type(namespace_t), intent(in) :: namespace
194 integer :: ii
195 type(block_t) :: blk
196 character(len=256) :: label
200 ! FIXME: nothing is thread-safe here!
202 !%Variable ProfilingMode
203 !%Default no
204 !%Type flag
205 !%Section Execution::Optimization
206 !%Description
207 !% Use this variable to run <tt>Octopus</tt> in profiling mode. In this mode
208 !% <tt>Octopus</tt> records the time spent in certain areas of the code and
209 !% the number of times this code is executed. These numbers
210 !% are written in <tt>./profiling.NNN/profiling.nnn</tt> with <tt>nnn</tt> being the
211 !% node number (<tt>000</tt> in serial) and <tt>NNN</tt> the number of processors.
212 !% This is mainly for development purposes. Note, however, that
213 !% <tt>Octopus</tt> should be compiled with <tt>--disable-debug</tt> to do proper
214 !% profiling. Warning: you may encounter strange results with OpenMP.
215 !%Option no 0
216 !% No profiling information is generated.
217 !%Option prof_time 1
218 !% Profile the time spent in defined profiling regions.
219 !%Option prof_memory 2
220 !% As well as the time, summary information on memory usage and the largest arrays are reported.
221 !%Option prof_memory_full 4
222 !% As well as the time and summary memory information, a
223 !% log is reported of every allocation and deallocation.
224 !%Option likwid 8
225 !% Enable instrumentation using LIKWID.
226 !%Option prof_io 16
227 !% Count the number of file open and close.
228 !%End
229
230 call parse_variable(namespace, 'ProfilingMode', 0, prof_vars%mode)
231 if (.not. varinfo_valid_option('ProfilingMode', prof_vars%mode, is_flag=.true.)) then
232 call messages_input_error(namespace, 'ProfilingMode')
233 end if
235 in_profiling_mode = (prof_vars%mode > 0)
236 if (.not. in_profiling_mode) then
237 pop_sub(profiling_init)
238 return
239 end if
240
241 !%Variable ProfilingAllNodes
242 !%Default no
243 !%Type logical
244 !%Section Execution::Optimization
245 !%Description
246 !% This variable controls whether all nodes print the time
247 !% profiling output. If set to no, the default, only the root node
248 !% will write the profile. If set to yes, all nodes will print it.
249 !%End
250
251 call parse_variable(namespace, 'ProfilingAllNodes', .false., prof_vars%all_nodes)
253 call get_output_dir()
257 end if
258
259 ! initialize memory profiling
260 if (bitand(prof_vars%mode, profiling_memory) /= 0) then
261 prof_vars%alloc_count = 0
262 prof_vars%dealloc_count = 0
264 prof_vars%total_memory = 0
265 prof_vars%max_memory = 0
266 prof_vars%max_memory_location = ''
267 prof_vars%start_time = loct_clock()
269 prof_vars%large_vars_size(:) = 0
270 prof_vars%large_vars(:) = ''
272 !%Variable MemoryLimit
273 !%Default -1
274 !%Type integer
275 !%Section Execution::Optimization
276 !%Description
277 !% If positive, <tt>Octopus</tt> will stop if more memory than <tt>MemoryLimit</tt>
278 !% is requested (in kb). Note that this variable only works when
279 !% <tt>ProfilingMode = prof_memory(_full)</tt>.
280 !%End
281 call parse_variable(namespace, 'MemoryLimit', -1, ii)
282 prof_vars%memory_limit = int(ii, int64)*1024
283 end if
285 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
286 ! make sure output directory is available before other processes try to write there
287 call mpi_world%barrier()
288
289 prof_vars%mem_iunit = io_open(trim(prof_vars%output_dir)//'/memory.'//prof_vars%file_number, &
290 namespace, action='write')
291 write(prof_vars%mem_iunit, '(5a16,a70)') 'Elapsed Time', 'Alloc/Dealloc', 'Size (words)', 'Prof Mem', &
292 'Sys Mem', 'Variable Name(Filename:Line)'
293 end if
294
295 ! initialize time profiling
296 prof_vars%last_profile = 0
297 nullify(prof_vars%current%p)
298
299 !%Variable LikwidRegions
300 !%Type block
301 !%Section Execution::Optimization
302 !%Description
303 !% Restricts the LIKWID markers (<tt>ProfilingMode = likwid</tt>) to the listed
304 !% profiling regions, given by their labels (case-insensitive). If the block is
305 !% not present, all profiling regions are marked. Example:
306 !%
307 !% <tt>%LikwidRegions
308 !% <br>&nbsp;&nbsp;"SCF_CYCLE"
309 !% <br>&nbsp;&nbsp;"BATCH_COPY"
310 !% <br>%</tt>
311 !%End
312 if (parse_block(namespace, 'LikwidRegions', blk) == 0) then
313 if (bitand(prof_vars%mode, profiling_likwid) /= 0) then
314 safe_allocate(prof_vars%likwid_regions(1:parse_block_n(blk)))
315 do ii = 1, parse_block_n(blk)
316 call parse_block_string(blk, ii - 1, 0, label)
317 if (len_trim(label) > label_length) then
318 message(1) = "LikwidRegions: label " // trim(label) // " is too long"
319 call messages_fatal(1, namespace=namespace)
320 end if
321 prof_vars%likwid_regions(ii) = to_upper(trim(label))
322 end do
323 else
324 message(1) = "LikwidRegions is ignored because ProfilingMode does not include likwid."
325 call messages_warning(1, namespace=namespace)
326 end if
327 call parse_block_end(blk)
328 end if
329
330 if (bitand(prof_vars%mode, profiling_likwid) /= 0) then
331#ifdef HAVE_LIKWID
332 call likwid_markerinit()
333#endif
334 end if
335
336 !%Variable ProfilingOutputYAML
337 !%Default no
338 !%Type logical
339 !%Section Execution::Optimization
340 !%Description
341 !% This variable controls whether the profiling output is additionally
342 !% written to a YAML file.
343 !%End
344 call parse_variable(namespace, 'ProfilingOutputYAML', .false., prof_vars%output_yaml)
345
346 !%Variable ProfilingOutputTree
347 !%Default yes
348 !%Type logical
349 !%Section Execution::Optimization
350 !%Description
351 !% This variable controls whether the profiling output is additionally
352 !% written as a tree.
353 !%End
354 call parse_variable(namespace, 'ProfilingOutputTree', .true., prof_vars%output_tree)
355
357
358 call profiling_in('COMPLETE_RUN')
359
360 pop_sub(profiling_init)
361
362 contains
363
364 ! ---------------------------------------------------------
365 subroutine get_output_dir()
366
368
369 write(prof_vars%file_number, '(i6.6)') mpi_world%rank
370
371 prof_vars%output_dir = 'profiling'
372
373 if (mpi_world%is_root()) call io_mkdir(trim(prof_vars%output_dir), namespace)
374
376 end subroutine get_output_dir
377
378 end subroutine profiling_init
379
380
381 ! ---------------------------------------------------------
382 subroutine profiling_end(namespace)
383 type(namespace_t), intent(in) :: namespace
384 integer :: ii
385 real(real64), parameter :: megabyte = 1048576.0_real64
386 integer(int64) :: io_open_count, io_close_count
387 integer(int64) :: io_open_count_red, io_close_count_red
388
389 if (.not. in_profiling_mode) return
390 push_sub(profiling_end)
391
392 call profiling_out('COMPLETE_RUN')
393 call profiling_output(namespace)
394
395 do ii = 1, prof_vars%last_profile
396 prof_vars%profile_list(ii)%p%initialized = .false.
397 end do
398
400 safe_deallocate_a(prof_vars%likwid_regions)
401
402 if (bitand(prof_vars%mode, profiling_memory) /= 0) then
403 call messages_print_with_emphasis(msg="Memory profiling information", namespace=namespace)
404 write(message(1), '(a,i10)') 'Number of allocations = ', prof_vars%alloc_count
405 write(message(2), '(a,i10)') 'Number of deallocations = ', prof_vars%dealloc_count
406 write(message(3), '(a,f18.3,a)') 'Maximum total memory allocated = ', prof_vars%max_memory/megabyte, ' Mbytes'
407 write(message(4), '(2x,a,a)') 'at ', trim(prof_vars%max_memory_location)
408 call messages_info(4)
409
410 message(1) = ''
411 message(2) = 'Largest variables allocated:'
412 call messages_info(2)
413 do ii = 1, max_memory_vars
414 write(message(1),'(i2,f18.3,2a)') ii, prof_vars%large_vars_size(ii)/megabyte, ' Mbytes ', trim(prof_vars%large_vars(ii))
415 call messages_info(1)
416 end do
417
418 call messages_print_with_emphasis(namespace=namespace)
419
420 if (prof_vars%alloc_count /= prof_vars%dealloc_count) then
421 write(message(1),'(a,i10,a,i10,a)') "Not all memory was deallocated: ", prof_vars%alloc_count, &
422 ' allocations and ', prof_vars%dealloc_count, ' deallocations'
423 call messages_warning(1, all_nodes = .true.)
424 end if
425 if (prof_vars%total_memory > 0) then
426 write(message(1),'(a,f18.3,a,f18.3,a)') "Remaining allocated memory: ", prof_vars%total_memory/megabyte, &
427 ' Mbytes (out of maximum ', prof_vars%max_memory/megabyte, ' Mbytes)'
428 call messages_warning(1, all_nodes = .true.)
429 end if
430 end if
431
432 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
433 call io_close(prof_vars%mem_iunit)
434 end if
435
436 if (bitand(prof_vars%mode, profiling_likwid) /= 0) then
437#ifdef HAVE_LIKWID
438 call likwid_markerclose()
439#endif
440 end if
441
442 if (bitand(prof_vars%mode, profiling_io) /= 0) then
443 call messages_print_with_emphasis(msg="IO profiling information", namespace=namespace)
446 write(message(1), '(a,i10)') 'Number of file open = ', io_open_count
447 write(message(2), '(a,i10)') 'Number of file close = ', io_close_count
448 call mpi_world%allreduce(io_open_count, io_open_count_red, 1, mpi_integer8, mpi_sum)
449 call mpi_world%allreduce(io_close_count, io_close_count_red, 1, mpi_integer8, mpi_sum)
450 write(message(3), '(a,i10)') 'Global number of file open = ', io_open_count_red
451 write(message(4), '(a,i10)') 'Global number of file close = ', io_close_count_red
452 call messages_info(4)
453 call messages_print_with_emphasis(namespace=namespace)
454 end if
455
456 pop_sub(profiling_end)
457 end subroutine profiling_end
459
460 ! ---------------------------------------------------------
462 subroutine profile_init(this, label)
463 type(profile_t), target, intent(out) :: this
464 character(*), intent(in) :: label
465
466 integer :: iprofile
467
468 push_sub(profile_init)
469
470 if(len_trim(label) > label_length) then
471 message(1) = "Label " // trim(label) // " is too long for the internal profiler"
472 call messages_fatal(1)
473 end if
474
475 this%label = label
476 this%total_time = m_zero
477 this%min_time = m_huge
478 this%self_time = m_zero
479 this%entry_time = huge(this%entry_time)
480 this%count = 0
481 this%op_count_current = m_zero
482 this%op_count = m_zero
483 this%op_count_child = m_zero
484 this%tr_count_current = m_zero
485 this%tr_count = m_zero
486 this%tr_count_child = m_zero
487 this%active = .false.
488 nullify(this%parent)
489 this%has_child = .false.
490 this%timings = m_zero
491 this%index = 0
492 this%likwid = .false.
493
494 if (.not. in_profiling_mode) then
495 pop_sub(profile_init)
496 return
497 end if
498
499 prof_vars%last_profile = prof_vars%last_profile + 1
500
501 assert(prof_vars%last_profile <= max_profiles)
502
503 prof_vars%profile_list(prof_vars%last_profile)%p => this
504 this%index = prof_vars%last_profile
505 this%initialized = .true.
506
507 if (bitand(prof_vars%mode, profiling_likwid) /= 0) then
508 if (allocated(prof_vars%likwid_regions)) then
509 this%likwid = any(prof_vars%likwid_regions == this%label)
510 else
511 this%likwid = .true.
512 end if
513 end if
514
515 ! print out a warning if a name is used more than once
516 do iprofile = 1, prof_vars%last_profile - 1
517 if (prof_vars%profile_list(iprofile)%p%label == this%label) then
518 message(1) = "Label "//label//" used more than once."
519 call messages_fatal(1)
520 exit
521 end if
522 end do
523
524 pop_sub(profile_init)
525 end subroutine profile_init
526
527
528 ! ---------------------------------------------------------
531 subroutine profiling_in(label, exclude)
532 character(*), intent(in) :: label
533 logical, optional, intent(in) :: exclude
535
536 real(real64) :: now
537 class(*), pointer :: profile_p
538 type(profile_t), allocatable :: profile
539 logical :: found
540 character(len=len(label)) :: label_
541
542 if (.not. in_profiling_mode) return
543 if (.not. not_in_openmp()) return
544
545 ! no PUSH_SUB, called too often
546
547 label_ = to_upper(trim(label))
548 profile_p => sphash_lookup(profiling_map, trim(label_), found)
549 if (.not. found) then
550 allocate(profile)
551 call sphash_insert(profiling_map, trim(label_), profile, clone=.true.)
552 deallocate(profile)
553 profile_p => sphash_lookup(profiling_map, trim(label_), found)
554 end if
555 select type(this => profile_p)
556 type is (profile_t)
557 if (.not. this%initialized) then
558 call profile_init(this, label_)
559 end if
560
561 if (this%active) then
562 message(1) = " The region with label "//trim(label)//" is already active."
563 message(2) = " This is likely caused by a missing or incorrect profiling_out call."
564 call messages_fatal(2)
565 end if
566 assert(.not. this%active)
567
568 this%active = .true.
569 now = mpi_get_wtime()
570
571 if (associated(prof_vars%current%p)) then
572 !keep a pointer to the parent
573 this%parent => prof_vars%current%p
574 this%parent%has_child(this%index) = .true.
575 else
576 !we are orphans
577 nullify(this%parent)
578 end if
579
580 this%op_count_current = m_zero
581 this%tr_count_current = m_zero
582 this%op_count_child_current = m_zero
583 this%tr_count_child_current = m_zero
584
585 prof_vars%current%p => this
586 this%entry_time = now
587
588 this%exclude = optional_default(exclude, .false.)
589
590#if defined(HAVE_NVTX) || (defined(HAVE_HIP) && defined(__HIP_PLATFORM_AMD__))
591 call nvtx_range_push(string_f_to_c(trim(label_)), this%index)
592#endif
593
594#ifdef HAVE_LIKWID
595 if (this%likwid) call likwid_markerstartregion(trim(label_))
596#endif
597 end select
598
599 end subroutine profiling_in
600
601
602 ! ---------------------------------------------------------
606 subroutine profiling_out(label)
607 character(*), intent(in) :: label
608
609 real(real64) :: now, time_spent
610 class(*), pointer :: profile_p
611 logical :: found
612
613 if (.not. in_profiling_mode) return
614 if (.not. not_in_openmp()) return
615
616 ! no PUSH_SUB, called too often
617 profile_p => sphash_lookup(profiling_map, to_upper(trim(label)), found)
618
619 if (.not. found) then
620 message(1) = " No profiling region with label "//trim(label)//" found."
621 message(2) = " This is likely caused by a missing or incorrect profiling_in call."
622 call messages_fatal(2)
623 end if
624 assert(found)
625
626 select type(this => profile_p)
627 type is (profile_t)
628 assert(this%initialized)
629 assert(this%active)
630 this%active = .false.
631 now = mpi_get_wtime()
632
633 time_spent = now - this%entry_time
634 this%total_time = this%total_time + time_spent
635 this%self_time = this%self_time + time_spent
636 this%count = this%count + 1
637 if (time_spent < this%min_time) then
638 this%min_time = time_spent
639 end if
640
641 this%op_count = this%op_count + this%op_count_current
642 this%tr_count = this%tr_count + this%tr_count_current
643 this%op_count_child = this%op_count_child + this%op_count_child_current
644 this%tr_count_child = this%tr_count_child + this%tr_count_child_current
645
646 if (associated(this%parent)) then
647 !remove the spent from the self time of our parent
648 this%parent%self_time = this%parent%self_time - time_spent
649 if (this%exclude) this%parent%total_time = this%parent%total_time - time_spent
650
651 ! add the operations to the parent
652 this%parent%op_count_child_current = this%parent%op_count_child_current &
653 + this%op_count_current + this%op_count_child_current
654 this%parent%tr_count_child_current = this%parent%tr_count_child_current &
655 + this%tr_count_current + this%tr_count_child_current
656
657 this%parent%timings(this%index) = this%parent%timings(this%index) + time_spent
658
659 !and set parent as current
660 prof_vars%current%p => this%parent
661
662 else
663 nullify(prof_vars%current%p)
664 end if
665
666#ifdef HAVE_LIKWID
667 if (this%likwid) call likwid_markerstopregion(trim(this%label))
668#endif
669 end select
670
671#if defined(HAVE_NVTX) || (defined(HAVE_HIP) && defined(__HIP_PLATFORM_AMD__))
672 call nvtx_range_pop()
673#endif
674
675 end subroutine profiling_out
676
677
678 ! ---------------------------------------------------------
679
680 subroutine iprofiling_count_operations(ops)
681 integer, intent(in) :: ops
682
683 if (.not. in_profiling_mode) return
684 ! no PUSH_SUB, called too often
685
686 prof_vars%current%p%op_count_current = prof_vars%current%p%op_count_current + real(ops, real64)
687 end subroutine iprofiling_count_operations
688
689
690 ! ---------------------------------------------------------
691
693 real(4), intent(in) :: ops
694
695 if (.not. in_profiling_mode) return
696 ! no PUSH_SUB, called too often
697
698 prof_vars%current%p%op_count_current = prof_vars%current%p%op_count_current + real(ops, real64)
699 end subroutine rprofiling_count_operations
700
701
702 ! ---------------------------------------------------------
703
704 subroutine dprofiling_count_operations(ops)
705 real(real64), intent(in) :: ops
706
707 if (.not. in_profiling_mode) return
708 ! no PUSH_SUB, called too often
709
710 prof_vars%current%p%op_count_current = prof_vars%current%p%op_count_current + ops
711
712 end subroutine dprofiling_count_operations
713
714
715 ! ---------------------------------------------------------
716
717 subroutine profiling_count_tran_int_l(trf, type)
718 integer(int64), intent(in) :: trf
719 integer, intent(in) :: type
720
721 if (.not. in_profiling_mode) return
722 ! no PUSH_SUB, called too often
723
724 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 4*real(trf, real64)
725 end subroutine profiling_count_tran_int_l
726
727
728 ! ---------------------------------------------------------
729
730 subroutine profiling_count_tran_int_8_l(trf, type)
731 integer(int64), intent(in) :: trf
732 integer(int64), intent(in) :: type
733
734 if (.not. in_profiling_mode) return
735 ! no PUSH_SUB, called too often
736
737 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
738 end subroutine profiling_count_tran_int_8_l
739
740
741 ! ---------------------------------------------------------
742
743 subroutine profiling_count_tran_real_4_l(trf, type)
744 integer(int64), intent(in) :: trf
745 real(4), intent(in) :: type
746
747 if (.not. in_profiling_mode) return
748 ! no PUSH_SUB, called too often
749
750 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 4*real(trf, real64)
751
752 end subroutine profiling_count_tran_real_4_l
753
754
755 ! ---------------------------------------------------------
756
757 subroutine profiling_count_tran_real_8_l(trf, type)
758 integer(int64), intent(in) :: trf
759 real(real64), intent(in) :: type
760
761 if (.not. in_profiling_mode) return
762 ! no PUSH_SUB, called too often
763
764 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
765
767
768
769 ! ---------------------------------------------------------
770
771 subroutine profiling_count_tran_complex_4_l(trf, type)
772 integer(int64), intent(in) :: trf
773 complex(4), intent(in) :: type
774
775 if (.not. in_profiling_mode) return
776 ! no PUSH_SUB, called too often
777
778 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
779
781
782
783 ! ---------------------------------------------------------
784
785 subroutine profiling_count_tran_complex_8_l(trf, type)
786 integer(int64), intent(in) :: trf
787 complex(real64), intent(in) :: type
788
789 if (.not. in_profiling_mode) return
790 ! no PUSH_SUB, called too often
791
792 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 16*real(trf, real64)
793
795
796
797 ! ---------------------------------------------------------
798
799 subroutine profiling_count_tran_type_l(trf, type)
800 integer(int64), intent(in) :: trf
801 type(type_t), intent(in) :: type
802
803 if (.not. in_profiling_mode) return
804 ! no PUSH_SUB, called too often
805
806 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + real(trf, real64) *types_get_size(type)
807
808 end subroutine profiling_count_tran_type_l
809
810
811 ! ---------------------------------------------------------
812
813 subroutine profiling_count_tran_int(trf, type)
814 integer, intent(in) :: trf
815 integer, intent(in) :: type
817 if (.not. in_profiling_mode) return
818 ! no PUSH_SUB, called too often
819
820 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 4*real(trf, real64)
821 end subroutine profiling_count_tran_int
822
823
824 ! ---------------------------------------------------------
825
826 subroutine profiling_count_tran_int_8(trf, type)
827 integer, intent(in) :: trf
828 integer(int64), intent(in) :: type
830 if (.not. in_profiling_mode) return
831 ! no PUSH_SUB, called too often
832
833 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
834 end subroutine profiling_count_tran_int_8
835
836
837 ! ---------------------------------------------------------
838
839 subroutine profiling_count_tran_real_4(trf, type)
840 integer, intent(in) :: trf
841 real(4), intent(in) :: type
842
843 if (.not. in_profiling_mode) return
844 ! no PUSH_SUB, called too often
845
846 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 4*real(trf, real64)
847
848 end subroutine profiling_count_tran_real_4
849
850
851 ! ---------------------------------------------------------
852
853 subroutine profiling_count_tran_real_8(trf, type)
854 integer, intent(in) :: trf
855 real(real64), intent(in) :: type
856
857 if (.not. in_profiling_mode) return
858 ! no PUSH_SUB, called too often
859
860 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
861
862 end subroutine profiling_count_tran_real_8
863
864
865 ! ---------------------------------------------------------
866
867 subroutine profiling_count_tran_complex_4(trf, type)
868 integer, intent(in) :: trf
869 complex(4), intent(in) :: type
870
871 if (.not. in_profiling_mode) return
872 ! no PUSH_SUB, called too often
873
874 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 8*real(trf, real64)
875
876 end subroutine profiling_count_tran_complex_4
877
878
879 ! ---------------------------------------------------------
880
881 subroutine profiling_count_tran_complex_8(trf, type)
882 integer, intent(in) :: trf
883 complex(real64), intent(in) :: type
884
885 if (.not. in_profiling_mode) return
886 ! no PUSH_SUB, called too often
887
888 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + 16*real(trf, real64)
889
890 end subroutine profiling_count_tran_complex_8
891
892
893 ! ---------------------------------------------------------
894
895 subroutine profiling_count_tran_type(trf, type)
896 integer, intent(in) :: trf
897 type(type_t), intent(in) :: type
898
899 if (.not. in_profiling_mode) return
900 ! no PUSH_SUB, called too often
901
902 prof_vars%current%p%tr_count_current = prof_vars%current%p%tr_count_current + real(trf, real64) *types_get_size(type)
903
904 end subroutine profiling_count_tran_type
905
906 ! ---------------------------------------------------------
907 real(real64) function profile_total_time(this)
908 type(profile_t), intent(in) :: this
909
910 push_sub(profile_total_time)
911 profile_total_time = this%total_time
913 pop_sub(profile_total_time)
914 end function profile_total_time
915
916
917 ! ---------------------------------------------------------
918 real(real64) function profile_self_time(this)
919 type(profile_t), intent(in) :: this
920
921 push_sub(profile_self_time)
922 profile_self_time = this%self_time
923
924 pop_sub(profile_self_time)
925 end function profile_self_time
926
927
928 ! ---------------------------------------------------------
929 real(real64) function profile_total_time_per_call(this)
930 type(profile_t), intent(in) :: this
931
933 profile_total_time_per_call = this%total_time / real(this%count, real64)
934
936 end function profile_total_time_per_call
937
938
939 ! ---------------------------------------------------------
940 real(real64) function profile_min_time(this)
941 type(profile_t), intent(in) :: this
942
943 push_sub(profile_min_time)
944 profile_min_time = this%min_time
945
946 pop_sub(profile_min_time)
947 end function profile_min_time
948
949
950 ! ---------------------------------------------------------
951 real(real64) function profile_self_time_per_call(this)
952 type(profile_t), intent(in) :: this
955 profile_self_time_per_call = this%self_time / real(this%count, real64)
956
958 end function profile_self_time_per_call
959
960
961 ! ---------------------------------------------------------
962 real(real64) function profile_total_throughput(this)
963 type(profile_t), intent(in) :: this
964
965 push_sub(profile_throughput)
966
967 if (this%total_time > epsilon(this%total_time)) then
968 profile_total_throughput = (this%op_count + this%op_count_child)/this%total_time*1.0e-6_real64
969 else
970 profile_total_throughput = 0.0_real64
971 end if
972
973 pop_sub(profile_throughput)
974 end function profile_total_throughput
975
976
977 ! ---------------------------------------------------------
978
979 real(real64) function profile_total_bandwidth(this)
980 type(profile_t), intent(in) :: this
982 push_sub(profile_bandwidth)
983
984 if (this%total_time > epsilon(this%total_time)) then
985 profile_total_bandwidth = (this%tr_count + this%tr_count_child)/(this%total_time*1024.0_real64**2)
986 else
987 profile_total_bandwidth = 0.0_real64
988 end if
989
990 pop_sub(profile_bandwidth)
991 end function profile_total_bandwidth
992
993 ! ---------------------------------------------------------
994
995 real(real64) function profile_self_throughput(this)
996 type(profile_t), intent(in) :: this
997
998 push_sub(profile_throughput)
999
1000 if (this%self_time > epsilon(this%self_time)) then
1001 profile_self_throughput = this%op_count/this%self_time*1.0e-6_real64
1002 else
1003 profile_self_throughput = 0.0_real64
1004 end if
1005
1006 pop_sub(profile_throughput)
1007 end function profile_self_throughput
1008
1009 ! ---------------------------------------------------------
1010
1011 real(real64) function profile_self_bandwidth(this)
1012 type(profile_t), intent(in) :: this
1013
1014 push_sub(profile_bandwidth)
1016 if (this%self_time > epsilon(this%self_time)) then
1017 profile_self_bandwidth = this%tr_count/(this%self_time*1024.0_real64**2)
1018 else
1019 profile_self_bandwidth = 0.0_real64
1020 end if
1021
1022 pop_sub(profile_bandwidth)
1023 end function profile_self_bandwidth
1024
1025
1026 ! ---------------------------------------------------------
1027 integer function profile_num_calls(this)
1028 type(profile_t), intent(in) :: this
1029
1030 push_sub(profile_num_calls)
1031 profile_num_calls = this%count
1032
1033 pop_sub(profile_num_calls)
1034 end function profile_num_calls
1035
1036
1037 ! ---------------------------------------------------------
1038 character(LABEL_LENGTH) function profile_label(this)
1039 type(profile_t), intent(in) :: this
1040
1041 push_sub(profile_label)
1042 profile_label = this%label
1043
1044 pop_sub(profile_label)
1045 end function profile_label
1046
1047
1048 ! ---------------------------------------------------------
1055 subroutine profiling_output(namespace)
1056 type(namespace_t), intent(in) :: namespace
1057
1058 integer :: ii
1059 integer :: iunit
1060 real(real64) :: total_time
1061 type(profile_t), pointer :: prof
1062 character(len=256) :: filename
1063 real(real64), allocatable :: selftime(:)
1064 integer, allocatable :: position(:)
1065 class(*), pointer :: profile_p
1066 logical :: found
1067
1068 if (.not. in_profiling_mode) return
1069 push_sub(profiling_output)
1070
1071 call mpi_world%barrier()
1072
1073 if (.not. prof_vars%all_nodes .and. .not. mpi_world%is_root()) then
1074 pop_sub(profiling_output)
1075 return
1076 end if
1077
1078 filename = trim(prof_vars%output_dir)//'/time.'//prof_vars%file_number
1079 iunit = io_open(trim(filename), namespace, action='write', die=.false.)
1080 if (iunit == -1) then
1081 message(1) = 'Failed to open file ' // trim(filename) // ' to write profiling results.'
1082 call messages_warning(1)
1083 pop_sub(profiling_output)
1084 return
1085 end if
1086
1087 write(iunit, '(2a)') &
1088 ' CUMULATIVE TIME ', &
1089 ' | SELF TIME'
1090 write(iunit, '(2a)') &
1091 ' ----------------------------------------------------------', &
1092 '----------------|-------------------------------------------------------------'
1093 write(iunit, '(2a)') &
1094 'TAG NUM_CALLS TOTAL_TIME TIME_PER_CALL MIN_TIME ', &
1095 ' MFLOPS MBYTES/S %TIME | TOTAL_TIME TIME_PER_CALL MFLOPS MBYTES/S %TIME'
1096 write(iunit, '(2a)') &
1097 '===================================================================================================', &
1098 '=================|============================================================='
1099
1100 profile_p => sphash_lookup(profiling_map, "COMPLETE_RUN", found)
1101 assert(found)
1102 select type(complete_run => profile_p)
1103 type is (profile_t)
1104 total_time = profile_total_time(complete_run)
1105 end select
1106
1107 safe_allocate(selftime(1:prof_vars%last_profile))
1108 safe_allocate(position(1:prof_vars%last_profile))
1109
1110 do ii = 1, prof_vars%last_profile
1111 selftime(ii) = -profile_self_time(prof_vars%profile_list(ii)%p)
1112 position(ii) = ii
1113 end do
1114
1115 call sort(selftime, position)
1116
1117 do ii = 1, prof_vars%last_profile
1118 prof => prof_vars%profile_list(position(ii))%p
1119 if (.not. prof%initialized) then
1120 write(message(1),'(a,i6,a)') "Internal error: Profile number ", position(ii), " is not initialized."
1121 call messages_fatal(1)
1122 end if
1123 if (prof%active) then
1124 write(message(1),'(a)') "Internal error: Profile '" // trim(profile_label(prof)) // &
1125 "' is active, i.e. profiling_out was not called."
1126 call messages_warning(1)
1127 end if
1128
1129 if (profile_num_calls(prof) == 0) cycle
1130
1131 write(iunit, '(a,i14,3f16.6,2f10.1,f8.1,a,2f16.6,2f10.1,f8.1)') &
1132 profile_label(prof), &
1133 profile_num_calls(prof), &
1134 profile_total_time(prof), &
1136 profile_min_time(prof), &
1139 profile_total_time(prof)/total_time*100.0_real64, &
1140 ' | ', &
1144 profile_self_bandwidth(prof), &
1145 profile_self_time(prof)/total_time*100.0_real64
1146 end do
1147
1148 call io_close(iunit)
1149
1150 if (prof_vars%output_yaml) then
1151 filename = trim(prof_vars%output_dir)//'/time.'//prof_vars%file_number//'.yaml'
1152 iunit = io_open(trim(filename), namespace, action='write', die=.false.)
1153 if (iunit == -1) then
1154 message(1) = 'Failed to open file ' // trim(filename) // ' to write profiling results.'
1155 call messages_warning(1)
1156 pop_sub(profiling_output)
1157 return
1158 end if
1159 write(iunit, '(2a)') 'schema: [num_calls, total_time, total_throughput, ', &
1160 'total_bandwidth, self_time, self_throughput, self_bandwidth]'
1161 write(iunit, '(a)') 'data:'
1162
1163 do ii = 1, prof_vars%last_profile
1164 prof => prof_vars%profile_list(position(ii))%p
1165 if (profile_num_calls(prof) == 0) cycle
1166 write(iunit, '(a,a,a,i6,a,e10.3,a,e10.3,a,e10.3,a,e10.3,a,e10.3,a,e10.3,a)') &
1167 ' ', profile_label(prof), ': [', &
1168 profile_num_calls(prof), ', ', &
1169 profile_total_time(prof), ', ', &
1170 profile_total_throughput(prof), ', ', &
1171 profile_total_bandwidth(prof), ', ', &
1172 profile_self_time(prof), ', ', &
1173 profile_self_throughput(prof), ', ', &
1174 profile_self_bandwidth(prof), ']'
1175 end do
1176
1177 call io_close(iunit)
1178 end if
1179
1180 safe_deallocate_a(selftime)
1181 safe_deallocate_a(position)
1182
1183 if (prof_vars%output_tree) then
1184 filename = trim(prof_vars%output_dir)//'/time.'//prof_vars%file_number//'.tree'
1185 iunit = io_open(trim(filename), namespace, action='write', die=.false.)
1186 if (iunit == -1) then
1187 message(1) = 'Failed to open file ' // trim(filename) // ' to write profiling results.'
1188 call messages_warning(1)
1189 pop_sub(profiling_output)
1190 return
1191 end if
1192 write(iunit, '(a40,a11,a11,a12)') &
1193 "Tree level, region ", &
1194 "% of total ", "% of parent", &
1195 " Full time"
1196
1197 select type(complete_run => profile_p)
1198 type is (profile_t)
1199 ! output of top-level node
1200 write(iunit, '(a,a25,a,f8.2,a,f8.2,a,f12.4)') &
1201 repeat('-', 0) // '| ', &
1202 profile_label(complete_run), &
1203 repeat(' ', 15-0-2), &
1204 100.0, "% ", &
1205 100.0, "% ", &
1206 total_time
1207 call output_tree_level(complete_run, 1, total_time, iunit)
1208 end select
1209 write(iunit, '(a)') "// modeline for vim to enable folding (put in ~/.vimrc: set modeline modelineexpr)"
1210 write(iunit, '(a)') "// vim: fdm=expr fde=getline(v\:lnum)=~'.*\|.*'?len(split(getline(v\:lnum))[0])-1\:0"
1211 call io_close(iunit)
1212 end if
1213
1214 pop_sub(profiling_output)
1215 contains
1216 ! Traverse the tree depth-first, pre-order
1217 recursive subroutine output_tree_level(profile, level, total_time, iunit)
1218 type(profile_t), intent(in) :: profile
1219 integer, intent(in) :: level
1220 real(real64), intent(in) :: total_time
1221 integer, intent(in) :: iunit
1222
1223 integer :: ichild, width
1224
1226 width = 15
1227 ! loop over children
1228 do ichild = 1, max_profiles
1229 if (profile%has_child(ichild)) then
1230 ! print out information on current child with the first marker
1231 ! placed according to the level of the tree
1232 write(iunit, '(a,a25,a,f8.2,a,f8.2,a,f12.4)') &
1233 repeat('-', level) // '| ', &
1234 profile_label(prof_vars%profile_list(ichild)%p), &
1235 repeat(' ', width-level-2), &
1236 profile%timings(ichild)/total_time * 100, "% ", &
1237 profile%timings(ichild)/profile%total_time * 100, "% ", &
1238 profile%timings(ichild)
1239 call output_tree_level(prof_vars%profile_list(ichild)%p, &
1240 level+1, total_time, iunit)
1241 end if
1242 end do
1244 end subroutine output_tree_level
1245 end subroutine profiling_output
1246
1247
1248 ! ---------------------------------------------------------
1249 subroutine profiling_make_position_str(var, file, line, str)
1250 character(len=*), intent(in) :: var
1251 character(len=*), intent(in) :: file
1252 integer, intent(in) :: line
1253 character(len=*), intent(out) :: str
1254
1255 integer :: ii, jj, nn
1256
1257 ! no push_sub, called too many times
1258
1259 jj = len(var)
1260 if (var(jj:jj) == ')') then
1261 nn = 1
1262 do ii = len(var)-1, 1, -1
1263 jj = ii - 1
1264 if (var(ii:ii) == ')') nn = nn + 1
1265 if (var(ii:ii) == '(') nn = nn - 1
1266 if (nn == 0) exit
1267 end do
1268 if (jj == 0) then
1269 message(1) = "Internal Error in profiling_memory_log"
1270 call messages_fatal(1)
1271 end if
1272 end if
1273 ii = index(file, '/', back=.true.)+1
1274
1275 write(str, '(4a,i5,a)') var(1:jj), "(", trim(file(ii:len(file))), ":", line, ")"
1276 call compact(str)
1277
1278 end subroutine profiling_make_position_str
1279
1280
1281 ! ---------------------------------------------------------
1282 subroutine profiling_memory_log(type, var, file, line, size)
1283 character(len=*), intent(in) :: type
1284 character(len=*), intent(in) :: var
1285 character(len=*), intent(in) :: file
1286 integer, intent(in) :: line
1287 integer(int64), intent(in) :: size
1288
1289 character(len=256) :: str
1290 integer(int64) :: mem
1291
1292 ! no push_sub, called too many times
1293
1294 call profiling_make_position_str(var, file, line, str)
1295
1296 ! get number of pages
1297 mem = loct_get_memory_usage()
1298
1299 write(prof_vars%mem_iunit, '(f16.6,a16,3i16,a70)') loct_clock() - prof_vars%start_time, &
1300 trim(type), size, prof_vars%total_memory, mem, trim(str)
1301
1302 end subroutine profiling_memory_log
1304
1305 !-----------------------------------------------------
1306 subroutine profiling_memory_allocate(var, file, line, size_)
1307 character(len=*), intent(in) :: var
1308 character(len=*), intent(in) :: file
1309 integer, intent(in) :: line
1310 integer(int64), intent(in) :: size_
1311
1312 integer :: ii, jj
1313 integer(int64) :: size
1314 character(len=256) :: str
1315
1316 ! no push_sub, called too many times
1317
1318 size = size_ ! make a copy that we can change
1319
1320 prof_vars%alloc_count = prof_vars%alloc_count + 1
1321 prof_vars%total_memory = prof_vars%total_memory + size
1322
1323 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
1324 call profiling_memory_log('A ', var, file, line, size)
1325 end if
1326
1327 if (prof_vars%memory_limit > 0) then
1328 if (prof_vars%total_memory > prof_vars%memory_limit) then
1329 message(1) = "Memory limit set in the input file was passed"
1330 call messages_fatal(1)
1331 end if
1332 end if
1333
1334 if (prof_vars%total_memory > prof_vars%max_memory) then
1335 prof_vars%max_memory = prof_vars%total_memory
1336 call profiling_make_position_str(var, file, line, prof_vars%max_memory_location)
1337 end if
1338
1339 call profiling_make_position_str(var, file, line, str)
1340
1341 ! check if variable is already in stack
1342 do ii = 1, max_memory_vars
1343 if (str == prof_vars%large_vars(ii)) then
1344 if (size > prof_vars%large_vars_size(ii)) then
1345 ! delete variable by moving stack up
1346 do jj = ii, max_memory_vars - 1
1347 prof_vars%large_vars(jj) = prof_vars%large_vars(jj + 1)
1348 prof_vars%large_vars_size(jj) = prof_vars%large_vars_size(jj + 1)
1349 end do
1350 prof_vars%large_vars(max_memory_vars) = ""
1351 prof_vars%large_vars_size(max_memory_vars) = 0
1352 else
1353 ! do not consider this variable any longer
1354 size = -1
1355 end if
1356 exit
1357 end if
1358 end do
1359
1360 do ii = 1, max_memory_vars
1361 if (size > prof_vars%large_vars_size(ii)) then
1362 ! move the stack one position down
1363 do jj = max_memory_vars, ii + 1, -1
1364 prof_vars%large_vars(jj) = prof_vars%large_vars(jj - 1)
1365 prof_vars%large_vars_size(jj) = prof_vars%large_vars_size(jj - 1)
1366 end do
1367 prof_vars%large_vars_size(ii) = size
1368 prof_vars%large_vars(ii) = str
1369 exit
1370 end if
1371 end do
1372
1373 end subroutine profiling_memory_allocate
1374
1375
1376 !-----------------------------------------------------
1377 subroutine profiling_memory_deallocate(var, file, line, size)
1378 character(len=*), intent(in) :: var
1379 character(len=*), intent(in) :: file
1380 integer, intent(in) :: line
1381 integer(int64), intent(in) :: size
1382
1383 ! no push_sub, called too many times
1384
1385 prof_vars%dealloc_count = prof_vars%dealloc_count + 1
1386 prof_vars%total_memory = prof_vars%total_memory - size
1387
1388 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
1389 call profiling_memory_log('D ', var, file, line, -size)
1390 end if
1391
1393
1394
1395 ! string handling functions from Fortran stdlib, licensed under MIT,
1396 ! available at https://github.com/fortran-lang/stdlib
1397 ! Returns the corresponding uppercase letter, if `c_in` is a lowercase
1398 ! ASCII character, otherwise `c` itself.
1399 pure function char_to_upper(c_in) result(c_out)
1400 character(len=1), intent(in) :: c_in
1401 character(len=1) :: c_out
1402
1403 integer, parameter :: difference=iachar('a')-iachar('A'), la=iachar('a'), lz=iachar('z')
1404 integer :: ascii_decimal
1405
1406 ! no push_sub/pop_sub, called too often
1407 ascii_decimal = iachar(c_in)
1408 if (ascii_decimal >= la .and. ascii_decimal <= lz) then
1409 ascii_decimal = ascii_decimal - difference
1410 end if
1411 c_out = achar(ascii_decimal)
1412 end function char_to_upper
1413
1414 ! Convert string to upper case
1415 pure function to_upper(string) result(upper_string)
1416 character(len=*), intent(in) :: string
1417 character(len=len(string)) :: upper_string
1418
1419 integer :: i
1420
1421 ! no push_sub/pop_sub, called too often
1422 do i = 1, len(string)
1423 upper_string(i:i) = char_to_upper(string(i:i))
1424 end do
1425 end function to_upper
1426end module profiling_oct_m
1427
1428!! Local Variables:
1429!! mode: f90
1430!! coding: utf-8
1431!! End:
real(real64), parameter, public m_huge
Definition: global.F90:216
real(real64), parameter, public m_zero
Definition: global.F90:198
logical pure function, public not_in_openmp()
Definition: global.F90:565
logical, public in_profiling_mode
Same for profiling mode.
Definition: global.F90:268
Definition: io.F90:114
integer(int64), save io_open_count
Definition: io.F90:153
subroutine, public io_close(iunit, grp)
Definition: io.F90:465
integer(int64) pure function, public io_get_close_count()
Definition: io.F90:681
integer(int64), save io_close_count
Definition: io.F90:154
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:359
integer(int64) pure function, public io_get_open_count()
Definition: io.F90:674
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:400
System information (time, memory, sysname)
Definition: loct.F90:115
character(kind=c_char, len=1) function, dimension(len_trim(f_string)+1), private string_f_to_c(f_string)
convert a Fortran string to a C string
Definition: loct.F90:238
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:896
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:523
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:408
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:689
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:592
real(real64) function, public mpi_get_wtime()
. Returns an elapsed time on the calling processor.
Definition: mpi.F90:649
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:338
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:816
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:621
/* To use the profiling module, call profiling_in and profiling_out with the label of the region as a...
Definition: profiling.F90:143
subroutine profiling_count_tran_int(trf, type)
Definition: profiling.F90:900
subroutine profiling_count_tran_int_8_l(trf, type)
Definition: profiling.F90:817
subroutine, public profiling_end(namespace)
Definition: profiling.F90:476
type(profile_vars_t), target, save, public prof_vars
Definition: profiling.F90:276
real(real64) function profile_self_bandwidth(this)
Definition: profiling.F90:1098
real(real64) function profile_self_time(this)
Definition: profiling.F90:1005
pure character(len=1) function char_to_upper(c_in)
Definition: profiling.F90:1486
integer, parameter max_memory_vars
Definition: profiling.F90:241
subroutine iprofiling_count_operations(ops)
Definition: profiling.F90:767
integer, parameter, public profiling_memory
Definition: profiling.F90:234
subroutine profiling_memory_log(type, var, file, line, size)
Definition: profiling.F90:1369
integer, parameter, public profiling_likwid
Definition: profiling.F90:234
subroutine profiling_output(namespace)
Write profiling results of each node to profiling.NNN/profiling.nnn The format of each line is tag-la...
Definition: profiling.F90:1142
integer, parameter, public profiling_memory_full
Definition: profiling.F90:234
subroutine profiling_count_tran_real_8(trf, type)
Definition: profiling.F90:940
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:693
subroutine profiling_count_tran_real_8_l(trf, type)
Definition: profiling.F90:844
subroutine profiling_count_tran_int_8(trf, type)
Definition: profiling.F90:913
subroutine rprofiling_count_operations(ops)
Definition: profiling.F90:779
integer, parameter, public profiling_io
Definition: profiling.F90:234
real(real64) function profile_self_throughput(this)
Definition: profiling.F90:1082
subroutine profiling_count_tran_complex_8_l(trf, type)
Definition: profiling.F90:872
subroutine profile_init(this, label)
Initialize a profile object and add it to the list.
Definition: profiling.F90:556
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:625
real(real64) function profile_total_throughput(this)
Definition: profiling.F90:1049
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:285
subroutine profiling_count_tran_real_4_l(trf, type)
Definition: profiling.F90:830
subroutine dprofiling_count_operations(ops)
Definition: profiling.F90:791
pure character(len=len(string)) function to_upper(string)
Definition: profiling.F90:1502
real(real64) function profile_total_time_per_call(this)
Definition: profiling.F90:1016
integer, parameter max_profiles
Max. number of tags.
Definition: profiling.F90:174
subroutine profiling_count_tran_int_l(trf, type)
Definition: profiling.F90:804
subroutine profiling_count_tran_complex_4_l(trf, type)
Definition: profiling.F90:858
subroutine profiling_count_tran_real_4(trf, type)
Definition: profiling.F90:926
type(sphash_t), save profiling_map
Definition: profiling.F90:278
integer function profile_num_calls(this)
Definition: profiling.F90:1114
subroutine profiling_count_tran_type(trf, type)
Definition: profiling.F90:982
real(real64) function profile_min_time(this)
Definition: profiling.F90:1027
subroutine, public profiling_memory_deallocate(var, file, line, size)
Definition: profiling.F90:1464
character(label_length) function profile_label(this)
Definition: profiling.F90:1125
real(real64) function profile_self_time_per_call(this)
Definition: profiling.F90:1038
subroutine, public profiling_memory_allocate(var, file, line, size_)
Definition: profiling.F90:1393
subroutine profiling_count_tran_type_l(trf, type)
Definition: profiling.F90:886
subroutine profiling_make_position_str(var, file, line, str)
Definition: profiling.F90:1336
subroutine profiling_count_tran_complex_8(trf, type)
Definition: profiling.F90:968
subroutine profiling_count_tran_complex_4(trf, type)
Definition: profiling.F90:954
real(real64) function profile_total_bandwidth(this)
Definition: profiling.F90:1066
real(real64) function profile_total_time(this)
Definition: profiling.F90:994
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:117
This module implements a simple hash table for string valued keys and integer values using the C++ ST...
Definition: sphash.F90:118
subroutine, public sphash_init(h)
Initialize a hash table h with size entries. Since we use separate chaining, the number of entries in...
Definition: sphash.F90:221
subroutine, public sphash_insert(h, key, val, clone)
Insert a (key, val) pair into the hash table h. If clone=.true., the object will be copied.
Definition: sphash.F90:291
subroutine, public sphash_end(h)
Free a hash table.
Definition: sphash.F90:247
class(*) function, pointer, public sphash_lookup(h, key, found)
Look up a value in the hash table h. If found is present, it indicates if key could be found in the t...
Definition: sphash.F90:323
integer pure function, public types_get_size(this)
Definition: types.F90:155
subroutine get_output_dir()
Definition: profiling.F90:459
recursive subroutine output_tree_level(profile, level, total_time, iunit)
Definition: profiling.F90:1304
int true(void)