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