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
149 type profile_vars_t
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
175
176 logical :: output_yaml
177 logical :: output_tree
179
180 type(profile_vars_t), target, save, public :: prof_vars
182 type(sphash_t), save :: profiling_map
183
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
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
230 in_profiling_mode = (prof_vars%mode > 0)
231 if (.not. in_profiling_mode) then
233 return
234 end if
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
245
246 call parse_variable(namespace, 'ProfilingAllNodes', .false., prof_vars%all_nodes)
247
249
250 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
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
320 call sphash_init(profiling_map)
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_grp_is_root(mpi_world)) 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
363 call sphash_end(profiling_map)
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
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#ifdef HAVE_NVTX
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
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#ifdef HAVE_NVTX
618 call nvtx_range_pop()
619#endif
620
621 end subroutine profiling_out
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
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
706
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 ! ---------------------------------------------------------
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
731 subroutine profiling_count_tran_complex_8_l(trf, type)
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
743 ! ---------------------------------------------------------
744
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
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
770 ! ---------------------------------------------------------
771
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
839 ! ---------------------------------------------------------
840
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
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
867 push_sub(profile_self_time)
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
895
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
921
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
943
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
954
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
965 profile_self_bandwidth = 0.0_real64
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
976 push_sub(profile_num_calls)
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
993
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_grp_is_root(mpi_world)) then
1020 pop_sub(profiling_output)
1021 return
1022 end if
1024 filename = trim(prof_vars%output_dir)//'/time.'//prof_vars%file_number
1025 iunit = io_open(trim(filename), namespace, action='write')
1026 if (iunit < 0) 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
1052
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')
1099 if (iunit < 0) 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')
1132 if (iunit < 0) 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 = 1
1220 do while (file(ii:ii+2) == "../")
1221 ii = ii + 3
1222 end do
1223 write(str, '(4a,i5,a)') var(1:jj), "(", trim(file(ii:len(file))), ":", line, ")"
1224 call compact(str)
1225
1226 end subroutine profiling_make_position_str
1227
1228
1229 ! ---------------------------------------------------------
1230 subroutine profiling_memory_log(type, var, file, line, size)
1231 character(len=*), intent(in) :: type
1232 character(len=*), intent(in) :: var
1233 character(len=*), intent(in) :: file
1234 integer, intent(in) :: line
1235 integer(int64), intent(in) :: size
1236
1237 character(len=256) :: str
1238 integer(int64) :: mem
1239
1240 ! no push_sub, called too many times
1241
1242 call profiling_make_position_str(var, file, line, str)
1243
1244 ! get number of pages
1245 mem = loct_get_memory_usage()
1246
1247 write(prof_vars%mem_iunit, '(f16.6,a16,3i16,a70)') loct_clock() - prof_vars%start_time, &
1248 trim(type), size, prof_vars%total_memory, mem, trim(str)
1249
1250 end subroutine profiling_memory_log
1251
1252
1253 !-----------------------------------------------------
1254 subroutine profiling_memory_allocate(var, file, line, size_)
1255 character(len=*), intent(in) :: var
1256 character(len=*), intent(in) :: file
1257 integer, intent(in) :: line
1258 integer(int64), intent(in) :: size_
1259
1260 integer :: ii, jj
1261 integer(int64) :: size
1262 character(len=256) :: str
1263
1264 ! no push_sub, called too many times
1265
1266 size = size_ ! make a copy that we can change
1267
1268 prof_vars%alloc_count = prof_vars%alloc_count + 1
1269 prof_vars%total_memory = prof_vars%total_memory + size
1270
1271 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
1272 call profiling_memory_log('A ', var, file, line, size)
1273 end if
1274
1275 if (prof_vars%memory_limit > 0) then
1276 if (prof_vars%total_memory > prof_vars%memory_limit) then
1277 message(1) = "Memory limit set in the input file was passed"
1278 call messages_fatal(1)
1279 end if
1280 end if
1281
1282 if (prof_vars%total_memory > prof_vars%max_memory) then
1283 prof_vars%max_memory = prof_vars%total_memory
1284 call profiling_make_position_str(var, file, line, prof_vars%max_memory_location)
1285 end if
1286
1287 call profiling_make_position_str(var, file, line, str)
1288
1289 ! check if variable is already in stack
1290 do ii = 1, max_memory_vars
1291 if (str == prof_vars%large_vars(ii)) then
1292 if (size > prof_vars%large_vars_size(ii)) then
1293 ! delete variable by moving stack up
1294 do jj = ii, max_memory_vars - 1
1295 prof_vars%large_vars(jj) = prof_vars%large_vars(jj + 1)
1296 prof_vars%large_vars_size(jj) = prof_vars%large_vars_size(jj + 1)
1297 end do
1298 prof_vars%large_vars(max_memory_vars) = ""
1299 prof_vars%large_vars_size(max_memory_vars) = 0
1300 else
1301 ! do not consider this variable any longer
1302 size = -1
1303 end if
1304 exit
1305 end if
1306 end do
1307
1308 do ii = 1, max_memory_vars
1309 if (size > prof_vars%large_vars_size(ii)) then
1310 ! move the stack one position down
1311 do jj = max_memory_vars, ii + 1, -1
1312 prof_vars%large_vars(jj) = prof_vars%large_vars(jj - 1)
1313 prof_vars%large_vars_size(jj) = prof_vars%large_vars_size(jj - 1)
1314 end do
1315 prof_vars%large_vars_size(ii) = size
1316 prof_vars%large_vars(ii) = str
1317 exit
1318 end if
1319 end do
1321 end subroutine profiling_memory_allocate
1322
1323
1324 !-----------------------------------------------------
1325 subroutine profiling_memory_deallocate(var, file, line, size)
1326 character(len=*), intent(in) :: var
1327 character(len=*), intent(in) :: file
1328 integer, intent(in) :: line
1329 integer(int64), intent(in) :: size
1330
1331 ! no push_sub, called too many times
1332
1333 prof_vars%dealloc_count = prof_vars%dealloc_count + 1
1334 prof_vars%total_memory = prof_vars%total_memory - size
1335
1336 if (bitand(prof_vars%mode, profiling_memory_full) /= 0) then
1337 call profiling_memory_log('D ', var, file, line, -size)
1338 end if
1339
1340 end subroutine profiling_memory_deallocate
1341
1342
1343 ! string handling functions from fortran stdlib, licensed unter MIT,
1344 ! available at https://github.com/fortran-lang/stdlib
1345 ! Returns the corresponding uppercase letter, if `c_in` is a lowercase
1346 ! ASCII character, otherwise `c` itself.
1347 pure function char_to_upper(c_in) result(c_out)
1348 character(len=1), intent(in) :: c_in
1349 character(len=1) :: c_out
1350
1351 integer, parameter :: difference=iachar('a')-iachar('A'), la=iachar('a'), lz=iachar('z')
1352 integer :: ascii_decimal
1353
1354 ! no push_sub/pop_sub, called too often
1355 ascii_decimal = iachar(c_in)
1356 if (ascii_decimal >= la .and. ascii_decimal <= lz) then
1357 ascii_decimal = ascii_decimal - difference
1358 end if
1359 c_out = achar(ascii_decimal)
1360 end function char_to_upper
1361
1362 ! Convert string to upper case
1363 pure function to_upper(string) result(upper_string)
1364 character(len=*), intent(in) :: string
1365 character(len=len(string)) :: upper_string
1366
1367 integer :: i
1368
1369 ! no push_sub/pop_sub, called too often
1370 do i = 1, len(string)
1371 upper_string(i:i) = char_to_upper(string(i:i))
1372 end do
1373 end function to_upper
1374end module profiling_oct_m
1375
1376!! Local Variables:
1377!! mode: f90
1378!! coding: utf-8
1379!! End:
real(real64), parameter, public m_huge
Definition: global.F90:205
real(real64), parameter, public m_zero
Definition: global.F90:187
logical pure function, public not_in_openmp()
Definition: global.F90:453
logical, public in_profiling_mode
Same for profiling mode.
Definition: global.F90:242
Definition: io.F90:114
integer(int64), save io_open_count
Definition: io.F90:156
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
integer(int64) pure function, public io_get_close_count()
Definition: io.F90:701
integer(int64), save io_close_count
Definition: io.F90:157
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:354
integer(int64) pure function, public io_get_open_count()
Definition: io.F90:694
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:930
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
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:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
real(real64) function, public mpi_get_wtime()
. Returns an elapsed time on the calling processor.
Definition: mpi.F90:646
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
subroutine profiling_count_tran_int(trf, type)
Definition: profiling.F90:826
subroutine profiling_count_tran_int_8_l(trf, type)
Definition: profiling.F90:743
subroutine, public profiling_end(namespace)
Definition: profiling.F90:413
type(profile_vars_t), target, save, public prof_vars
Definition: profiling.F90:246
real(real64) function profile_self_bandwidth(this)
Definition: profiling.F90:1024
real(real64) function profile_self_time(this)
Definition: profiling.F90:931
pure character(len=1) function char_to_upper(c_in)
Definition: profiling.F90:1414
integer, parameter max_memory_vars
Definition: profiling.F90:213
subroutine iprofiling_count_operations(ops)
Definition: profiling.F90:693
integer, parameter, public profiling_memory
Definition: profiling.F90:206
subroutine profiling_memory_log(type, var, file, line, size)
Definition: profiling.F90:1297
integer, parameter, public profiling_likwid
Definition: profiling.F90:206
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:1068
integer, parameter, public profiling_memory_full
Definition: profiling.F90:206
subroutine profiling_count_tran_real_8(trf, type)
Definition: profiling.F90:866
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine profiling_count_tran_real_8_l(trf, type)
Definition: profiling.F90:770
subroutine profiling_count_tran_int_8(trf, type)
Definition: profiling.F90:839
subroutine rprofiling_count_operations(ops)
Definition: profiling.F90:705
integer, parameter, public profiling_io
Definition: profiling.F90:206
real(real64) function profile_self_throughput(this)
Definition: profiling.F90:1008
subroutine profiling_count_tran_complex_8_l(trf, type)
Definition: profiling.F90:798
subroutine profile_init(this, label)
Initialize a profile object and add it to the list.
Definition: profiling.F90:492
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
real(real64) function profile_total_throughput(this)
Definition: profiling.F90:975
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:255
subroutine profiling_count_tran_real_4_l(trf, type)
Definition: profiling.F90:756
subroutine dprofiling_count_operations(ops)
Definition: profiling.F90:717
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:942
integer, parameter max_profiles
Max. number of tags.
Definition: profiling.F90:147
subroutine profiling_count_tran_int_l(trf, type)
Definition: profiling.F90:730
subroutine profiling_count_tran_complex_4_l(trf, type)
Definition: profiling.F90:784
subroutine profiling_count_tran_real_4(trf, type)
Definition: profiling.F90:852
type(sphash_t), save profiling_map
Definition: profiling.F90:248
integer function profile_num_calls(this)
Definition: profiling.F90:1040
subroutine profiling_count_tran_type(trf, type)
Definition: profiling.F90:908
real(real64) function profile_min_time(this)
Definition: profiling.F90:953
subroutine, public profiling_memory_deallocate(var, file, line, size)
Definition: profiling.F90:1392
character(label_length) function profile_label(this)
Definition: profiling.F90:1051
real(real64) function profile_self_time_per_call(this)
Definition: profiling.F90:964
subroutine, public profiling_memory_allocate(var, file, line, size_)
Definition: profiling.F90:1321
subroutine profiling_count_tran_type_l(trf, type)
Definition: profiling.F90:812
subroutine profiling_make_position_str(var, file, line, str)
Definition: profiling.F90:1262
subroutine profiling_count_tran_complex_8(trf, type)
Definition: profiling.F90:894
subroutine profiling_count_tran_complex_4(trf, type)
Definition: profiling.F90:880
real(real64) function profile_total_bandwidth(this)
Definition: profiling.F90:992
real(real64) function profile_total_time(this)
Definition: profiling.F90:920
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:222
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:248
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:152
subroutine get_output_dir()
Definition: profiling.F90:396
recursive subroutine output_tree_level(profile, level, total_time, iunit)
Definition: profiling.F90:1230
int true(void)