19 character(len=LEN_SECTION_TITLE) :: title
22 integer(I4B) :: status
23 integer(I4B) :: parent_id
32 real(dp) :: sim_start_time
34 integer(I4B) :: tmr_run
35 integer(I4B) :: tmr_init
36 integer(I4B) :: tmr_update
37 integer(I4B) :: tmr_finalize
38 integer(I4B) :: tmr_prep_tstp
39 integer(I4B) :: tmr_do_tstp
40 integer(I4B) :: tmr_final_tstp
41 integer(I4B) :: tmr_output
42 integer(I4B) :: tmr_nc_export
44 integer(I4B),
private :: iout
45 integer(I4B),
private :: pr_option
46 integer(I4B),
private :: nr_sections
47 integer(I4B),
private,
dimension(3) :: top_three
48 integer(I4B),
private :: max_title_len
49 integer(I4B),
private :: root_id
78 call cpu_time(this%sim_start_time)
87 character(len=LENMEMPATH) :: input_mempath
90 character(len=:),
pointer :: prprof
92 integer(I4B) :: max_sections
93 integer(I4B) :: nr_solutions
98 this%tmr_finalize = -1
99 this%tmr_prep_tstp = -1
100 this%tmr_do_tstp = -1
101 this%tmr_final_tstp = -1
103 this%tmr_nc_export = -1
105 call this%callstack%init()
109 call mem_setptr(slntype,
'SLNTYPE', input_mempath)
110 nr_solutions =
size(slntype)
111 call mem_setptr(prprof,
'PRPROF', input_mempath)
112 call this%set_print_option(prprof)
115 allocate (this%all_sections(max_sections))
116 do i = 1, max_sections
117 this%all_sections(i)%title =
"undefined"
118 this%all_sections(i)%status = 0
119 this%all_sections(i)%walltime =
dzero
120 this%all_sections(i)%count = 0
121 this%all_sections(i)%parent_id = 0
122 call this%all_sections(i)%children%init()
127 this%top_three = [0, 0, 0]
130 if (this%pr_option > 0)
then
131 call this%start(
"Run", this%tmr_run)
132 this%all_sections(this%tmr_run)%walltime = -this%sim_start_time
143 character(len=*) :: title
144 integer(I4B) :: parent_id
145 integer(I4B) :: section_id
148 this%nr_sections = this%nr_sections + 1
149 section_id = this%nr_sections
150 if (section_id >
size(this%all_sections))
then
151 write (*, *)
"Internal error: Too many profiled sections, "&
152 &
"disable profiling to circumvent."
157 this%all_sections(section_id)%title = title
158 this%all_sections(section_id)%walltime =
dzero
159 this%all_sections(section_id)%status = 0
162 if (parent_id > 0)
then
164 this%all_sections(section_id)%parent_id = parent_id
165 call this%all_sections(parent_id)%children%push_back(section_id)
168 this%all_sections(section_id)%parent_id = 0
169 this%root_id = section_id
176 subroutine start(this, title, section_id)
178 character(len=*) :: title
179 integer(I4B) :: section_id
181 integer(I4B) :: parent_id
182 real(DP) :: start_time
185 if (this%pr_option == 0)
return
187 call cpu_time(start_time)
189 if (section_id == -1)
then
192 if (this%callstack%size() > 0)
then
193 parent_id = this%callstack%top()
195 section_id = this%add_section(title, parent_id)
197 call this%callstack%push(section_id)
199 section => this%all_sections(section_id)
200 section%count = section%count + 1
202 section%walltime = section%walltime - start_time
206 subroutine stop(this, section_id)
208 integer(I4B) :: section_id
213 if (this%pr_option == 0)
return
215 call cpu_time(end_time)
218 section => this%all_sections(section_id)
220 section%walltime = section%walltime + end_time
223 call this%callstack%pop()
229 integer(I4B),
intent(in) :: output_unit
231 integer(I4B) :: level, i, top_idx
232 integer(I4B),
dimension(:),
allocatable :: sorted_idxs
234 if (this%pr_option == 0)
return
236 this%iout = output_unit
240 sorted_idxs = (/(i, i=1, this%nr_sections)/)
241 call this%sort_by_walltime(sorted_idxs)
242 do i = 1, this%nr_sections
243 if (this%all_sections(sorted_idxs(i))%children%size == 0)
then
244 if (top_idx > 3)
exit
245 this%top_three(top_idx) = sorted_idxs(i)
246 top_idx = top_idx + 1
250 this%max_title_len = this%largest_title_length()
252 if (this%pr_option > 1)
then
255 write (this%iout,
'(/1x,a/)') &
256 repeat(
'-', 18)//
" Profiler: Call Stack "//repeat(
'-', 18)
257 call this%print_section(this%root_id, level)
263 write (this%iout,
'(1x,a/)') &
264 repeat(
'-', 20)//
" Profiler: Totals "//repeat(
'-', 20)
265 call this%print_total(
"Formulate")
266 call this%print_total(
"Linear solve")
267 call this%print_total(
"Calculate flows")
268 call this%print_total(
"Calculate budgets")
269 call this%print_total(
"Write output")
270 call this%print_total(
"Parallel Solution")
271 call this%print_total(
"MPI_WaitAll")
272 write (this%iout,
'(/1x,a/)') &
273 repeat(
'-', 22)//
" End Profiler "//repeat(
'-', 22)
280 integer(I4B) :: section_id
281 integer(I4B) :: level
283 integer(I4B) :: i, new_level, nr_padding, idx_top
286 character(len=:),
allocatable :: title_padded
287 character(len=LINELENGTH) :: top_marker
289 section => this%all_sections(section_id)
293 if (section%parent_id /= 0)
then
294 percent = section%walltime / this%all_sections(this%root_id)%walltime
296 percent = percent * 100.0_dp
300 idx_top =
ifind(this%top_three, section_id)
301 if (idx_top > 0)
then
302 nr_padding = max(0, 32 - level * 4)
303 write (top_marker,
'(a,i0)') repeat(
" ", nr_padding)//
"<== #", idx_top
307 nr_padding = this%max_title_len - len_trim(section%title) + 2
308 title_padded = trim(section%title)//
":"//repeat(
' ', nr_padding)
309 write (this%iout,
'(3a,f6.2,2a,f14.6,2a,i0,a,a)')
" ", &
310 repeat(
'....', level),
"[", percent,
"%] ", title_padded, &
311 section%walltime,
"s",
" (", section%count,
"x)", trim(top_marker)
314 new_level = level + 1
315 do i = 1, section%children%size
316 call this%print_section(section%children%at(i), new_level)
319 if (level == 0)
write (this%iout, *)
325 character(len=*) :: subtitle
327 integer(I4B) :: count
328 real(DP) :: walltime, percent
329 integer(I4B) :: nr_padding
330 character(len=:),
allocatable :: title_padded
333 nr_padding = this%max_title_len - len_trim(subtitle)
334 title_padded = trim(subtitle)//repeat(
' ', nr_padding)
336 count = this%aggregate_counts(subtitle)
339 percent = (walltime / this%all_sections(this%root_id)%walltime) * 100.0_dp
340 write (this%iout,
'(2a,f6.2,3a,f14.6,2a,i0,a)')
" ",
"[", percent, &
341 "%] ", title_padded,
": ", walltime,
"s",
" (", count,
"x)"
350 character(len=*) :: title
356 do i = 1, this%nr_sections
357 if (index(this%all_sections(i)%title, trim(title)) > 0)
then
358 walltime = walltime + this%all_sections(i)%walltime
368 character(len=*) :: title
369 integer(I4B) :: counts
374 do i = 1, this%nr_sections
375 if (index(this%all_sections(i)%title, trim(title)) > 0)
then
376 counts = counts + this%all_sections(i)%count
386 character(len=*),
intent(in) :: profile_option
388 select case (trim(profile_option))
408 call this%callstack%destroy()
410 do i = 1,
size(this%all_sections)
411 call this%all_sections(i)%children%destroy()
413 deallocate (this%all_sections)
414 nullify (this%all_sections)
422 integer(I4B) :: max_length
426 do i = 1, this%nr_sections
427 max_length = max(max_length, len_trim(this%all_sections(i)%title))
436 integer(I4B),
dimension(:),
allocatable :: idxs
437 integer(I4B) :: i, j, temp
440 do i = 1,
size(idxs) - 1
441 do j = 1,
size(idxs) - i
442 if (this%all_sections(idxs(j))%walltime < &
443 this%all_sections(idxs(j + 1))%walltime)
then
445 idxs(j) = idxs(j + 1)
This module contains simulation constants.
integer(i4b), parameter linelength
maximum length of a standard line
real(dp), parameter dnodata
real no data constant
real(dp), parameter dzero
real constant zero
integer(i4b), parameter lenmempath
maximum length of the memory path
This module defines variable data types.
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
type(profilertype), public g_prof
the global timer object (to reduce trivial lines of code)
integer(i4b) function aggregate_counts(this, title)
Aggregate counts over sections with a certain title.
integer(i4b), parameter max_sections_per_sln
real(dp) function aggregate_walltime(this, title)
Aggregate walltime over sections with a certain title.
subroutine pre_init(this)
subroutine sort_by_walltime(this, idxs)
Sort section indexes based on walltime.
integer(i4b), parameter, public len_section_title
subroutine set_print_option(this, profile_option)
Set the profile option from the user input.
subroutine print(this, output_unit)
integer(i4b) function largest_title_length(this)
Calculate the largest title length.
subroutine initialize(this)
integer(i4b) function add_section(this, title, parent_id)
Add a new timed section to the tree, passing the parent id will add it as a child.
recursive subroutine print_section(this, section_id, level)
subroutine start(this, title, section_id)
Start section timing, add when not exist yet (i.e. when id < 1)
subroutine stop(this, section_id)
subroutine print_total(this, subtitle)
This module contains simulation methods.
subroutine, public ustop(stopmess, ioutlocal)
Stop the simulation.
This module contains simulation variables.
character(len=linelength) idm_context
This class is used to store a single deferred-length character string. It was designed to work in an ...
A public type for profiling performance in the application. The ProfilerType is used to measure and r...
A derived type representing a stack of integers.