V3FIT
profiler.f
Go to the documentation of this file.
1 !*******************************************************************************
4 !
5 ! Note separating the Doxygen comment block here so detailed decription is
6 ! found in the Module not the file.
7 !
11 !*******************************************************************************
12 
13  MODULE profiler
14  USE stel_kinds
15 
16  IMPLICIT NONE
17 
18 !*******************************************************************************
19 ! profiler module parameters
20 !*******************************************************************************
22  INTEGER, PARAMETER :: profiler_string_size = 68
24  INTEGER, PARAMETER :: profiler_bucket_size = 1000
25 
26 !*******************************************************************************
27 ! DERIVED-TYPE DECLARATIONS
28 ! 1) bucket
29 !
30 !*******************************************************************************
31 !-------------------------------------------------------------------------------
33 !-------------------------------------------------------------------------------
36 !$ INTEGER (kind=8) :: lock
38  INTEGER :: number_of_calls = 0
40  REAL (rprec) :: total_time = 0.0
42  REAL (rprec) :: average_time = 0.0
44  CHARACTER (len=profiler_string_size) :: symbol_name = ''
45  END TYPE
46 
47 !*******************************************************************************
48 ! profiler module variables
49 !*******************************************************************************
50 #if PROFILE_ON
51 
52  TYPE (profiler_bucket), DIMENSION(profiler_bucket_size), SAVE &
53  & :: buckets
54 #endif
55 
56  CONTAINS
57 !*******************************************************************************
58 ! CONSTRUCTION SUBROUTINES
59 !*******************************************************************************
60 !-------------------------------------------------------------------------------
65 !-------------------------------------------------------------------------------
66  SUBROUTINE profiler_construct()
67 
68  IMPLICIT NONE
69 
70 ! local variables
71 !$ INTEGER :: i
72 
73 ! Start of executable code
74 #if PROFILE_ON
75 !$ DO i = 1, profiler_bucket_size
76 !$ CALL OMP_INIT_LOCK(buckets(i)%lock)
77 !$ END DO
78 #endif
79  END SUBROUTINE
80 
81 !*******************************************************************************
82 ! DESTRUCTION SUBROUTINES
83 !*******************************************************************************
84 !-------------------------------------------------------------------------------
89 !-------------------------------------------------------------------------------
90  SUBROUTINE profiler_destruct()
91 
92  IMPLICIT NONE
93 
94 ! local variables
95 !$ INTEGER :: i
96 
97 ! Start of executable code
98 #if PROFILE_ON
99 !$ DO i = 1, profiler_bucket_size
100 !$ CALL OMP_DESTROY_LOCK(buckets(i)%lock)
101 !$ END DO
102 #endif
103  END SUBROUTINE
104 
105 !*******************************************************************************
106 ! SETTER SUBROUTINES
107 !*******************************************************************************
108 !-------------------------------------------------------------------------------
119 !-------------------------------------------------------------------------------
120  SUBROUTINE profiler_set_stop_time(symbol_name, start_time)
121 
122 ! Declare Arguments
123  CHARACTER (len=*), INTENT(in) :: symbol_name
124  REAL (rprec), INTENT(in) :: start_time
125 
126 ! local variables
127  INTEGER :: i, index
128  REAL (rprec) :: time
129 
130 ! Start of executable code.
131 #if PROFILE_ON
132  CALL second0(time)
133  time = time - start_time
134  index = profiler_hash_function(symbol_name)
135 
136  DO i = index, profiler_bucket_size
137 !$ CALL OMP_SET_LOCK(buckets(i)%lock)
138  IF (buckets(i)%symbol_name .eq. '') THEN
139  buckets(i)%symbol_name = symbol_name
140  buckets(i)%number_of_calls = 1
141  buckets(i)%total_time = time
142  buckets(i)%average_time = time
143 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
144  RETURN
145  ELSE IF (buckets(i)%symbol_name .eq. symbol_name) THEN
146  buckets(i)%number_of_calls = buckets(i)%number_of_calls + 1
147  buckets(i)%total_time = buckets(i)%total_time + time
148  buckets(i)%average_time = buckets(i)%total_time &
149  & / buckets(i)%number_of_calls
150 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
151  RETURN
152  END IF
153 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
154  END DO
155 
156  DO i = 1, index - 1
157 !$ CALL OMP_SET_LOCK(buckets(i)%lock)
158  IF (buckets(i)%symbol_name .eq. '') THEN
159  buckets(i)%symbol_name = symbol_name
160  buckets(i)%number_of_calls = 1
161  buckets(i)%total_time = time
162  buckets(i)%average_time = time
163 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
164  RETURN
165  ELSE IF (buckets(i)%symbol_name .eq. symbol_name) THEN
166  buckets(i)%number_of_calls = buckets(i)%number_of_calls + 1
167  buckets(i)%total_time = buckets(i)%total_time + time
168  buckets(i)%average_time = buckets(i)%total_time &
169  & / buckets(i)%number_of_calls
170 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
171  RETURN
172  END IF
173 !$ CALL OMP_UNSET_LOCK(buckets(i)%lock)
174  END DO
175 
176  WRITE (*,*) 'Profile table full: ' // trim(symbol_name) // &
177  & ' could not be profiled.'
178 #endif
179 
180  END SUBROUTINE
181 
182 !*******************************************************************************
183 ! GETTER SUBROUTINES
184 !*******************************************************************************
185 !-------------------------------------------------------------------------------
192 !-------------------------------------------------------------------------------
193  FUNCTION profiler_get_start_time()
194 
195  IMPLICIT NONE
196 
197 ! Declare Arguments
198  REAL (rprec) :: profiler_get_start_time
199 
200 ! Start of executable code
201 #if profile_on
202  CALL second0(profiler_get_start_time)
203 #else
205 #endif
206 
207  END FUNCTION
208 
209 !*******************************************************************************
210 ! UTILITY SUBROUTINES
211 !*******************************************************************************
212 !-------------------------------------------------------------------------------
219 !-------------------------------------------------------------------------------
220  RECURSIVE SUBROUTINE profiler_sort(low_index, high_index)
221 
222  IMPLICIT NONE
223 
224 ! Declare Arguments
225  INTEGER, INTENT(in) :: low_index
226  INTEGER, INTENT(in) :: high_index
227 
228 ! local variables
229  INTEGER :: mid_index
230  INTEGER :: i, i1, i2
231  TYPE (profiler_bucket) :: swap_bucket
232  TYPE (profiler_bucket), DIMENSION(:), ALLOCATABLE :: temp_buckets
233 
234 ! Start of executable code
235 #if profile_on
236  IF (high_index - low_index .lt. 2) THEN
237 ! Since the table has been reduced to two elements, sort the sub table.
238  IF (buckets(high_index)%average_time .gt. &
239  & buckets(low_index)%average_time) THEN
240 ! Swap the values
241  swap_bucket = buckets(low_index)
242  buckets(low_index) = buckets(high_index)
243  buckets(high_index) = swap_bucket
244  END IF
245  RETURN
246  END IF
247 
248 ! Split the table in the middle and sort the sub tables.
249  mid_index = (high_index + low_index)/2
250  CALL profiler_sort(low_index, mid_index - 1)
251  CALL profiler_sort(mid_index, high_index)
252 
253 ! Merge the two tables.
254  i1 = low_index
255  i2 = mid_index
256 
257  ALLOCATE(temp_buckets(low_index:high_index))
258 
259  DO i = low_index, high_index
260  IF (buckets(i1)%average_time .gt. &
261  & buckets(i2)%average_time) THEN
262 ! Take the value of the lower table and increment the lower index
263  temp_buckets(i) = buckets(i1)
264  i1 = i1 + 1
265  IF (i1 .gt. mid_index - 1) THEN
266 ! Merged the last value in the lower table the remining values are all from the
267 ! upper.
268  temp_buckets(i + 1:high_index) = buckets(i2:high_index)
269  EXIT
270  END IF
271  ELSE
272 ! Take the value of the upper table and increment the upper index
273  temp_buckets(i) = buckets(i2)
274  i2 = i2 + 1
275  IF (i2 .gt. high_index) THEN
276 ! Merged the last value in the upper tabel the remining values are all from the
277 ! lower.
278  temp_buckets(i + 1:high_index) = &
279  & buckets(i1:mid_index - 1)
280  EXIT
281  END IF
282  END IF
283  END DO
284 
285  buckets(low_index:high_index) = temp_buckets(low_index:high_index)
286 
287  DEALLOCATE(temp_buckets)
288 #endif
289  END SUBROUTINE
290 
291 !-------------------------------------------------------------------------------
304 !-------------------------------------------------------------------------------
305  FUNCTION profiler_hash_function(symbol_name)
306 
307  IMPLICIT NONE
308 
309 ! Declare Arguments
310  INTEGER :: profiler_hash_function
311  CHARACTER (len=*), INTENT(in) :: symbol_name
312 
313 ! local variables
314  INTEGER (kind=8) :: hash
315  INTEGER :: i
316 
317 ! Start of executable code
318  hash = 5381
319  DO i = 1, len_trim(symbol_name)
320  hash = (lshift(hash, 5) + hash) + ichar(symbol_name(i:i))
321  END DO
322 
323  profiler_hash_function = mod(abs(hash), profiler_bucket_size) + 1
324 
325  END FUNCTION
326 
327 !-------------------------------------------------------------------------------
334 !-------------------------------------------------------------------------------
335  SUBROUTINE profiler_write(iou)
336 
337  IMPLICIT NONE
338 
339 ! Declare Arguments
340  INTEGER, INTENT(in) :: iou
341 
342 ! local variables
343  INTEGER :: i
344 
345 ! Start of executable code
346 #if PROFILE_ON
347  WRITE (iou,*)
348  WRITE (iou,*) ' *** Code Profile Information'
349 
351 
352  WRITE (iou,1000)
353 
354  DO i = 1, profiler_bucket_size
355  IF (buckets(i)%symbol_name .ne. '') THEN
356  WRITE (iou, 1001) buckets(i)%symbol_name, &
357  & buckets(i)%average_time, &
358  & buckets(i)%total_time, &
359  & buckets(i)%number_of_calls
360  END IF
361  END DO
362 
363 1000 FORMAT('Symbol Name',59x,'Average Time',2x,'TotalTime',5x, &
364  & 'Num Calls')
365 1001 FORMAT(a68,2x,es12.5,2x,es12.5,2x,i9)
366 #endif
367 
368  END SUBROUTINE
369 
370  END MODULE
profiler::profiler_bucket_size
integer, parameter profiler_bucket_size
Max number of buckets.
Definition: profiler.f:24
profiler
Defines functions for measuring an tabulating performance of function and subroutine calls....
Definition: profiler.f:13
profiler::profiler_destruct
subroutine profiler_destruct()
Deconstruct a profiler.
Definition: profiler.f:91
profiler::profiler_sort
recursive subroutine profiler_sort(low_index, high_index)
Sorts the profile table based on the average call time.
Definition: profiler.f:221
profiler::buckets
type(profiler_bucket), dimension(profiler_bucket_size), save buckets
Array of buckets to hold the values.
Definition: profiler.f:52
profiler::profiler_string_size
integer, parameter profiler_string_size
Max string length.
Definition: profiler.f:22
profiler::profiler_get_start_time
real(rprec) function profiler_get_start_time()
Gets the start time of profiled function.
Definition: profiler.f:194
profiler::profiler_construct
subroutine profiler_construct()
Construct a profiler.
Definition: profiler.f:67
profiler::profiler_bucket
Full table of profiled functions.
Definition: profiler.f:34
profiler::profiler_set_stop_time
subroutine profiler_set_stop_time(symbol_name, start_time)
Gets the end time of profiled function.
Definition: profiler.f:121
profiler::profiler_write
subroutine profiler_write(iou)
Write out the profiled data to an output file.
Definition: profiler.f:336
profiler::profiler_hash_function
integer function profiler_hash_function(symbol_name)
Computes a hash for the symbol name.
Definition: profiler.f:306