forked from LLNL/MACSio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmacsio_timing.h
287 lines (229 loc) · 10.9 KB
/
macsio_timing.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#ifndef _MACSIO_TIMING_H
#define _MACSIO_TIMING_H
/*
Copyright (c) 2015, Lawrence Livermore National Security, LLC.
Produced at the Lawrence Livermore National Laboratory.
Written by Mark C. Miller
LLNL-CODE-676051. All rights reserved.
This file is part of MACSio
Please also read the LICENSE file at the top of the source code directory or
folder hierarchy.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (as published by the Free Software
Foundation) version 2, dated June 1991.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <mpi.h>
#include <stdio.h>
#include <string.h>
/*!
\defgroup MACSIO_TIMING MACSIO_TIMING
\brief Timing utilities
MACSIO_TIMING utilities support the creation of a number of timers to time different sections of code.
Timers are initialized/started with a user-defined label, and an optional group mask and iteration number.
A hash of the timer is computed from its label and group combined with the source file name and line number.
The resulting hash value is used to identify the timer.
Timers can be iterated and re-started. These are two different concepts. During iteration, the same timer can be
used to time the same section of code as it gets executed multiple times. Each time represents a different
iteration of the timer. The timer will keep track of the minimum time, maximum time, average time and variance
of times over all iterations it is invoked. However, apart from these running statistics, a timer maintains no memory
of past values. If a timer is iterated 10 times, it does not maintain knowledge of all 10 individual times. It
maintains only knowledge of the running statistics; min, max, avg, var. The algorithm it uses to maintain these
running statistics is the Knuth "online" algorithm.
Within any timer iteration, a timer can be stopped and restarted. If a timer is being used to time
a block of code that involves some occasional and perhaps irrlevant alternative logic path,
the timer can be stopped until execution returns from the alternative path. Then the
timer can be restarted. This can only be done <em>within</em> a given iteration.
Timers can also be grouped into a small number of different classes. For example, it is possible to maintain
a set of timers for MIF file I/O apart from a set of timers being used to time a particular plugin's operations
to marshal a mesh or variable to/from persistent storage. Or, operations use to interact with filesystem metadata
directly (e.g. mkdir(2), chdir(2), readir(2), etc.) can be maintained separately from timers used for entirely
other purposes.
Finally, timers can be <em>reduced</em> across MPI ranks thereby creating a statistical summary of timer information
across processors.
A timer is initialized/started by a call to \c MACSIO_TIMING_StartTimer() or the convenience macro \c MT_StartTimer().
This call returns the timer's <em>ID</em> which is used in a subsequent call to \c MACSIO_TIMING_StopTimer() to stop
the timer.
\code
MACSIO_TIMING_TimerId_t tid = MT_StartTimer("my timer", MACSIO_TIMING_GROUP_NONE, MACSIO_TIMING_ITER_AUTO);
...do some work here...
MT_StopTimer(tid);
\endcode
In the above code, the call to MT_StartTimer starts a timer for a new (automatic) iteration. In this simple
examle, we do not worry about timer group masks.
By default, MACSIO_TIMING uses MPI_Wtime but a caller can set \c MACSIO_TIMING_UseMPI_Wtime() to zero to
instead use \c gettimeofday().
@{
*/
#ifdef __cplusplus
extern "C" {
#endif
/*!
\def MACSIO_TIMING_ITER_AUTO
\brief Automatic iteration numbering
Use for \c iter argument to \c StartTimer() when you don't want to manager iteration numbering
of the timer explicitly.
*/
#define MACSIO_TIMING_ITER_AUTO -1
/*!
\def MACSIO_TIMING_ITER_IGNORE
\brief What is this?
*/
#define MACSIO_TIMING_ITER_IGNORE -2
/*!
\def MACSIO_TIMING_INVALID_TIMER
\brief Maybe returned from \c StartTimer()
*/
#define MACSIO_TIMING_INVALID_TIMER (~((MACSIO_TIMING_TimerId_t)0x0))
/*!
\def MACSIO_TIMING_NO_GROUP
\brief Group mask when timer is not assigned to any group
*/
#define MACSIO_TIMING_NO_GROUP (((MACSIO_TIMING_GroupMask_t)0x0)
/*!
\def MACSIO_TIMING_ALL_GROUPS
\brief Group mask representing all groups
*/
#define MACSIO_TIMING_ALL_GROUPS (~((MACSIO_TIMING_GroupMask_t)0))
/*!
\def MT_Time
\brief Convenience macro for getting current time
*/
#define MT_Time MACSIO_TIMING_GetCurrentTime
/*!
\def MT_StartTimer
\brief Convenience macro for starting a timer
\param [in] LAB User defined timer label string
\param [in] GMASK User defined group mask. Use MACSIO_TIMING_NO_GROUP if timer grouping is not needed.
\param [in] ITER The iteration number. Use MACSIO_TIMING_ITER_IGNORE if timer iteration is not needed.
*/
#define __BASEFILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#define MT_StartTimer(LAB, GMASK, ITER) MACSIO_TIMING_StartTimer(LAB, GMASK, ITER, __BASEFILE__, __LINE__)
/*!
\def MT_StopTimer
\brief Convenience macro for stopping a timer
\param [in] ID The timer's hash id returned from a call to \c MT_StartTimer().
*/
#define MT_StopTimer(ID) MACSIO_TIMING_StopTimer(ID)
typedef unsigned int MACSIO_TIMING_TimerId_t;
typedef unsigned long long MACSIO_TIMING_GroupMask_t;
/*!
\brief Integer variable to control function used to get timer values
A non-zero value indicates that MACSIO_TIMING should use \c MPI_Wtime. Otherwise, it will
use \c gettimeofday().
*/
extern int MACSIO_TIMING_UseMPI_Wtime;
/*!
\brief Create a group name and mask
A small number of groups (less than 64) can be defined into which timers can be grouped
Timers can be assigned to multiple groups by or'ing the resulting group masks.
*/
extern MACSIO_TIMING_GroupMask_t MACSIO_TIMING_GroupMask(
char const *grpName /**< Name of the group for which group mask is needed */
);
/*!
\brief Create/Start a timer
This call either creates a new timer and starts it or starts a new iteration of an existing timer.
\return A hash derived from a string catenation the \c label, \c gmask, \c file and \c line.
*/
extern MACSIO_TIMING_TimerId_t
MACSIO_TIMING_StartTimer(
char const *label, /**< User defined label to be assigned to the timer */
MACSIO_TIMING_GroupMask_t gmask, /**< Mask to indicate the timer's group membership */
int iter_num, /**< Iteration number */
char const *file, /**< The source file name */
int line /**< The source file line number*/);
/*!
\brief Stop a timer
This call stops a currently running timer.
\return Returns the time for the current iteration of the timer
*/
extern double
MACSIO_TIMING_StopTimer(MACSIO_TIMING_TimerId_t id /**< The timer's ID, returned from a call to StartTimer */);
/*!
\brief Get data from a specific timer
For field names, see definition of timerInfo_t
*/
extern double
MACSIO_TIMING_GetTimer(
MACSIO_TIMING_TimerId_t tid, /**< The timer's ID, returned from a call to StartTimer */
char const *field /**< The name of the field from the timer to return */
);
/*!
\brief Get data from a specific reduced timer
*/
extern double
MACSIO_TIMING_GetReducedTimer(
MACSIO_TIMING_TimerId_t tid, /**< The timer's ID, returned from a call to StartTimer */
char const *field /**< The name of the field from the timer to return */
);
/*!
\brief Dump timers to ascii strings
This call will find all used timers in the hash table matching the specified \c gmask group mask and dumps
each timer to a string. For convenience, the maximum length of the strings is also returned. This is to
facilitate dumping the strings to a MACSIO_LOG.
Each timer is dumped to a string with the following informational fields catenated together ...
- TOT=%10.5f total amount of time spent in this time over all iterations (and ranks when reduced)
- CNT=%04d total number of iterations this timer was triggered (over all ranks when reduced)
- MIN=%8.5f(%4.2f):%06d
- minimum time recorded for this timer over all iterations (and ranks when reduced)
- (%4.2f) the number of standard deviations from the mean time
- :%06d the rank (when reduced) where the minimum was observed.
- AVG=%8.5f the mean time of this timer over all iterations (and ranks when reduced)
- MAX=%8.5f(%4.2f):%06d,
- maximum time recorded for this timer over all iterations (and ranks when reduced)
- (%4.2f) the number of standard deviations from the mean time
- :%06d the rank (when reduced) where the maximum was observed.
- DEV=%8.8f standard deviation observed for all iterations of this timer
- FILE=%s the source file where this timer is triggered
- LINE=%d the source line number where this timer is triggered
- LAB=%s the user-defined label for this timer
*/
extern void MACSIO_TIMING_DumpTimersToStrings(
MACSIO_TIMING_GroupMask_t gmask, /**< Group mask to filter only timers belonging to specific groups */
char ***strs, /**< An array of strings, one for each timer, returned to caller. Caller is responsible for freeing */
int *nstrs, /**< Number of strings returned to caller */
int *maxlen /**< The maximum length of all strings */);
/*!
\brief Reduce timers across MPI tasks
Computes a parallel reduction across MPI tasks of all timers.
*/
extern void
MACSIO_TIMING_ReduceTimers(
#ifdef HAVE_MPI
MPI_Comm comm, /**< The MPI communicator to use for the reduction */
#else
int comm, /**< Dummy value for non-parallel builds */
#endif
int root /**< The MPI rank of the root task to be used for the reduction */);
/*!
\brief Dump reduced timers to ascii strings
Similar to \c DumpTimersToStrings except this call dumps reduced timers
*/
extern void
MACSIO_TIMING_DumpReducedTimersToStrings(
MACSIO_TIMING_GroupMask_t gmask, /**< Group mask to filter only timers belonging to specific groups */
char ***strs, /**< An array of strings, one for each timer, returned to caller. Caller is responsible for freeing */
int *nstrs, /**< Number of strings returned to caller */
int *maxlen /**< The maximum length of all strings */);
/*!
\brief Clear a group of timers
Clears and resets timers of specified group
*/
extern void MACSIO_TIMING_ClearTimers(
MACSIO_TIMING_GroupMask_t gmask /**< Group mask to filter only timers belonging to specific groups */);
/*!
\brief Get current time
*/
extern double MACSIO_TIMING_GetCurrentTime(void);
#ifdef __cplusplus
}
#endif
/*!@}*/
#endif /* _MACSIO_TIMING_H */