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