xref: /petsc/include/petsclog.h (revision 1c1ad86e71981700dcc8fd0d1cc1167892fbe263)
1 /*
2     Defines profile/logging in PETSc.
3 */
4 #ifndef PETSCLOG_H
5 #define PETSCLOG_H
6 
7 #include <petscsys.h>
8 #include <petsctime.h>
9 #include <petsclogtypes.h>
10 
11 /* SUBMANSEC = Profiling */
12 
13 /* General logging of information; different from event logging */
14 PETSC_EXTERN PetscErrorCode PetscInfo_Private(const char[], PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(3, 4);
15 #if defined(PETSC_USE_INFO)
16   #define PetscInfo(A, ...) PetscInfo_Private(PETSC_FUNCTION_NAME, ((PetscObject)A), __VA_ARGS__)
17 #else
18   #define PetscInfo(A, ...) PETSC_SUCCESS
19 #endif
20 
21 #define PetscInfo1(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
22 #define PetscInfo2(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
23 #define PetscInfo3(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
24 #define PetscInfo4(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
25 #define PetscInfo5(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
26 #define PetscInfo6(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
27 #define PetscInfo7(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
28 #define PetscInfo8(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
29 #define PetscInfo9(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
30 
31 /*E
32   PetscInfoCommFlag - Describes the method by which to filter information displayed by `PetscInfo()` by communicator size
33 
34   Values:
35 + `PETSC_INFO_COMM_ALL` - Default uninitialized value. `PetscInfo()` will not filter based on
36                           communicator size (i.e. will print for all communicators)
37 . `PETSC_INFO_COMM_NO_SELF` - `PetscInfo()` will NOT print for communicators with size = 1 (i.e. *_COMM_SELF)
38 - `PETSC_INFO_COMM_ONLY_SELF` - `PetscInfo()` will ONLY print for communicators with size = 1
39 
40   Level: intermediate
41 
42   Note:
43   Used as an input for `PetscInfoSetFilterCommSelf()`
44 
45 .seealso: `PetscInfo()`, `PetscInfoSetFromOptions()`, `PetscInfoSetFilterCommSelf()`
46 E*/
47 typedef enum {
48   PETSC_INFO_COMM_ALL       = -1,
49   PETSC_INFO_COMM_NO_SELF   = 0,
50   PETSC_INFO_COMM_ONLY_SELF = 1
51 } PetscInfoCommFlag;
52 
53 PETSC_EXTERN const char *const PetscInfoCommFlags[];
54 PETSC_EXTERN PetscErrorCode    PetscInfoDeactivateClass(PetscClassId);
55 PETSC_EXTERN PetscErrorCode    PetscInfoActivateClass(PetscClassId);
56 PETSC_EXTERN PetscErrorCode    PetscInfoEnabled(PetscClassId, PetscBool *);
57 PETSC_EXTERN PetscErrorCode    PetscInfoAllow(PetscBool);
58 PETSC_EXTERN PetscErrorCode    PetscInfoSetFile(const char[], const char[]);
59 PETSC_EXTERN PetscErrorCode    PetscInfoGetFile(char **, FILE **);
60 PETSC_EXTERN PetscErrorCode    PetscInfoSetClasses(PetscBool, PetscInt, const char *const *);
61 PETSC_EXTERN PetscErrorCode    PetscInfoGetClass(const char *, PetscBool *);
62 PETSC_EXTERN PetscErrorCode    PetscInfoGetInfo(PetscBool *, PetscBool *, PetscBool *, PetscBool *, PetscInfoCommFlag *);
63 PETSC_EXTERN PetscErrorCode    PetscInfoProcessClass(const char[], PetscInt, const PetscClassId[]);
64 PETSC_EXTERN PetscErrorCode    PetscInfoSetFilterCommSelf(PetscInfoCommFlag);
65 PETSC_EXTERN PetscErrorCode    PetscInfoSetFromOptions(PetscOptions);
66 PETSC_EXTERN PetscErrorCode    PetscInfoDestroy(void);
67 PETSC_EXTERN PetscBool         PetscLogPrintInfo; /* if true, indicates PetscInfo() is turned on */
68 
69 #define PETSC_EVENT 1311311
70 PETSC_EXTERN PetscLogEvent PETSC_LARGEST_EVENT;
71 
72 PETSC_EXTERN PetscErrorCode PetscIntStackCreate(PetscIntStack *);
73 PETSC_EXTERN PetscErrorCode PetscIntStackDestroy(PetscIntStack);
74 PETSC_EXTERN PetscErrorCode PetscIntStackPush(PetscIntStack, int);
75 PETSC_EXTERN PetscErrorCode PetscIntStackPop(PetscIntStack, int *);
76 PETSC_EXTERN PetscErrorCode PetscIntStackTop(PetscIntStack, int *);
77 PETSC_EXTERN PetscErrorCode PetscIntStackEmpty(PetscIntStack, PetscBool *);
78 
79 /* Handle multithreading */
80 #if defined(PETSC_HAVE_THREADSAFETY)
81   #if defined(__cplusplus)
82     #define PETSC_TLS thread_local
83   #else
84     #define PETSC_TLS _Thread_local
85   #endif
86   #define PETSC_EXTERN_TLS extern PETSC_TLS PETSC_VISIBILITY_PUBLIC
87 PETSC_EXTERN PetscErrorCode PetscAddLogDouble(PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
88 PETSC_EXTERN PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
89 #else
90   #define PETSC_EXTERN_TLS PETSC_EXTERN
91   #define PETSC_TLS
92   #define PetscAddLogDouble(a, b, c)          ((PetscErrorCode)((*(a) += (c), PETSC_SUCCESS) || ((*(b) += (c)), PETSC_SUCCESS)))
93   #define PetscAddLogDoubleCnt(a, b, c, d, e) ((PetscErrorCode)(PetscAddLogDouble(a, c, 1) || PetscAddLogDouble(b, d, e)))
94 #endif
95 
96 /*
97     PetscClassRegInfo, PetscClassPerfInfo - Each class has two data structures associated with it. The first has
98        static information about it, the second collects statistics on how many objects of the class are created,
99        how much memory they use, etc.
100 
101     PetscClassRegLog, PetscClassPerfLog - arrays of the PetscClassRegInfo and PetscClassPerfInfo for all classes.
102 */
103 typedef struct {
104   char        *name;    /* The class name */
105   PetscClassId classid; /* The integer identifying this class */
106 } PetscClassRegInfo;
107 
108 typedef struct {
109   PetscClassId   id;           /* The integer identifying this class */
110   int            creations;    /* The number of objects of this class created */
111   int            destructions; /* The number of objects of this class destroyed */
112   PetscLogDouble mem;          /* The total memory allocated by objects of this class; this is completely wrong and should possibly be removed */
113   PetscLogDouble descMem;      /* The total memory allocated by descendents of these objects; this is completely wrong and should possibly be removed */
114 } PetscClassPerfInfo;
115 
116 typedef struct _n_PetscClassRegLog *PetscClassRegLog;
117 struct _n_PetscClassRegLog {
118   int                numClasses; /* The number of classes registered */
119   int                maxClasses; /* The maximum number of classes */
120   PetscClassRegInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
121 };
122 
123 typedef struct _n_PetscClassPerfLog *PetscClassPerfLog;
124 struct _n_PetscClassPerfLog {
125   int                 numClasses; /* The number of logging classes */
126   int                 maxClasses; /* The maximum number of classes */
127   PetscClassPerfInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
128 };
129 
130 /*
131     PetscEventRegInfo, PetscEventPerfInfo - Each event has two data structures associated with it. The first has
132        static information about it, the second collects statistics on how many times the event is used, how
133        much time it takes, etc.
134 
135     PetscEventRegLog, PetscEventPerfLog - an array of all PetscEventRegInfo and PetscEventPerfInfo for all events. There is one
136       of these for each stage.
137 
138 */
139 typedef struct {
140   char        *name;       /* The name of this event */
141   PetscClassId classid;    /* The class the event is associated with */
142   PetscBool    collective; /* Flag this event as collective */
143 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
144   void *timer; /* Associated external tool timer for this event */
145 #endif
146 #if defined(PETSC_HAVE_MPE)
147   int mpe_id_begin; /* MPE IDs that define the event */
148   int mpe_id_end;
149 #endif
150 } PetscEventRegInfo;
151 
152 typedef struct _n_PetscEventRegLog *PetscEventRegLog;
153 struct _n_PetscEventRegLog {
154   int                numEvents; /* The number of registered events */
155   int                maxEvents; /* The maximum number of events */
156   PetscEventRegInfo *eventInfo; /* The registration information for each event */
157 };
158 
159 typedef struct _n_PetscEventPerfLog *PetscEventPerfLog;
160 struct _n_PetscEventPerfLog {
161   int                 numEvents; /* The number of logging events */
162   int                 maxEvents; /* The maximum number of events */
163   PetscEventPerfInfo *eventInfo; /* The performance information for each event */
164 };
165 
166 /*
167    PetscStageInfo - Contains all the information about a particular stage.
168 
169    PetscStageLog - An array of PetscStageInfo for each registered stage. There is a single one of these in the code.
170 */
171 typedef struct _PetscStageInfo {
172   char              *name;     /* The stage name */
173   PetscBool          used;     /* The stage was pushed on this processor */
174   PetscEventPerfInfo perfInfo; /* The stage performance information */
175   PetscEventPerfLog  eventLog; /* The event information for this stage */
176   PetscClassPerfLog  classLog; /* The class information for this stage */
177 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
178   void *timer; /* Associated external tool timer for this stage */
179 #endif
180 } PetscStageInfo;
181 
182 typedef struct _n_PetscStageLog *PetscStageLog;
183 struct _n_PetscStageLog {
184   int              numStages; /* The number of registered stages */
185   int              maxStages; /* The maximum number of stages */
186   PetscIntStack    stack;     /* The stack for active stages */
187   int              curStage;  /* The current stage (only used in macros so we don't call PetscIntStackTop) */
188   PetscStageInfo  *stageInfo; /* The information for each stage */
189   PetscEventRegLog eventLog;  /* The registered events */
190   PetscClassRegLog classLog;  /* The registered classes */
191 };
192 
193 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectParent()", ) static inline PetscErrorCode PetscLogObjectParent(PetscObject o, PetscObject p)
194 {
195   (void)o;
196   (void)p;
197   return PETSC_SUCCESS;
198 }
199 
200 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectMemory()", ) static inline PetscErrorCode PetscLogObjectMemory(PetscObject o, PetscLogDouble m)
201 {
202   (void)o;
203   (void)m;
204   return PETSC_SUCCESS;
205 }
206 
207 #if defined(PETSC_USE_LOG) /* --- Logging is turned on --------------------------------*/
208 PETSC_EXTERN PetscStageLog  petsc_stageLog;
209 PETSC_EXTERN PetscErrorCode PetscLogGetStageLog(PetscStageLog *);
210 PETSC_EXTERN PetscErrorCode PetscStageLogGetCurrent(PetscStageLog, int *);
211 PETSC_EXTERN PetscErrorCode PetscStageLogGetEventPerfLog(PetscStageLog, int, PetscEventPerfLog *);
212 
213 PETSC_EXTERN PetscErrorCode PetscGetFlops(PetscLogDouble *);
214 
215   #if defined(PETSC_HAVE_MPE)
216 PETSC_EXTERN PetscErrorCode PetscLogMPEBegin(void);
217 PETSC_EXTERN PetscErrorCode PetscLogMPEDump(const char[]);
218   #endif
219 
220 PETSC_EXTERN PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
221 PETSC_EXTERN PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
222 PETSC_EXTERN PetscErrorCode (*PetscLogPHC)(PetscObject);
223 PETSC_EXTERN PetscErrorCode (*PetscLogPHD)(PetscObject);
224 
225   #define PetscLogObjectParents(p, n, d) PetscMacroReturnStandard(for (int _i = 0; _i < (n); ++_i) PetscCall(PetscLogObjectParent((PetscObject)(p), (PetscObject)(d)[_i]));)
226   #define PetscLogObjectCreate(h)        ((PetscLogPHC) ? (*PetscLogPHC)((PetscObject)(h)) : PETSC_SUCCESS)
227   #define PetscLogObjectDestroy(h)       ((PetscLogPHD) ? (*PetscLogPHD)((PetscObject)(h)) : PETSC_SUCCESS)
228 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
229 
230 /* Initialization functions */
231 PETSC_EXTERN PetscErrorCode PetscLogDefaultBegin(void);
232 PETSC_EXTERN PetscErrorCode PetscLogAllBegin(void);
233 PETSC_EXTERN PetscErrorCode PetscLogNestedBegin(void);
234 PETSC_EXTERN PetscErrorCode PetscLogTraceBegin(FILE *);
235 PETSC_EXTERN PetscErrorCode PetscLogActions(PetscBool);
236 PETSC_EXTERN PetscErrorCode PetscLogObjects(PetscBool);
237 PETSC_EXTERN PetscErrorCode PetscLogSetThreshold(PetscLogDouble, PetscLogDouble *);
238 PETSC_EXTERN PetscErrorCode PetscLogSet(PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject));
239 
240 /* Output functions */
241 PETSC_EXTERN PetscErrorCode PetscLogView(PetscViewer);
242 PETSC_EXTERN PetscErrorCode PetscLogViewFromOptions(void);
243 PETSC_EXTERN PetscErrorCode PetscLogDump(const char[]);
244 
245 /* Status checking functions */
246 PETSC_EXTERN PetscErrorCode PetscLogIsActive(PetscBool *);
247 
248 /* Stage functions */
249 PETSC_EXTERN PetscErrorCode PetscLogStageRegister(const char[], PetscLogStage *);
250 PETSC_EXTERN PetscErrorCode PetscLogStagePush(PetscLogStage);
251 PETSC_EXTERN PetscErrorCode PetscLogStagePop(void);
252 PETSC_EXTERN PetscErrorCode PetscLogStageSetActive(PetscLogStage, PetscBool);
253 PETSC_EXTERN PetscErrorCode PetscLogStageGetActive(PetscLogStage, PetscBool *);
254 PETSC_EXTERN PetscErrorCode PetscLogStageSetVisible(PetscLogStage, PetscBool);
255 PETSC_EXTERN PetscErrorCode PetscLogStageGetVisible(PetscLogStage, PetscBool *);
256 PETSC_EXTERN PetscErrorCode PetscLogStageGetId(const char[], PetscLogStage *);
257 
258 /* Event functions */
259 PETSC_EXTERN PetscErrorCode PetscLogEventRegister(const char[], PetscClassId, PetscLogEvent *);
260 PETSC_EXTERN PetscErrorCode PetscLogEventSetCollective(PetscLogEvent, PetscBool);
261 PETSC_EXTERN PetscErrorCode PetscLogEventIncludeClass(PetscClassId);
262 PETSC_EXTERN PetscErrorCode PetscLogEventExcludeClass(PetscClassId);
263 PETSC_EXTERN PetscErrorCode PetscLogEventActivate(PetscLogEvent);
264 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivate(PetscLogEvent);
265 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent);
266 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent);
267 PETSC_EXTERN PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent, PetscBool);
268 PETSC_EXTERN PetscErrorCode PetscLogEventActivateClass(PetscClassId);
269 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivateClass(PetscClassId);
270 PETSC_EXTERN PetscErrorCode PetscLogEventGetId(const char[], PetscLogEvent *);
271 PETSC_EXTERN PetscErrorCode PetscLogEventGetPerfInfo(int, PetscLogEvent, PetscEventPerfInfo *);
272 PETSC_EXTERN PetscErrorCode PetscLogEventSetDof(PetscLogEvent, PetscInt, PetscLogDouble);
273 PETSC_EXTERN PetscErrorCode PetscLogEventSetError(PetscLogEvent, PetscInt, PetscLogDouble);
274 PETSC_EXTERN PetscErrorCode PetscLogPushCurrentEvent_Internal(PetscLogEvent);
275 PETSC_EXTERN PetscErrorCode PetscLogPopCurrentEvent_Internal(void);
276 
277 PETSC_EXTERN PetscBool PetscLogMemory;
278 
279 PETSC_EXTERN PetscBool      PetscLogSyncOn; /* true if logging synchronization is enabled */
280 PETSC_EXTERN PetscErrorCode PetscLogEventSynchronize(PetscLogEvent, MPI_Comm);
281 
282   #define PetscLogEventSync(e, comm) \
283     ((PetscErrorCode)(((PetscLogPLB && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? PetscLogEventSynchronize((e), (comm)) : PETSC_SUCCESS)))
284 
285   #define PetscLogEventBegin(e, o1, o2, o3, o4) \
286     ((PetscErrorCode)((PetscLogPLB && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? (PetscErrorCode)(((*PetscLogPLB)((e), 0, (PetscObject)(o1), (PetscObject)(o2), (PetscObject)(o3), (PetscObject)(o4))) || PetscLogPushCurrentEvent_Internal(e)) : PETSC_SUCCESS))
287 
288   #define PetscLogEventEnd(e, o1, o2, o3, o4) \
289     ((PetscErrorCode)((PetscLogPLE && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? (PetscErrorCode)(((*PetscLogPLE)((e), 0, (PetscObject)(o1), (PetscObject)(o2), (PetscObject)(o3), (PetscObject)(o4))) || PetscLogPopCurrentEvent_Internal()) : PETSC_SUCCESS))
290 
291 PETSC_EXTERN PetscErrorCode PetscLogEventGetFlops(PetscLogEvent, PetscLogDouble *);
292 PETSC_EXTERN PetscErrorCode PetscLogEventZeroFlops(PetscLogEvent);
293 
294 /* Global flop counter */
295 PETSC_EXTERN PetscLogDouble petsc_TotalFlops;
296 PETSC_EXTERN PetscLogDouble petsc_irecv_ct;
297 PETSC_EXTERN PetscLogDouble petsc_isend_ct;
298 PETSC_EXTERN PetscLogDouble petsc_recv_ct;
299 PETSC_EXTERN PetscLogDouble petsc_send_ct;
300 PETSC_EXTERN PetscLogDouble petsc_irecv_len;
301 PETSC_EXTERN PetscLogDouble petsc_isend_len;
302 PETSC_EXTERN PetscLogDouble petsc_recv_len;
303 PETSC_EXTERN PetscLogDouble petsc_send_len;
304 PETSC_EXTERN PetscLogDouble petsc_allreduce_ct;
305 PETSC_EXTERN PetscLogDouble petsc_gather_ct;
306 PETSC_EXTERN PetscLogDouble petsc_scatter_ct;
307 PETSC_EXTERN PetscLogDouble petsc_wait_ct;
308 PETSC_EXTERN PetscLogDouble petsc_wait_any_ct;
309 PETSC_EXTERN PetscLogDouble petsc_wait_all_ct;
310 PETSC_EXTERN PetscLogDouble petsc_sum_of_waits_ct;
311 
312 /* Thread local storage */
313 PETSC_EXTERN_TLS PetscLogDouble petsc_TotalFlops_th;
314 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_ct_th;
315 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_ct_th;
316 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_ct_th;
317 PETSC_EXTERN_TLS PetscLogDouble petsc_send_ct_th;
318 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_len_th;
319 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_len_th;
320 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_len_th;
321 PETSC_EXTERN_TLS PetscLogDouble petsc_send_len_th;
322 PETSC_EXTERN_TLS PetscLogDouble petsc_allreduce_ct_th;
323 PETSC_EXTERN_TLS PetscLogDouble petsc_gather_ct_th;
324 PETSC_EXTERN_TLS PetscLogDouble petsc_scatter_ct_th;
325 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_ct_th;
326 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_any_ct_th;
327 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_all_ct_th;
328 PETSC_EXTERN_TLS PetscLogDouble petsc_sum_of_waits_ct_th;
329 
330   /*
331    Flop counting:  We count each arithmetic operation (e.g., addition, multiplication) separately.
332 
333    For the complex numbers version, note that
334        1 complex addition = 2 flops
335        1 complex multiplication = 6 flops,
336    where we define 1 flop as that for a double precision scalar.  We roughly approximate
337    flop counting for complex numbers by multiplying the total flops by 4; this corresponds
338    to the assumption that we're counting mostly additions and multiplications -- and
339    roughly the same number of each.  More accurate counting could be done by distinguishing
340    among the various arithmetic operations.
341  */
342 
343   #if defined(PETSC_USE_COMPLEX)
344     #define PETSC_FLOPS_PER_OP 4.0
345   #else
346     #define PETSC_FLOPS_PER_OP 1.0
347   #endif
348 
349 /*@C
350        PetscLogFlops - Log how many flops are performed in a calculation
351 
352    Input Parameter:
353 .   flops - the number of flops
354 
355    Level: intermediate
356 
357    Note:
358      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
359      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
360 
361 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`
362 @*/
363 static inline PetscErrorCode PetscLogFlops(PetscLogDouble n)
364 {
365   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
366   return PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n);
367 }
368 
369   /*
370      These are used internally in the PETSc routines to keep a count of MPI messages and
371    their sizes.
372 
373      This does not work for MPI-Uni because our include/petsc/mpiuni/mpi.h file
374    uses macros to defined the MPI operations.
375 
376      It does not work correctly from HP-UX because it processes the
377    macros in a way that sometimes it double counts, hence
378    PETSC_HAVE_BROKEN_RECURSIVE_MACRO
379 
380      It does not work with Windows because winmpich lacks MPI_Type_size()
381 */
382   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
383 /*
384    Logging of MPI activities
385 */
386 static inline PetscErrorCode PetscMPITypeSize(PetscInt count, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
387 {
388   PetscMPIInt typesize;
389 
390   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
391   PetscCallMPI(MPI_Type_size(type, &typesize));
392   return PetscAddLogDouble(length, length_th, (PetscLogDouble)(count * typesize));
393 }
394 
395 static inline PetscErrorCode PetscMPITypeSizeComm(MPI_Comm comm, const PetscMPIInt *counts, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
396 {
397   PetscMPIInt    typesize, size, p;
398   PetscLogDouble l;
399 
400   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
401   PetscCallMPI(MPI_Comm_size(comm, &size));
402   PetscCallMPI(MPI_Type_size(type, &typesize));
403   for (p = 0, l = 0.0; p < size; ++p) l += (PetscLogDouble)(counts[p] * typesize);
404   return PetscAddLogDouble(length, length_th, l);
405 }
406 
407 /*
408     Returns 1 if the communicator is parallel else zero
409 */
410 static inline int PetscMPIParallelComm(MPI_Comm comm)
411 {
412   PetscMPIInt size;
413   MPI_Comm_size(comm, &size);
414   return size > 1;
415 }
416 
417     #define MPI_Irecv(buf, count, datatype, source, tag, comm, request) \
418       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPI_Irecv((buf), (count), (datatype), (source), (tag), (comm), (request)))
419 
420     #define MPI_Irecv_c(buf, count, datatype, source, tag, comm, request) \
421       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPI_Irecv_c((buf), (count), (datatype), (source), (tag), (comm), (request)))
422 
423     #define MPI_Isend(buf, count, datatype, dest, tag, comm, request) \
424       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPI_Isend((buf), (count), (datatype), (dest), (tag), (comm), (request)))
425 
426     #define MPI_Isend_c(buf, count, datatype, dest, tag, comm, request) \
427       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPI_Isend_c((buf), (count), (datatype), (dest), (tag), (comm), (request)))
428 
429     #define MPI_Startall_irecv(count, datatype, number, requests) \
430       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || ((number) && MPI_Startall((number), (requests))))
431 
432     #define MPI_Startall_isend(count, datatype, number, requests) \
433       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || ((number) && MPI_Startall((number), (requests))))
434 
435     #define MPI_Start_isend(count, datatype, requests) (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_isend_len), (&petsc_isend_len_th)) || MPI_Start((requests)))
436 
437     #define MPI_Recv(buf, count, datatype, source, tag, comm, status) \
438       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Recv((buf), (count), (datatype), (source), (tag), (comm), (status)))
439 
440     #define MPI_Recv_c(buf, count, datatype, source, tag, comm, status) \
441       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Recv_c((buf), (count), (datatype), (source), (tag), (comm), (status)))
442 
443     #define MPI_Send(buf, count, datatype, dest, tag, comm) \
444       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Send((buf), (count), (datatype), (dest), (tag), (comm)))
445 
446     #define MPI_Send_c(buf, count, datatype, dest, tag, comm) \
447       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Send_c((buf), (count), (datatype), (dest), (tag), (comm)))
448 
449     #define MPI_Wait(request, status) (PetscAddLogDouble(&petsc_wait_ct, &petsc_wait_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPI_Wait((request), (status)))
450 
451     #define MPI_Waitany(a, b, c, d) (PetscAddLogDouble(&petsc_wait_any_ct, &petsc_wait_any_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPI_Waitany((a), (b), (c), (d)))
452 
453     #define MPI_Waitall(count, array_of_requests, array_of_statuses) \
454       (PetscAddLogDouble(&petsc_wait_all_ct, &petsc_wait_all_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, count) || MPI_Waitall((count), (array_of_requests), (array_of_statuses)))
455 
456     #define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm) (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Allreduce((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
457 
458     #define MPI_Bcast(buffer, count, datatype, root, comm) (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Bcast((buffer), (count), (datatype), (root), (comm)))
459 
460     #define MPI_Reduce_scatter_block(sendbuf, recvbuf, recvcount, datatype, op, comm) \
461       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Reduce_scatter_block((sendbuf), (recvbuf), (recvcount), (datatype), (op), (comm)))
462 
463     #define MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
464       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Alltoall((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
465 
466     #define MPI_Alltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm) \
467       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSizeComm((comm), (sendcnts), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Alltoallv((sendbuf), (sendcnts), (sdispls), (sendtype), (recvbuf), (recvcnts), (rdispls), (recvtype), (comm)))
468 
469     #define MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
470       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
471 
472     #define MPI_Allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm) \
473       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm)))
474 
475     #define MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
476       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Gather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
477 
478     #define MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm) \
479       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Gatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (root), (comm)))
480 
481     #define MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
482       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Scatter((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
483 
484     #define MPI_Scatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm) \
485       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Scatterv((sendbuf), (sendcount), (displs), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
486 
487     #define MPI_Ialltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
488       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Ialltoall((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
489 
490     #define MPI_Ialltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm, request) \
491       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSizeComm((comm), (sendcnts), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Ialltoallv((sendbuf), (sendcnts), (sdispls), (sendtype), (recvbuf), (recvcnts), (rdispls), (recvtype), (comm), (request)))
492 
493     #define MPI_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
494       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
495 
496     #define MPI_Iallgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm, request) \
497       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm), (request)))
498 
499     #define MPI_Igather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
500       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Igather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
501 
502     #define MPI_Igatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm, request) \
503       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Igatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (root), (comm), (request)))
504 
505     #define MPI_Iscatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
506       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Iscatter((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
507 
508     #define MPI_Iscatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
509       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Iscatterv((sendbuf), (sendcount), (displs), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
510 
511     #define MPIX_Send_enqueue(buf, count, datatype, dest, tag, comm) \
512       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPIX_Send_enqueue((buf), (count), (datatype), (dest), (tag), (comm)))
513 
514     #define MPIX_Recv_enqueue(buf, count, datatype, source, tag, comm, status) \
515       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPIX_Recv_enqueue((buf), (count), (datatype), (source), (tag), (comm), (status)))
516 
517     #define MPIX_Isend_enqueue(buf, count, datatype, dest, tag, comm, request) \
518       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPIX_Isend_enqueue((buf), (count), (datatype), (dest), (tag), (comm), (request)))
519 
520     #define MPIX_Irecv_enqueue(buf, count, datatype, source, tag, comm, request) \
521       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPIX_Irecv_enqueue((buf), (count), (datatype), (source), (tag), (comm), (request)))
522 
523     #define MPIX_Allreduce_enqueue(sendbuf, recvbuf, count, datatype, op, comm) \
524       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPIX_Allreduce_enqueue((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
525 
526     #define MPIX_Wait_enqueue(request, status) (PetscAddLogDouble(&petsc_wait_ct, &petsc_wait_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPIX_Wait_enqueue((request), (status)))
527 
528     #define MPIX_Waitall_enqueue(count, array_of_requests, array_of_statuses) \
529       (PetscAddLogDouble(&petsc_wait_all_ct, &petsc_wait_all_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, count) || MPIX_Waitall_enqueue((count), (array_of_requests), (array_of_statuses)))
530   #else
531 
532     #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
533 
534     #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
535 
536     #define MPI_Start_isend(count, datatype, requests) (MPI_Start((requests)))
537 
538   #endif /* !MPIUNI_H && ! PETSC_HAVE_BROKEN_RECURSIVE_MACRO */
539 
540 #else /* ---Logging is turned off --------------------------------------------*/
541 
542   #define PetscLogMemory PETSC_FALSE
543 
544   #define PetscLogFlops(n) ((void)(n), PETSC_SUCCESS)
545   #define PetscGetFlops(a) (*(a) = 0.0, PETSC_SUCCESS)
546 
547   #define PetscLogStageRegister(a, b)   PETSC_SUCCESS
548   #define PetscLogStagePush(a)          PETSC_SUCCESS
549   #define PetscLogStagePop()            PETSC_SUCCESS
550   #define PetscLogStageSetActive(a, b)  PETSC_SUCCESS
551   #define PetscLogStageGetActive(a, b)  PETSC_SUCCESS
552   #define PetscLogStageGetVisible(a, b) PETSC_SUCCESS
553   #define PetscLogStageSetVisible(a, b) PETSC_SUCCESS
554   #define PetscLogStageGetId(a, b)      (*(b) = 0, PETSC_SUCCESS)
555 
556   #define PetscLogEventRegister(a, b, c)    PETSC_SUCCESS
557   #define PetscLogEventSetCollective(a, b)  PETSC_SUCCESS
558   #define PetscLogEventIncludeClass(a)      PETSC_SUCCESS
559   #define PetscLogEventExcludeClass(a)      PETSC_SUCCESS
560   #define PetscLogEventActivate(a)          PETSC_SUCCESS
561   #define PetscLogEventDeactivate(a)        PETSC_SUCCESS
562   #define PetscLogEventDeactivatePush(a)    PETSC_SUCCESS
563   #define PetscLogEventDeactivatePop(a)     PETSC_SUCCESS
564   #define PetscLogEventActivateClass(a)     PETSC_SUCCESS
565   #define PetscLogEventDeactivateClass(a)   PETSC_SUCCESS
566   #define PetscLogEventSetActiveAll(a, b)   PETSC_SUCCESS
567   #define PetscLogEventGetId(a, b)          (*(b) = 0, PETSC_SUCCESS)
568   #define PetscLogEventGetPerfInfo(a, b, c) PETSC_SUCCESS
569   #define PetscLogEventSetDof(a, b, c)      PETSC_SUCCESS
570   #define PetscLogEventSetError(a, b, c)    PETSC_SUCCESS
571 
572   #define PetscLogPLB PETSC_SUCCESS
573   #define PetscLogPLE PETSC_SUCCESS
574   #define PetscLogPHC PETSC_SUCCESS
575   #define PetscLogPHD PETSC_SUCCESS
576 
577   #define PetscLogObjectParents(p, n, c) PETSC_SUCCESS
578   #define PetscLogObjectCreate(h)        PETSC_SUCCESS
579   #define PetscLogObjectDestroy(h)       PETSC_SUCCESS
580 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
581 
582   #define PetscLogDefaultBegin()     PETSC_SUCCESS
583   #define PetscLogAllBegin()         PETSC_SUCCESS
584   #define PetscLogNestedBegin()      PETSC_SUCCESS
585   #define PetscLogTraceBegin(file)   PETSC_SUCCESS
586   #define PetscLogActions(a)         PETSC_SUCCESS
587   #define PetscLogObjects(a)         PETSC_SUCCESS
588   #define PetscLogSetThreshold(a, b) PETSC_SUCCESS
589   #define PetscLogSet(lb, le)        PETSC_SUCCESS
590   #define PetscLogIsActive(flag)     (*(flag) = PETSC_FALSE, PETSC_SUCCESS)
591 
592   #define PetscLogView(viewer)      PETSC_SUCCESS
593   #define PetscLogViewFromOptions() PETSC_SUCCESS
594   #define PetscLogDump(c)           PETSC_SUCCESS
595 
596   #define PetscLogEventSync(e, comm)                            PETSC_SUCCESS
597   #define PetscLogEventBegin(e, o1, o2, o3, o4)                 PETSC_SUCCESS
598   #define PetscLogEventEnd(e, o1, o2, o3, o4)                   PETSC_SUCCESS
599 
600   /* If PETSC_USE_LOG is NOT defined, these still need to be! */
601   #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
602   #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
603   #define MPI_Start_isend(count, datatype, requests)            MPI_Start(requests)
604 
605 #endif /* PETSC_USE_LOG */
606 
607 #define PetscPreLoadBegin(flag, name) \
608   do { \
609     PetscBool     PetscPreLoading = flag; \
610     int           PetscPreLoadMax, PetscPreLoadIt; \
611     PetscLogStage _stageNum; \
612     PetscCall(PetscOptionsGetBool(NULL, NULL, "-preload", &PetscPreLoading, NULL)); \
613     PetscPreLoadMax     = (int)(PetscPreLoading); \
614     PetscPreLoadingUsed = PetscPreLoading ? PETSC_TRUE : PetscPreLoadingUsed; \
615     for (PetscPreLoadIt = 0; PetscPreLoadIt <= PetscPreLoadMax; PetscPreLoadIt++) { \
616       PetscPreLoadingOn = PetscPreLoading; \
617       PetscCall(PetscBarrier(NULL)); \
618       if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
619       else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
620       PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
621       PetscCall(PetscLogStagePush(_stageNum))
622 
623 #define PetscPreLoadEnd() \
624   PetscCall(PetscLogStagePop()); \
625   PetscPreLoading = PETSC_FALSE; \
626   } \
627   } \
628   while (0)
629 
630 #define PetscPreLoadStage(name) \
631   do { \
632     PetscCall(PetscLogStagePop()); \
633     if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
634     else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
635     PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
636     PetscCall(PetscLogStagePush(_stageNum)); \
637   } while (0)
638 
639 /* some vars for logging */
640 PETSC_EXTERN PetscBool PetscPreLoadingUsed; /* true if we are or have done preloading */
641 PETSC_EXTERN PetscBool PetscPreLoadingOn;   /* true if we are currently in a preloading calculation */
642 
643 #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_DEVICE)
644 
645 /* Global GPU counters */
646 PETSC_EXTERN PetscLogDouble petsc_ctog_ct;
647 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct;
648 PETSC_EXTERN PetscLogDouble petsc_ctog_sz;
649 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz;
650 PETSC_EXTERN PetscLogDouble petsc_ctog_ct_scalar;
651 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct_scalar;
652 PETSC_EXTERN PetscLogDouble petsc_ctog_sz_scalar;
653 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz_scalar;
654 PETSC_EXTERN PetscLogDouble petsc_gflops;
655 PETSC_EXTERN PetscLogDouble petsc_gtime;
656 
657 /* Thread local storage */
658 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_th;
659 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_th;
660 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_th;
661 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_th;
662 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_scalar_th;
663 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_scalar_th;
664 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_scalar_th;
665 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_scalar_th;
666 PETSC_EXTERN_TLS PetscLogDouble petsc_gflops_th;
667 PETSC_EXTERN_TLS PetscLogDouble petsc_gtime_th;
668 
669 PETSC_EXTERN PetscErrorCode PetscLogGpuTime(void);
670 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeBegin(void);
671 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeEnd(void);
672 
673 /*@C
674        PetscLogGpuFlops - Log how many flops are performed in a calculation on the device
675 
676    Input Parameter:
677 .   flops - the number of flops
678 
679    Level: intermediate
680 
681    Notes:
682      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
683      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
684 
685      The values are also added to the total flop count for the MPI rank that is set with `PetscLogFlops()`; hence the number of flops
686      just on the CPU would be the value from set from `PetscLogFlops()` minus the value set from `PetscLogGpuFlops()`
687 
688 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogFlops()`, `PetscLogGpuTimeBegin()`, `PetscLogGpuTimeEnd()`
689 @*/
690 static inline PetscErrorCode PetscLogGpuFlops(PetscLogDouble n)
691 {
692   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
693   PetscCall(PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n));
694   PetscCall(PetscAddLogDouble(&petsc_gflops, &petsc_gflops_th, PETSC_FLOPS_PER_OP * n));
695   return PETSC_SUCCESS;
696 }
697 
698 static inline PetscErrorCode PetscLogGpuTimeAdd(PetscLogDouble t)
699 {
700   return PetscAddLogDouble(&petsc_gtime, &petsc_gtime_th, t);
701 }
702 
703 static inline PetscErrorCode PetscLogCpuToGpu(PetscLogDouble size)
704 {
705   return PetscAddLogDoubleCnt(&petsc_ctog_ct, &petsc_ctog_sz, &petsc_ctog_ct_th, &petsc_ctog_sz_th, size);
706 }
707 
708 static inline PetscErrorCode PetscLogGpuToCpu(PetscLogDouble size)
709 {
710   return PetscAddLogDoubleCnt(&petsc_gtoc_ct, &petsc_gtoc_sz, &petsc_gtoc_ct_th, &petsc_gtoc_sz_th, size);
711 }
712 
713 static inline PetscErrorCode PetscLogCpuToGpuScalar(PetscLogDouble size)
714 {
715   return PetscAddLogDoubleCnt(&petsc_ctog_ct_scalar, &petsc_ctog_sz_scalar, &petsc_ctog_ct_scalar_th, &petsc_ctog_sz_scalar_th, size);
716 }
717 
718 static inline PetscErrorCode PetscLogGpuToCpuScalar(PetscLogDouble size)
719 {
720   return PetscAddLogDoubleCnt(&petsc_gtoc_ct_scalar, &petsc_gtoc_sz_scalar, &petsc_gtoc_ct_scalar_th, &petsc_gtoc_sz_scalar_th, size);
721 }
722 #else
723 
724   #define PetscLogCpuToGpu(a)       PETSC_SUCCESS
725   #define PetscLogGpuToCpu(a)       PETSC_SUCCESS
726   #define PetscLogCpuToGpuScalar(a) PETSC_SUCCESS
727   #define PetscLogGpuToCpuScalar(a) PETSC_SUCCESS
728   #define PetscLogGpuFlops(a)       PETSC_SUCCESS
729   #define PetscLogGpuTime()         PETSC_SUCCESS
730   #define PetscLogGpuTimeAdd(a)     PETSC_SUCCESS
731   #define PetscLogGpuTimeBegin()    PETSC_SUCCESS
732   #define PetscLogGpuTimeEnd()      PETSC_SUCCESS
733 
734 #endif /* PETSC_USE_LOG && PETSC_HAVE_DEVICE */
735 
736 /* remove TLS defines */
737 #undef PETSC_EXTERN_TLS
738 #undef PETSC_TLS
739 
740 #endif
741