Actual source code: plog.c

  1: /*
  2:       PETSc code to log object creation and destruction and PETSc events.

  4:       This provides the public API used by the rest of PETSc and by users.

  6:       These routines use a private API that is not used elsewhere in PETSc and is not
  7:       accessible to users. The private API is defined in logimpl.h and the utils directory.

  9:       ***

 11:       This file, and only this file, is for functions that interact with the global logging state
 12: */
 13: #include <petsc/private/logimpl.h>
 14: #include <petsc/private/loghandlerimpl.h>
 15: #include <petsctime.h>
 16: #include <petscviewer.h>
 17: #include <petscdevice.h>
 18: #include <petsc/private/deviceimpl.h>

 20: #if defined(PETSC_HAVE_THREADSAFETY)

 22: PetscInt           petsc_log_gid = -1; /* Global threadId counter */
 23: PETSC_TLS PetscInt petsc_log_tid = -1; /* Local threadId */

 25: /* shared variables */
 26: PetscSpinlock PetscLogSpinLock;

 28: PetscInt PetscLogGetTid(void)
 29: {
 30:   if (petsc_log_tid < 0) {
 31:     PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
 32:     petsc_log_tid = ++petsc_log_gid;
 33:     PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
 34:   }
 35:   return petsc_log_tid;
 36: }

 38: #endif

 40: /* Global counters */
 41: PetscLogDouble petsc_BaseTime        = 0.0;
 42: PetscLogDouble petsc_TotalFlops      = 0.0; /* The number of flops */
 43: PetscLogDouble petsc_send_ct         = 0.0; /* The number of sends */
 44: PetscLogDouble petsc_recv_ct         = 0.0; /* The number of receives */
 45: PetscLogDouble petsc_send_len        = 0.0; /* The total length of all sent messages */
 46: PetscLogDouble petsc_recv_len        = 0.0; /* The total length of all received messages */
 47: PetscLogDouble petsc_isend_ct        = 0.0; /* The number of immediate sends */
 48: PetscLogDouble petsc_irecv_ct        = 0.0; /* The number of immediate receives */
 49: PetscLogDouble petsc_isend_len       = 0.0; /* The total length of all immediate send messages */
 50: PetscLogDouble petsc_irecv_len       = 0.0; /* The total length of all immediate receive messages */
 51: PetscLogDouble petsc_wait_ct         = 0.0; /* The number of waits */
 52: PetscLogDouble petsc_wait_any_ct     = 0.0; /* The number of anywaits */
 53: PetscLogDouble petsc_wait_all_ct     = 0.0; /* The number of waitalls */
 54: PetscLogDouble petsc_sum_of_waits_ct = 0.0; /* The total number of waits */
 55: PetscLogDouble petsc_allreduce_ct    = 0.0; /* The number of reductions */
 56: PetscLogDouble petsc_gather_ct       = 0.0; /* The number of gathers and gathervs */
 57: PetscLogDouble petsc_scatter_ct      = 0.0; /* The number of scatters and scattervs */

 59: /* Thread Local storage */
 60: PETSC_TLS PetscLogDouble petsc_TotalFlops_th      = 0.0;
 61: PETSC_TLS PetscLogDouble petsc_send_ct_th         = 0.0;
 62: PETSC_TLS PetscLogDouble petsc_recv_ct_th         = 0.0;
 63: PETSC_TLS PetscLogDouble petsc_send_len_th        = 0.0;
 64: PETSC_TLS PetscLogDouble petsc_recv_len_th        = 0.0;
 65: PETSC_TLS PetscLogDouble petsc_isend_ct_th        = 0.0;
 66: PETSC_TLS PetscLogDouble petsc_irecv_ct_th        = 0.0;
 67: PETSC_TLS PetscLogDouble petsc_isend_len_th       = 0.0;
 68: PETSC_TLS PetscLogDouble petsc_irecv_len_th       = 0.0;
 69: PETSC_TLS PetscLogDouble petsc_wait_ct_th         = 0.0;
 70: PETSC_TLS PetscLogDouble petsc_wait_any_ct_th     = 0.0;
 71: PETSC_TLS PetscLogDouble petsc_wait_all_ct_th     = 0.0;
 72: PETSC_TLS PetscLogDouble petsc_sum_of_waits_ct_th = 0.0;
 73: PETSC_TLS PetscLogDouble petsc_allreduce_ct_th    = 0.0;
 74: PETSC_TLS PetscLogDouble petsc_gather_ct_th       = 0.0;
 75: PETSC_TLS PetscLogDouble petsc_scatter_ct_th      = 0.0;

 77: PetscLogDouble petsc_ctog_ct        = 0.0; /* The total number of CPU to GPU copies */
 78: PetscLogDouble petsc_gtoc_ct        = 0.0; /* The total number of GPU to CPU copies */
 79: PetscLogDouble petsc_ctog_sz        = 0.0; /* The total size of CPU to GPU copies */
 80: PetscLogDouble petsc_gtoc_sz        = 0.0; /* The total size of GPU to CPU copies */
 81: PetscLogDouble petsc_ctog_ct_scalar = 0.0; /* The total number of CPU to GPU copies */
 82: PetscLogDouble petsc_gtoc_ct_scalar = 0.0; /* The total number of GPU to CPU copies */
 83: PetscLogDouble petsc_ctog_sz_scalar = 0.0; /* The total size of CPU to GPU copies */
 84: PetscLogDouble petsc_gtoc_sz_scalar = 0.0; /* The total size of GPU to CPU copies */
 85: PetscLogDouble petsc_gflops         = 0.0; /* The flops done on a GPU */
 86: PetscLogDouble petsc_gtime          = 0.0; /* The time spent on a GPU */

 88: PETSC_TLS PetscLogDouble petsc_ctog_ct_th        = 0.0;
 89: PETSC_TLS PetscLogDouble petsc_gtoc_ct_th        = 0.0;
 90: PETSC_TLS PetscLogDouble petsc_ctog_sz_th        = 0.0;
 91: PETSC_TLS PetscLogDouble petsc_gtoc_sz_th        = 0.0;
 92: PETSC_TLS PetscLogDouble petsc_ctog_ct_scalar_th = 0.0;
 93: PETSC_TLS PetscLogDouble petsc_gtoc_ct_scalar_th = 0.0;
 94: PETSC_TLS PetscLogDouble petsc_ctog_sz_scalar_th = 0.0;
 95: PETSC_TLS PetscLogDouble petsc_gtoc_sz_scalar_th = 0.0;
 96: PETSC_TLS PetscLogDouble petsc_gflops_th         = 0.0;
 97: PETSC_TLS PetscLogDouble petsc_gtime_th          = 0.0;

 99: PetscBool PetscLogMemory = PETSC_FALSE;
100: PetscBool PetscLogSyncOn = PETSC_FALSE;

102: PetscBool PetscLogGpuTimeFlag = PETSC_FALSE;

104: PetscLogState petsc_log_state = NULL;

106: #define PETSC_LOG_HANDLER_HOT_BLANK \
107:   { \
108:     NULL, NULL, NULL, NULL, NULL, NULL \
109:   }

111: PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX] = {
112:   PETSC_LOG_HANDLER_HOT_BLANK,
113:   PETSC_LOG_HANDLER_HOT_BLANK,
114:   PETSC_LOG_HANDLER_HOT_BLANK,
115:   PETSC_LOG_HANDLER_HOT_BLANK,
116: };

118: #undef PETSC_LOG_HANDLERS_HOT_BLANK

120: #if defined(PETSC_USE_LOG)
121: #include <../src/sys/logging/handler/impls/default/logdefault.h>

123:   #if defined(PETSC_HAVE_THREADSAFETY)
124: PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble tmp)
125: {
126:   *tot_th += tmp;
127:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
128:   *tot += tmp;
129:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
130:   return PETSC_SUCCESS;
131: }

133: PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble tmp)
134: {
135:   *cnt_th = *cnt_th + 1;
136:   *tot_th += tmp;
137:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
138:   *tot += (PetscLogDouble)(tmp);
139:   *cnt += *cnt + 1;
140:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
141:   return PETSC_SUCCESS;
142: }

144:   #endif

146: static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
147: {
148:   PetscFunctionBegin;
149:   PetscAssertPointer(handler, 2);
150:   *handler = NULL;
151:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
152:     PetscLogHandler h = PetscLogHandlers[i].handler;
153:     if (h) {
154:       PetscBool match;

156:       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
157:       if (match) {
158:         *handler = PetscLogHandlers[i].handler;
159:         PetscFunctionReturn(PETSC_SUCCESS);
160:       }
161:     }
162:   }
163:   PetscFunctionReturn(PETSC_SUCCESS);
164: }

166: /*@
167:   PetscLogGetDefaultHandler - Get the default log handler if it is running.

169:   Not collective

171:   Output Parameter:
172: . handler - the default `PetscLogHandler`, or `NULL` if it is not running.

174:   Level: developer

176:   Notes:
177:   The default handler is started with `PetscLogDefaultBegin()`,
178:   if the options flags `-log_all` or `-log_view` is given without arguments,
179:   or for `-log_view :output:format` if `format` is not `ascii_xml` or `ascii_flamegraph`.

181: .seealso: [](ch_profiling)
182: @*/
183: PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
184: {
185:   PetscFunctionBegin;
186:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
187:   PetscFunctionReturn(PETSC_SUCCESS);
188: }

190: static PetscErrorCode PetscLogGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
191: {
192:   PetscFunctionBegin;
193:   PetscAssertPointer(handler, 2);
194:   PetscCall(PetscLogTryGetHandler(type, handler));
195:   PetscCheck(*handler != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "A PetscLogHandler of type %s has not been started.", type);
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: /*@
200:   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
201:   by all default log handlers (`PetscLogDefaultBegin()`,
202:   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
203:   `PetscLogPerfstubsBegin()`).

205:   Collective on `PETSC_COMM_WORLD`

207:   Output Parameter:
208: . state - The `PetscLogState` changed by registrations (such as
209:           `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or
210:           `PetscLogStagePush()`), or `NULL` if logging is not active

212:   Level: developer

214: .seealso: [](ch_profiling), `PetscLogState`
215: @*/
216: PetscErrorCode PetscLogGetState(PetscLogState *state)
217: {
218:   PetscFunctionBegin;
219:   PetscAssertPointer(state, 1);
220:   *state = petsc_log_state;
221:   PetscFunctionReturn(PETSC_SUCCESS);
222: }

224: static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
225: {
226:   PetscFunctionBegin;
227:   hot->handler       = h;
228:   hot->eventBegin    = h->ops->eventbegin;
229:   hot->eventEnd      = h->ops->eventend;
230:   hot->eventSync     = h->ops->eventsync;
231:   hot->objectCreate  = h->ops->objectcreate;
232:   hot->objectDestroy = h->ops->objectdestroy;
233:   PetscFunctionReturn(PETSC_SUCCESS);
234: }

236: /*@
237:   PetscLogHandlerStart - Connect a log handler to PETSc's global logging stream and state.

239:   Logically collective

241:   Input Parameters:
242: . h - a `PetscLogHandler`

244:   Level: developer

246:   Notes:
247:   Users should only need this if they create their own log handlers: handlers that are started
248:   from the command line (such as `-log_view` and `-log_trace`) or from a function like
249:   `PetscLogNestedBegin()` will automatically be started.

251:   There is a limit of `PESC_LOG_HANDLER_MAX` handlers that can be active at one time.

253:   To disconnect a handler from the global stream call `PetscLogHandlerStop()`.

255:   When a log handler is started, stages that have already been pushed with `PetscLogStagePush()`,
256:   will be pushed for the new log handler, but it will not be informed of any events that are
257:   in progress.  It is recommended to start any user-defined log handlers immediately following
258:   `PetscInitialize()`  before any user-defined stages are pushed.

260: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`, `PetscInitialize()`
261: @*/
262: PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
263: {
264:   PetscFunctionBegin;
265:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
266:     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
267:   }
268:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
269:     if (PetscLogHandlers[i].handler == NULL) {
270:       PetscCall(PetscObjectReference((PetscObject)h));
271:       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
272:       if (petsc_log_state) {
273:         PetscLogStage stack_height;
274:         PetscIntStack orig_stack, temp_stack;

276:         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
277:         stack_height = petsc_log_state->stage_stack->top + 1;
278:         PetscCall(PetscIntStackCreate(&temp_stack));
279:         orig_stack                     = petsc_log_state->stage_stack;
280:         petsc_log_state->stage_stack   = temp_stack;
281:         petsc_log_state->current_stage = -1;
282:         for (int s = 0; s < stack_height; s++) {
283:           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];
284:           PetscCall(PetscLogHandlerStagePush(h, stage));
285:           PetscCall(PetscIntStackPush(temp_stack, stage));
286:           petsc_log_state->current_stage = stage;
287:         }
288:         PetscCall(PetscIntStackDestroy(temp_stack));
289:         petsc_log_state->stage_stack = orig_stack;
290:       }
291:       PetscFunctionReturn(PETSC_SUCCESS);
292:     }
293:   }
294:   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
295:   PetscFunctionReturn(PETSC_SUCCESS);
296: }

298: /*@
299:   PetscLogHandlerStop - Disconnect a log handler from PETSc's global logging stream.

301:   Logically collective

303:   Input Parameters:
304: . h - a `PetscLogHandler`

306:   Level: developer

308:   Note:
309:   After `PetscLogHandlerStop()`, the handler can still access the global logging state
310:   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
311:   (for instance, in `PetscLogHandlerView()`),

313:   When a log handler is stopped, the remaining stages will be popped before it is
314:   disconnected from the log stream.

316: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
317: @*/
318: PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
319: {
320:   PetscFunctionBegin;
321:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
322:     if (PetscLogHandlers[i].handler == h) {
323:       if (petsc_log_state) {
324:         PetscLogState state;
325:         PetscLogStage stack_height;
326:         PetscIntStack orig_stack, temp_stack;

328:         PetscCall(PetscLogHandlerGetState(h, &state));
329:         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
330:         stack_height = petsc_log_state->stage_stack->top + 1;
331:         PetscCall(PetscIntStackCreate(&temp_stack));
332:         orig_stack                   = petsc_log_state->stage_stack;
333:         petsc_log_state->stage_stack = temp_stack;
334:         for (int s = 0; s < stack_height; s++) {
335:           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];

337:           PetscCall(PetscIntStackPush(temp_stack, stage));
338:         }
339:         for (int s = 0; s < stack_height; s++) {
340:           PetscLogStage stage;
341:           PetscBool     empty;

343:           PetscCall(PetscIntStackPop(temp_stack, &stage));
344:           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
345:           if (!empty) {
346:             PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
347:           } else petsc_log_state->current_stage = -1;
348:           PetscCall(PetscLogHandlerStagePop(h, stage));
349:         }
350:         PetscCall(PetscIntStackDestroy(temp_stack));
351:         petsc_log_state->stage_stack = orig_stack;
352:         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
353:       }
354:       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
355:       PetscCall(PetscObjectDereference((PetscObject)h));
356:     }
357:   }
358:   PetscFunctionReturn(PETSC_SUCCESS);
359: }

361: /*@C
362:   PetscLogIsActive - Check if logging is currently in progress.

364:   Not Collective

366:   Output Parameter:
367: . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise

369:   Level: beginner

371: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
372: @*/
373: PetscErrorCode PetscLogIsActive(PetscBool *isActive)
374: {
375:   PetscFunctionBegin;
376:   *isActive = PETSC_FALSE;
377:   if (petsc_log_state) {
378:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
379:       if (PetscLogHandlers[i].handler) {
380:         *isActive = PETSC_TRUE;
381:         PetscFunctionReturn(PETSC_SUCCESS);
382:       }
383:     }
384:   }
385:   PetscFunctionReturn(PETSC_SUCCESS);
386: }

388: PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
389: {
390:   PetscFunctionBegin;
391:   *isActive = PETSC_FALSE;
392:   if (petsc_log_state) {
393:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
394:       if (PetscLogHandlers[i].eventBegin) {
395:         *isActive = PETSC_TRUE;
396:         PetscFunctionReturn(PETSC_SUCCESS);
397:       }
398:     }
399:   }
400:   PetscFunctionReturn(PETSC_SUCCESS);
401: }

403: PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
404: {
405:   PetscFunctionBegin;
406:   *isActive = PETSC_FALSE;
407:   if (petsc_log_state) {
408:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
409:       if (PetscLogHandlers[i].eventEnd) {
410:         *isActive = PETSC_TRUE;
411:         PetscFunctionReturn(PETSC_SUCCESS);
412:       }
413:     }
414:   }
415:   PetscFunctionReturn(PETSC_SUCCESS);
416: }

418: PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
419: {
420:   PetscLogHandler handler;

422:   PetscFunctionBegin;
423:   PetscCall(PetscLogTryGetHandler(type, &handler));
424:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
425:   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
426:   PetscCall(PetscLogHandlerSetType(handler, type));
427:   PetscCall(PetscLogHandlerStart(handler));
428:   PetscCall(PetscLogHandlerDestroy(&handler));
429:   PetscFunctionReturn(PETSC_SUCCESS);
430: }

432: /*@C
433:   PetscLogDefaultBegin - Turns on logging of objects and events using the default log handler. This logs flop
434:   rates and object creation and should not slow programs down too much.
435:   This routine may be called more than once.

437:   Logically Collective on `PETSC_COMM_WORLD`

439:   Options Database Key:
440: . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing information to the
441:                   screen (for code configured with --with-log=1 (which is the default))

443:   Example Usage:
444: .vb
445:       PetscInitialize(...);
446:       PetscLogDefaultBegin();
447:        ... code ...
448:       PetscLogView(viewer); or PetscLogDump();
449:       PetscFinalize();
450: .ve

452:   Level: advanced

454:   Note:
455:   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
456:   the logging information.

458: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
459: @*/
460: PetscErrorCode PetscLogDefaultBegin(void)
461: {
462:   PetscFunctionBegin;
463:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
464:   PetscFunctionReturn(PETSC_SUCCESS);
465: }

467: /*@C
468:   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
469:   begins or ends, the event name is printed.

471:   Logically Collective on `PETSC_COMM_WORLD`

473:   Input Parameter:
474: . file - The file to print trace in (e.g. stdout)

476:   Options Database Key:
477: . -log_trace [filename] - Begins `PetscLogTraceBegin()`

479:   Level: intermediate

481:   Notes:
482:   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
483:   then "Event begin:" or "Event end:" followed by the event name.

485:   `PetscLogTraceBegin()` allows tracing of all PETSc calls, which is useful
486:   to determine where a program is hanging without running in the
487:   debugger.  Can be used in conjunction with the -info option.

489: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
490: @*/
491: PetscErrorCode PetscLogTraceBegin(FILE *file)
492: {
493:   PetscLogHandler handler;

495:   PetscFunctionBegin;
496:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
497:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
498:   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
499:   PetscCall(PetscLogHandlerStart(handler));
500:   PetscCall(PetscLogHandlerDestroy(&handler));
501:   PetscFunctionReturn(PETSC_SUCCESS);
502: }

504: PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(MPI_Comm, PetscLogHandler *);

506: /*@C
507:   PetscLogNestedBegin - Turns on nested logging of objects and events. This logs flop
508:   rates and object creation and should not slow programs down too much.

510:   Logically Collective on `PETSC_COMM_WORLD`

512:   Options Database Keys:
513: . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file

515:   Example Usage:
516: .vb
517:       PetscInitialize(...);
518:       PetscLogNestedBegin();
519:        ... code ...
520:       PetscLogView(viewer);
521:       PetscFinalize();
522: .ve

524:   Level: advanced

526: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
527: @*/
528: PetscErrorCode PetscLogNestedBegin(void)
529: {
530:   PetscFunctionBegin;
531:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
532:   PetscFunctionReturn(PETSC_SUCCESS);
533: }

535: /*@C
536:   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
537:   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
538:   `PetscLogPHC`, `PetscLogPHD`.

540:   Logically Collective on `PETSC_COMM_WORLD`

542:   Input Parameters:
543: + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
544: . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
545: . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
546: - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)

548:   Calling sequence of `PetscLogPLB`:
549: + e  - a `PetscLogEvent` that is beginning
550: . _i - deprecated, unused
551: . o1 - a `PetscObject` associated with `e` (or `NULL`)
552: . o2 - a `PetscObject` associated with `e` (or `NULL`)
553: . o3 - a `PetscObject` associated with `e` (or `NULL`)
554: - o4 - a `PetscObject` associated with `e` (or `NULL`)

556:   Calling sequence of `PetscLogPLE`:
557: + e  - a `PetscLogEvent` that is beginning
558: . _i - deprecated, unused
559: . o1 - a `PetscObject` associated with `e` (or `NULL`)
560: . o2 - a `PetscObject` associated with `e` (or `NULL`)
561: . o3 - a `PetscObject` associated with `e` (or `NULL`)
562: - o4 - a `PetscObject` associated with `e` (or `NULL`)

564:   Calling sequence of `PetscLogPHC`:
565: . o - a `PetscObject` that has just been created

567:   Calling sequence of `PetscLogPHD`:
568: . o - a `PetscObject` that is about to be destroyed

570:   Level: advanced

572:   Notes:
573:   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.

575:   This should help migrate external log handlers to use `PetscLogHandler`, but
576:   callbacks that depend on the deprecated `PetscLogStage` datatype will have to be
577:   updated.

579: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
580: @*/
581: PetscErrorCode PetscLogLegacyCallbacksBegin(PetscErrorCode (*PetscLogPLB)(PetscLogEvent e, int _i, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4), PetscErrorCode (*PetscLogPLE)(PetscLogEvent e, int _i, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4), PetscErrorCode (*PetscLogPHC)(PetscObject o), PetscErrorCode (*PetscLogPHD)(PetscObject o))
582: {
583:   PetscLogHandler handler;

585:   PetscFunctionBegin;
586:   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
587:   PetscCall(PetscLogHandlerStart(handler));
588:   PetscCall(PetscLogHandlerDestroy(&handler));
589:   PetscFunctionReturn(PETSC_SUCCESS);
590: }

592:   #if defined(PETSC_HAVE_MPE)
593:     #include <mpe.h>
594: static PetscBool PetscBeganMPE = PETSC_FALSE;
595:   #endif

597: /*@C
598:   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
599:   program down.

601:   Collective on `PETSC_COMM_WORLD`

603:   Options Database Key:
604: . -log_mpe - Prints extensive log information

606:   Level: advanced

608:   Note:
609:   A related routine is `PetscLogDefaultBegin()` (with the options key `-log_view`), which is
610:   intended for production runs since it logs only flop rates and object creation (and should
611:   not significantly slow the programs).

613: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
614:           `PetscLogEventDeactivate()`
615: @*/
616: PetscErrorCode PetscLogMPEBegin(void)
617: {
618:   PetscFunctionBegin;
619:   #if defined(PETSC_HAVE_MPE)
620:   /* Do MPE initialization */
621:   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
622:     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
623:     PetscCall(MPE_Init_log());

625:     PetscBeganMPE = PETSC_TRUE;
626:   } else {
627:     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
628:   }
629:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
630:   #else
631:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
632:   #endif
633:   PetscFunctionReturn(PETSC_SUCCESS);
634: }

636:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
637: #include <../src/sys/perfstubs/timer.h>
638:   #endif

640: /*@C
641:   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.

643:   Collective on `PETSC_COMM_WORLD`

645:   Options Database Key:
646: . -log_perfstubs - use an external log handler through the perfstubs interface

648:   Level: advanced

650: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
651: @*/
652: PetscErrorCode PetscLogPerfstubsBegin(void)
653: {
654:   PetscFunctionBegin;
655:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
656:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
657:   #else
658:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
659:   #endif
660:   PetscFunctionReturn(PETSC_SUCCESS);
661: }

663: /*@
664:   PetscLogActions - Determines whether actions are logged for the default log handler.

666:   Not Collective

668:   Input Parameter:
669: . flag - `PETSC_TRUE` if actions are to be logged

671:   Options Database Key:
672: + -log_exclude_actions - (deprecated) Does nothing
673: - -log_include_actions - Turn on action logging

675:   Level: intermediate

677:   Note:
678:   Logging of actions continues to consume more memory as the program
679:   runs. Long running programs should consider turning this feature off.

681: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
682: @*/
683: PetscErrorCode PetscLogActions(PetscBool flag)
684: {
685:   PetscFunctionBegin;
686:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
687:     PetscLogHandler h = PetscLogHandlers[i].handler;

689:     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
690:   }
691:   PetscFunctionReturn(PETSC_SUCCESS);
692: }

694: /*@
695:   PetscLogObjects - Determines whether objects are logged for the graphical viewer.

697:   Not Collective

699:   Input Parameter:
700: . flag - `PETSC_TRUE` if objects are to be logged

702:   Options Database Key:
703: + -log_exclude_objects - (deprecated) Does nothing
704: - -log_include_objects - Turns on object logging

706:   Level: intermediate

708:   Note:
709:   Logging of objects continues to consume more memory as the program
710:   runs. Long running programs should consider turning this feature off.

712: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
713: @*/
714: PetscErrorCode PetscLogObjects(PetscBool flag)
715: {
716:   PetscFunctionBegin;
717:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
718:     PetscLogHandler h = PetscLogHandlers[i].handler;

720:     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
721:   }
722:   PetscFunctionReturn(PETSC_SUCCESS);
723: }

725: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
726: /*@C
727:   PetscLogStageRegister - Attaches a character string name to a logging stage.

729:   Not Collective

731:   Input Parameter:
732: . sname - The name to associate with that stage

734:   Output Parameter:
735: . stage - The stage number or -1 if logging is not active (`PetscLogIsActive()`).

737:   Level: intermediate

739: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
740: @*/
741: PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
742: {
743:   PetscLogState state;

745:   PetscFunctionBegin;
746:   *stage = -1;
747:   PetscCall(PetscLogGetState(&state));
748:   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
749:   PetscFunctionReturn(PETSC_SUCCESS);
750: }

752: /*@C
753:   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage

755:   Not Collective

757:   Input Parameter:
758: . stage - The stage on which to log

760:   Example Usage:
761:   If the option -log_view is used to run the program containing the
762:   following code, then 2 sets of summary data will be printed during
763:   PetscFinalize().
764: .vb
765:       PetscInitialize(int *argc,char ***args,0,0);
766:       [stage 0 of code]
767:       PetscLogStagePush(1);
768:       [stage 1 of code]
769:       PetscLogStagePop();
770:       PetscBarrier(...);
771:       [more stage 0 of code]
772:       PetscFinalize();
773: .ve

775:   Level: intermediate

777:   Note:
778:   Use `PetscLogStageRegister()` to register a stage.

780: .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
781: @*/
782: PetscErrorCode PetscLogStagePush(PetscLogStage stage)
783: {
784:   PetscLogState state;

786:   PetscFunctionBegin;
787:   PetscCall(PetscLogGetState(&state));
788:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
789:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
790:     PetscLogHandler h = PetscLogHandlers[i].handler;
791:     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
792:   }
793:   PetscCall(PetscLogStateStagePush(state, stage));
794:   PetscFunctionReturn(PETSC_SUCCESS);
795: }

797: /*@C
798:   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`

800:   Not Collective

802:   Example Usage:
803:   If the option -log_view is used to run the program containing the
804:   following code, then 2 sets of summary data will be printed during
805:   PetscFinalize().
806: .vb
807:       PetscInitialize(int *argc,char ***args,0,0);
808:       [stage 0 of code]
809:       PetscLogStagePush(1);
810:       [stage 1 of code]
811:       PetscLogStagePop();
812:       PetscBarrier(...);
813:       [more stage 0 of code]
814:       PetscFinalize();
815: .ve

817:   Level: intermediate

819: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
820: @*/
821: PetscErrorCode PetscLogStagePop(void)
822: {
823:   PetscLogState state;
824:   PetscLogStage current_stage;

826:   PetscFunctionBegin;
827:   PetscCall(PetscLogGetState(&state));
828:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
829:   current_stage = state->current_stage;
830:   PetscCall(PetscLogStateStagePop(state));
831:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
832:     PetscLogHandler h = PetscLogHandlers[i].handler;
833:     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
834:   }
835:   PetscFunctionReturn(PETSC_SUCCESS);
836: }

838: /*@
839:   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.

841:   Not Collective

843:   Input Parameters:
844: + stage    - The stage
845: - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

847:   Level: intermediate

849:   Note:
850:   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist

852: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
853: @*/
854: PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
855: {
856:   PetscLogState state;

858:   PetscFunctionBegin;
859:   PetscCall(PetscLogGetState(&state));
860:   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
861:   PetscFunctionReturn(PETSC_SUCCESS);
862: }

864: /*@
865:   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.

867:   Not Collective

869:   Input Parameter:
870: . stage - The stage

872:   Output Parameter:
873: . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

875:   Level: intermediate

877: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
878: @*/
879: PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
880: {
881:   PetscLogState state;

883:   PetscFunctionBegin;
884:   *isActive = PETSC_FALSE;
885:   PetscCall(PetscLogGetState(&state));
886:   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
887:   PetscFunctionReturn(PETSC_SUCCESS);
888: }

890: /*@
891:   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`

893:   Not Collective

895:   Input Parameters:
896: + stage     - The stage
897: - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

899:   Level: intermediate

901:   Developer Notes:
902:   Visibility only affects the default log handler in `PetscLogView()`: stages that are
903:   set to invisible are suppressed from output.

905: .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
906: @*/
907: PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)

909: {
910:   PetscFunctionBegin;
911:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
912:     PetscLogHandler h = PetscLogHandlers[i].handler;

914:     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
915:   }
916:   PetscFunctionReturn(PETSC_SUCCESS);
917: }

919: /*@
920:   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`

922:   Not Collective

924:   Input Parameter:
925: . stage - The stage

927:   Output Parameter:
928: . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

930:   Level: intermediate

932: .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
933: @*/
934: PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
935: {
936:   PetscLogHandler handler;

938:   PetscFunctionBegin;
939:   *isVisible = PETSC_FALSE;
940:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
941:   if (handler) { PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible)); }
942:   PetscFunctionReturn(PETSC_SUCCESS);
943: }

945: /*@C
946:   PetscLogStageGetId - Returns the stage id when given the stage name.

948:   Not Collective

950:   Input Parameter:
951: . name - The stage name

953:   Output Parameter:
954: . stage - The stage, , or -1 if no stage with that name exists

956:   Level: intermediate

958: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
959: @*/
960: PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
961: {
962:   PetscLogState state;

964:   PetscFunctionBegin;
965:   *stage = -1;
966:   PetscCall(PetscLogGetState(&state));
967:   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
968:   PetscFunctionReturn(PETSC_SUCCESS);
969: }

971: /*@C
972:   PetscLogStageGetName - Returns the stage name when given the stage id.

974:   Not Collective

976:   Input Parameter:
977: . stage - The stage

979:   Output Parameter:
980: . name - The stage name

982:   Level: intermediate

984: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
985: @*/
986: PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char **name)
987: {
988:   PetscLogStageInfo stage_info;
989:   PetscLogState     state;

991:   PetscFunctionBegin;
992:   *name = NULL;
993:   PetscCall(PetscLogGetState(&state));
994:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
995:   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
996:   *name = stage_info.name;
997:   PetscFunctionReturn(PETSC_SUCCESS);
998: }

1000: /*------------------------------------------------ Event Functions --------------------------------------------------*/

1002: /*@C
1003:   PetscLogEventRegister - Registers an event name for logging operations

1005:   Not Collective

1007:   Input Parameters:
1008: + name    - The name associated with the event
1009: - classid - The classid associated to the class for this event, obtain either with
1010:            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
1011:            are only available in C code

1013:   Output Parameter:
1014: . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.

1016:   Example Usage:
1017: .vb
1018:       PetscLogEvent USER_EVENT;
1019:       PetscClassId classid;
1020:       PetscLogDouble user_event_flops;
1021:       PetscClassIdRegister("class name",&classid);
1022:       PetscLogEventRegister("User event name",classid,&USER_EVENT);
1023:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
1024:          [code segment to monitor]
1025:          PetscLogFlops(user_event_flops);
1026:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
1027: .ve

1029:   Level: intermediate

1031:   Notes:
1032:   PETSc automatically logs library events if the code has been
1033:   configured with --with-log (which is the default) and
1034:   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
1035:   intended for logging user events to supplement this PETSc
1036:   information.

1038:   PETSc can gather data for use with the utilities Jumpshot
1039:   (part of the MPICH distribution).  If PETSc has been compiled
1040:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
1041:   MPICH), the user can employ another command line option, -log_mpe,
1042:   to create a logfile, "mpe.log", which can be visualized
1043:   Jumpshot.

1045:   The classid is associated with each event so that classes of events
1046:   can be disabled simultaneously, such as all matrix events. The user
1047:   can either use an existing classid, such as `MAT_CLASSID`, or create
1048:   their own as shown in the example.

1050:   If an existing event with the same name exists, its event handle is
1051:   returned instead of creating a new event.

1053: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1054:           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1055: @*/
1056: PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1057: {
1058:   PetscLogState state;

1060:   PetscFunctionBegin;
1061:   *event = -1;
1062:   PetscCall(PetscLogGetState(&state));
1063:   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1064:   PetscFunctionReturn(PETSC_SUCCESS);
1065: }

1067: /*@
1068:   PetscLogEventSetCollective - Indicates that a particular event is collective.

1070:   Logically Collective

1072:   Input Parameters:
1073: + event      - The event id
1074: - collective - Boolean flag indicating whether a particular event is collective

1076:   Level: developer

1078:   Notes:
1079:   New events returned from `PetscLogEventRegister()` are collective by default.

1081:   Collective events are handled specially if the command line option -log_sync is used. In that case the logging saves information about
1082:   two parts of the event; the time for all the MPI ranks to synchronize and then the time for the actual computation/communication
1083:   to be performed. This option is useful to debug imbalance within the computations or communications.

1085: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1086: @*/
1087: PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1088: {
1089:   PetscLogState state;

1091:   PetscFunctionBegin;
1092:   PetscCall(PetscLogGetState(&state));
1093:   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1094:   PetscFunctionReturn(PETSC_SUCCESS);
1095: }

1097: /*
1098:   PetscLogClassSetActiveAll - Activate or inactivate logging for all events associated with a PETSc object class in every stage.

1100:   Not Collective

1102:   Input Parameters:
1103: + classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1104: - isActive - if `PETSC_FALSE`, events associated with this class will not be send to log handlers.

1106:   Level: developer

1108: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1109: */
1110: static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1111: {
1112:   PetscLogState state;

1114:   PetscFunctionBegin;
1115:   PetscCall(PetscLogGetState(&state));
1116:   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1117:   PetscFunctionReturn(PETSC_SUCCESS);
1118: }

1120: /*@
1121:   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.

1123:   Not Collective

1125:   Input Parameter:
1126: . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

1128:   Level: developer

1130: .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1131: @*/
1132: PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1133: {
1134:   PetscFunctionBegin;
1135:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
1136:   PetscFunctionReturn(PETSC_SUCCESS);
1137: }

1139: /*@
1140:   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.

1142:   Not Collective

1144:   Input Parameter:
1145: . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

1147:   Level: developer

1149:   Note:
1150:   If a class is excluded then events associated with that class are not logged.

1152: .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1153: @*/
1154: PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1155: {
1156:   PetscFunctionBegin;
1157:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
1158:   PetscFunctionReturn(PETSC_SUCCESS);
1159: }

1161: /*
1162:   PetscLogEventSetActive - Activate or inactivate logging for an event in a given stage

1164:   Not Collective

1166:   Input Parameters:
1167: + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1168: . event - A `PetscLogEvent`
1169: - isActive - If `PETSC_FALSE`, activity from this event (`PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventSync()`) will not be sent to log handlers during this stage

1171:   Usage:
1172: .vb
1173:       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
1174:         [code where you do not want to log VecSetValues()]
1175:       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
1176:         [code where you do want to log VecSetValues()]
1177: .ve

1179:   Level: advanced

1181:   Note:
1182:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1183:   or an event number obtained with `PetscLogEventRegister()`.

1185: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1186: */
1187: static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1188: {
1189:   PetscLogState state;

1191:   PetscFunctionBegin;
1192:   PetscCall(PetscLogGetState(&state));
1193:   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1194:   PetscFunctionReturn(PETSC_SUCCESS);
1195: }

1197: /*@
1198:   PetscLogEventActivate - Indicates that a particular event should be logged.

1200:   Not Collective

1202:   Input Parameter:
1203: . event - The event id

1205:   Example Usage:
1206: .vb
1207:       PetscLogEventDeactivate(VEC_SetValues);
1208:         [code where you do not want to log VecSetValues()]
1209:       PetscLogEventActivate(VEC_SetValues);
1210:         [code where you do want to log VecSetValues()]
1211: .ve

1213:   Level: advanced

1215:   Note:
1216:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1217:   or an event number obtained with `PetscLogEventRegister()`.

1219: .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1220: @*/
1221: PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1222: {
1223:   PetscFunctionBegin;
1224:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
1225:   PetscFunctionReturn(PETSC_SUCCESS);
1226: }

1228: /*@
1229:   PetscLogEventDeactivate - Indicates that a particular event should not be logged.

1231:   Not Collective

1233:   Input Parameter:
1234: . event - The event id

1236:   Example Usage:
1237: .vb
1238:       PetscLogEventDeactivate(VEC_SetValues);
1239:         [code where you do not want to log VecSetValues()]
1240:       PetscLogEventActivate(VEC_SetValues);
1241:         [code where you do want to log VecSetValues()]
1242: .ve

1244:   Level: advanced

1246:   Note:
1247:   The event may be either a pre-defined PETSc event (found in
1248:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

1250: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1251: @*/
1252: PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1253: {
1254:   PetscFunctionBegin;
1255:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
1256:   PetscFunctionReturn(PETSC_SUCCESS);
1257: }

1259: /*@
1260:   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called

1262:   Not Collective

1264:   Input Parameter:
1265: . event - The event id

1267:   Example Usage:
1268: .vb
1269:       PetscLogEventDeactivatePush(VEC_SetValues);
1270:         [code where you do not want to log VecSetValues()]
1271:       PetscLogEventDeactivatePop(VEC_SetValues);
1272:         [code where you do want to log VecSetValues()]
1273: .ve

1275:   Level: advanced

1277:   Note:
1278:   The event may be either a pre-defined PETSc event (found in
1279:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

1281:   PETSc's default log handler (`PetscLogDefaultBegin()`) respects this function because it can make the output of `PetscLogView()` easier to interpret, but other handlers (such as the nested handler, `PetscLogNestedBegin()`) ignore it because suppressing events is not helpful in their output formats.

1283: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePop()`
1284: @*/
1285: PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
1286: {
1287:   PetscFunctionBegin;
1288:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1289:     PetscLogHandler h = PetscLogHandlers[i].handler;

1291:     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1292:   }
1293:   PetscFunctionReturn(PETSC_SUCCESS);
1294: }

1296: /*@
1297:   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`

1299:   Not Collective

1301:   Input Parameter:
1302: . event - The event id

1304:   Example Usage:
1305: .vb
1306:       PetscLogEventDeactivatePush(VEC_SetValues);
1307:         [code where you do not want to log VecSetValues()]
1308:       PetscLogEventDeactivatePop(VEC_SetValues);
1309:         [code where you do want to log VecSetValues()]
1310: .ve

1312:   Level: advanced

1314:   Note:
1315:   The event may be either a pre-defined PETSc event (found in
1316:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

1318: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1319: @*/
1320: PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1321: {
1322:   PetscFunctionBegin;
1323:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1324:     PetscLogHandler h = PetscLogHandlers[i].handler;

1326:     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1327:   }
1328:   PetscFunctionReturn(PETSC_SUCCESS);
1329: }

1331: /*@
1332:   PetscLogEventSetActiveAll - Turns on logging of all events

1334:   Not Collective

1336:   Input Parameters:
1337: + event    - The event id
1338: - isActive - The activity flag determining whether the event is logged

1340:   Level: advanced

1342: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1343: @*/
1344: PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1345: {
1346:   PetscLogState state;

1348:   PetscFunctionBegin;
1349:   PetscCall(PetscLogGetState(&state));
1350:   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1351:   PetscFunctionReturn(PETSC_SUCCESS);
1352: }

1354: /*
1355:   PetscLogClassSetActive - Activates event logging for a PETSc object class for the current stage

1357:   Not Collective

1359:   Input Parameters:
1360: + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1361: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1362: - isActive - If `PETSC_FALSE`, events associated with this class are not sent to log handlers.

1364:   Level: developer

1366: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1367: */
1368: static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1369: {
1370:   PetscLogState state;

1372:   PetscFunctionBegin;
1373:   PetscCall(PetscLogGetState(&state));
1374:   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1375:   PetscFunctionReturn(PETSC_SUCCESS);
1376: }

1378: /*@
1379:   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage

1381:   Not Collective

1383:   Input Parameter:
1384: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

1386:   Level: developer

1388: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1389: @*/
1390: PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1391: {
1392:   PetscFunctionBegin;
1393:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
1394:   PetscFunctionReturn(PETSC_SUCCESS);
1395: }

1397: /*@
1398:   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage

1400:   Not Collective

1402:   Input Parameter:
1403: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

1405:   Level: developer

1407: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1408: @*/
1409: PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1410: {
1411:   PetscFunctionBegin;
1412:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
1413:   PetscFunctionReturn(PETSC_SUCCESS);
1414: }

1416: /*MC
1417:   PetscLogEventSync - Synchronizes the beginning of a user event.

1419:   Synopsis:
1420: #include <petsclog.h>
1421:   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)

1423:   Collective

1425:   Input Parameters:
1426: + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1427: - comm - an MPI communicator

1429:   Example Usage:
1430: .vb
1431:   PetscLogEvent USER_EVENT;

1433:   PetscLogEventRegister("User event", 0, &USER_EVENT);
1434:   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1435:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1436:   [code segment to monitor]
1437:   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1438: .ve

1440:   Level: developer

1442:   Note:
1443:   This routine should be called only if there is not a `PetscObject` available to pass to
1444:   `PetscLogEventBegin()`.

1446: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1447: M*/

1449: /*MC
1450:   PetscLogEventBegin - Logs the beginning of a user event.

1452:   Synopsis:
1453: #include <petsclog.h>
1454:   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

1456:   Not Collective

1458:   Input Parameters:
1459: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1460: . o1 - object associated with the event, or `NULL`
1461: . o2 - object associated with the event, or `NULL`
1462: . o3 - object associated with the event, or `NULL`
1463: - o4 - object associated with the event, or `NULL`

1465:   Fortran Synopsis:
1466:   void PetscLogEventBegin(int e, PetscErrorCode ierr)

1468:   Example Usage:
1469: .vb
1470:   PetscLogEvent USER_EVENT;

1472:   PetscLogDouble user_event_flops;
1473:   PetscLogEventRegister("User event",0, &USER_EVENT);
1474:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1475:   [code segment to monitor]
1476:   PetscLogFlops(user_event_flops);
1477:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1478: .ve

1480:   Level: intermediate

1482:   Developer Note:
1483:   `PetscLogEventBegin()` and `PetscLogEventBegin()` return error codes instead of explicitly
1484:   handling the errors that occur in the macro directly because other packages that use this
1485:   macros have used them in their own functions or methods that do not return error codes and it
1486:   would be disruptive to change the current behavior.

1488: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
1489: M*/

1491: /*MC
1492:   PetscLogEventEnd - Log the end of a user event.

1494:   Synopsis:
1495: #include <petsclog.h>
1496:   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

1498:   Not Collective

1500:   Input Parameters:
1501: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1502: . o1 - object associated with the event, or `NULL`
1503: . o2 - object associated with the event, or `NULL`
1504: . o3 - object associated with the event, or `NULL`
1505: - o4 - object associated with the event, or `NULL`

1507:   Fortran Synopsis:
1508:   void PetscLogEventEnd(int e, PetscErrorCode ierr)

1510:   Example Usage:
1511: .vb
1512:   PetscLogEvent USER_EVENT;

1514:   PetscLogDouble user_event_flops;
1515:   PetscLogEventRegister("User event", 0, &USER_EVENT);
1516:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1517:   [code segment to monitor]
1518:   PetscLogFlops(user_event_flops);
1519:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1520: .ve

1522:   Level: intermediate

1524: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
1525: M*/

1527: /*@C
1528:   PetscLogStageGetPerfInfo - Return the performance information about the given stage

1530:   Input Parameters:
1531: . stage - The stage number or `PETSC_DETERMINE` for the current stage

1533:   Output Parameter:
1534: . info - This structure is filled with the performance information

1536:   Level: intermediate

1538:   Notes:
1539:   This is a low level routine used by the logging functions in PETSc.

1541:   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1542:   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1543:   all performance statistics in `info` will be zeroed.

1545: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1546: @*/
1547: PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
1548: {
1549:   PetscLogHandler     handler;
1550:   PetscEventPerfInfo *event_info;

1552:   PetscFunctionBegin;
1553:   PetscAssertPointer(info, 2);
1554:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1555:   if (handler) {
1556:     PetscCall(PetscLogHandlerGetStagePerfInfo(handler, stage, &event_info));
1557:     *info = *event_info;
1558:   } else {
1559:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogStageGetPerfInfo() returning zeros\n"));
1560:     PetscCall(PetscMemzero(info, sizeof(*info)));
1561:   }
1562:   PetscFunctionReturn(PETSC_SUCCESS);
1563: }

1565: /*@C
1566:   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage

1568:   Input Parameters:
1569: + stage - The stage number or `PETSC_DETERMINE` for the current stage
1570: - event - The event number

1572:   Output Parameter:
1573: . info - This structure is filled with the performance information

1575:   Level: intermediate

1577:   Note:
1578:   This is a low level routine used by the logging functions in PETSc

1580:   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1581:   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1582:   all performance statistics in `info` will be zeroed.

1584: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1585: @*/
1586: PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
1587: {
1588:   PetscLogHandler     handler;
1589:   PetscEventPerfInfo *event_info;

1591:   PetscFunctionBegin;
1592:   PetscAssertPointer(info, 3);
1593:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1594:   if (handler) {
1595:     PetscCall(PetscLogHandlerGetEventPerfInfo(handler, stage, event, &event_info));
1596:     *info = *event_info;
1597:   } else {
1598:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogEventGetPerfInfo() returning zeros\n"));
1599:     PetscCall(PetscMemzero(info, sizeof(*info)));
1600:   }
1601:   PetscFunctionReturn(PETSC_SUCCESS);
1602: }

1604: /*@C
1605:   PetscLogEventSetDof - Set the nth number of degrees of freedom of a numerical problem associated with this event

1607:   Not Collective

1609:   Input Parameters:
1610: + event - The event id to log
1611: . n     - The dof index, in [0, 8)
1612: - dof   - The number of dofs

1614:   Options Database Key:
1615: . -log_view - Activates log summary

1617:   Level: developer

1619:   Note:
1620:   This is to enable logging of convergence

1622: .seealso: `PetscLogEventSetError()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1623: @*/
1624: PetscErrorCode PetscLogEventSetDof(PetscLogEvent event, PetscInt n, PetscLogDouble dof)
1625: {
1626:   PetscFunctionBegin;
1627:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1628:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1629:     PetscLogHandler h = PetscLogHandlers[i].handler;

1631:     if (h) {
1632:       PetscEventPerfInfo *event_info;

1634:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1635:       if (event_info) event_info->dof[n] = dof;
1636:     }
1637:   }
1638:   PetscFunctionReturn(PETSC_SUCCESS);
1639: }

1641: /*@C
1642:   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event

1644:   Not Collective

1646:   Input Parameters:
1647: + event - The event id to log
1648: . n     - The error index, in [0, 8)
1649: - error - The error

1651:   Options Database Key:
1652: . -log_view - Activates log summary

1654:   Level: developer

1656:   Notes:
1657:   This is to enable logging of convergence, and enable users to interpret the errors as they wish. For example,
1658:   as different norms, or as errors for different fields

1660:   This is a low level routine used by the logging functions in PETSc

1662: .seealso: `PetscLogEventSetDof()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1663: @*/
1664: PetscErrorCode PetscLogEventSetError(PetscLogEvent event, PetscInt n, PetscLogDouble error)
1665: {
1666:   PetscFunctionBegin;
1667:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1668:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1669:     PetscLogHandler h = PetscLogHandlers[i].handler;

1671:     if (h) {
1672:       PetscEventPerfInfo *event_info;

1674:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1675:       if (event_info) event_info->errors[n] = error;
1676:     }
1677:   }
1678:   PetscFunctionReturn(PETSC_SUCCESS);
1679: }

1681: /*@C
1682:   PetscLogEventGetId - Returns the event id when given the event name.

1684:   Not Collective

1686:   Input Parameter:
1687: . name - The event name

1689:   Output Parameter:
1690: . event - The event, or -1 if no event with that name exists

1692:   Level: intermediate

1694: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1695: @*/
1696: PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1697: {
1698:   PetscLogState state;

1700:   PetscFunctionBegin;
1701:   *event = -1;
1702:   PetscCall(PetscLogGetState(&state));
1703:   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1704:   PetscFunctionReturn(PETSC_SUCCESS);
1705: }

1707: /*@C
1708:   PetscLogEventGetName - Returns the event name when given the event id.

1710:   Not Collective

1712:   Input Parameter:
1713: . event - The event

1715:   Output Parameter:
1716: . name - The event name

1718:   Level: intermediate

1720: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
1721: @*/
1722: PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char **name)
1723: {
1724:   PetscLogEventInfo event_info;
1725:   PetscLogState     state;

1727:   PetscFunctionBegin;
1728:   *name = NULL;
1729:   PetscCall(PetscLogGetState(&state));
1730:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1731:   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1732:   *name = event_info.name;
1733:   PetscFunctionReturn(PETSC_SUCCESS);
1734: }

1736: /*@
1737:   PetscLogEventsPause - Put event logging into "paused" mode: timers and counters for in-progress events are paused, and any events that happen before logging is resumed with `PetscLogEventsResume()` are logged in the "Main Stage" of execution.

1739:   Not collective

1741:   Level: advanced

1743:   Notes:
1744:   When an external library or runtime has is initialized it can involve lots of setup time that skews the statistics of any unrelated running events: this function is intended to isolate such calls in the default log summary (`PetscLogDefaultBegin()`, `PetscLogView()`).

1746:   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.

1748: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
1749: @*/
1750: PetscErrorCode PetscLogEventsPause(void)
1751: {
1752:   PetscFunctionBegin;
1753:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1754:     PetscLogHandler h = PetscLogHandlers[i].handler;

1756:     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1757:   }
1758:   PetscFunctionReturn(PETSC_SUCCESS);
1759: }

1761: /*@
1762:   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.

1764:   Not collective

1766:   Level: advanced

1768: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
1769: @*/
1770: PetscErrorCode PetscLogEventsResume(void)
1771: {
1772:   PetscFunctionBegin;
1773:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1774:     PetscLogHandler h = PetscLogHandlers[i].handler;

1776:     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1777:   }
1778:   PetscFunctionReturn(PETSC_SUCCESS);
1779: }

1781: /*------------------------------------------------ Class Functions --------------------------------------------------*/

1783: /*MC
1784:    PetscLogObjectCreate - Log the creation of a `PetscObject`

1786:    Synopsis:
1787: #include <petsclog.h>
1788:    PetscErrorCode PetscLogObjectCreate(PetscObject h)

1790:    Not Collective

1792:    Input Parameters:
1793: .  h - A `PetscObject`

1795:    Level: developer

1797:    Developer Note:
1798:      Called internally by PETSc when creating objects: users do not need to call this directly.
1799:      Notification of the object creation is sent to each `PetscLogHandler` that is running.

1801: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1802: M*/

1804: /*MC
1805:    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`

1807:    Synopsis:
1808: #include <petsclog.h>
1809:    PetscErrorCode PetscLogObjectDestroy(PetscObject h)

1811:    Not Collective

1813:    Input Parameters:
1814: .  h - A `PetscObject`

1816:    Level: developer

1818:    Developer Note:
1819:      Called internally by PETSc when destroying objects: users do not need to call this directly.
1820:      Notification of the object creation is sent to each `PetscLogHandler` that is running.

1822: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1823: M*/

1825: /*@C
1826:   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.

1828:   Not Collective

1830:   Input Parameter:
1831: . name - The class name

1833:   Output Parameter:
1834: . classid - The `PetscClassId` id, or -1 if no class with that name exists

1836:   Level: intermediate

1838: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1839: @*/
1840: PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1841: {
1842:   PetscLogClass     log_class;
1843:   PetscLogClassInfo class_info;
1844:   PetscLogState     state;

1846:   PetscFunctionBegin;
1847:   *classid = -1;
1848:   PetscCall(PetscLogGetState(&state));
1849:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1850:   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1851:   if (log_class < 0) {
1852:     *classid = -1;
1853:     PetscFunctionReturn(PETSC_SUCCESS);
1854:   }
1855:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1856:   *classid = class_info.classid;
1857:   PetscFunctionReturn(PETSC_SUCCESS);
1858: }

1860: /*@C
1861:   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.

1863:   Not Collective

1865:   Input Parameter:
1866: . classid - A `PetscClassId`

1868:   Output Parameter:
1869: . name - The class name

1871:   Level: intermediate

1873: .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
1874: @*/
1875: PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
1876: {
1877:   PetscLogClass     log_class;
1878:   PetscLogClassInfo class_info;
1879:   PetscLogState     state;

1881:   PetscFunctionBegin;
1882:   PetscCall(PetscLogGetState(&state));
1883:   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1884:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1885:   *name = class_info.name;
1886:   PetscFunctionReturn(PETSC_SUCCESS);
1887: }

1889: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1890: /*@C
1891:   PetscLogDump - Dumps logs of objects to a file. This file is intended to
1892:   be read by bin/petscview. This program no longer exists.

1894:   Collective on `PETSC_COMM_WORLD`

1896:   Input Parameter:
1897: . sname - an optional file name

1899:   Example Usage:
1900: .vb
1901:   PetscInitialize(...);
1902:   PetscLogDefaultBegin();
1903:   // ... code ...
1904:   PetscLogDump(filename);
1905:   PetscFinalize();
1906: .ve

1908:   Level: advanced

1910:   Note:
1911:   The default file name is Log.<rank> where <rank> is the MPI process rank. If no name is specified,
1912:   this file will be used.

1914: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1915: @*/
1916: PetscErrorCode PetscLogDump(const char sname[])
1917: {
1918:   PetscLogHandler handler;

1920:   PetscFunctionBegin;
1921:   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1922:   PetscCall(PetscLogHandlerDump(handler, sname));
1923:   PetscFunctionReturn(PETSC_SUCCESS);
1924: }

1926: /*@C
1927:   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.

1929:   Collective on `PETSC_COMM_WORLD`

1931:   Input Parameter:
1932: . sname - filename for the MPE logfile

1934:   Level: advanced

1936: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
1937: @*/
1938: PetscErrorCode PetscLogMPEDump(const char sname[])
1939: {
1940:   PetscFunctionBegin;
1941:   #if defined(PETSC_HAVE_MPE)
1942:   if (PetscBeganMPE) {
1943:     char name[PETSC_MAX_PATH_LEN];

1945:     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
1946:     if (sname) {
1947:       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
1948:     } else {
1949:       PetscCall(PetscGetProgramName(name, sizeof(name)));
1950:     }
1951:     PetscCall(MPE_Finish_log(name));
1952:   } else {
1953:     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
1954:   }
1955:   #else
1956:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
1957:   #endif
1958:   PetscFunctionReturn(PETSC_SUCCESS);
1959: }

1961: /*@C
1962:   PetscLogView - Prints a summary of the logging.

1964:   Collective

1966:   Input Parameter:
1967: . viewer - an ASCII viewer

1969:   Options Database Keys:
1970: + -log_view [:filename]                    - Prints summary of log information
1971: . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
1972: . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
1973: . -log_view :filename.txt:ascii_flamegraph - Saves logging information in a format suitable for visualising as a Flame Graph (see below for how to view it)
1974: . -log_view_memory                         - Also display memory usage in each event
1975: . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
1976: . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
1977: - -log_trace [filename]                    - Displays a trace of what each process is doing

1979:   Level: beginner

1981:   Notes:
1982:   It is possible to control the logging programmatically but we recommend using the options database approach whenever possible
1983:   By default the summary is printed to stdout.

1985:   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()

1987:   If PETSc is configured with --with-logging=0 then this functionality is not available

1989:   To view the nested XML format filename.xml first copy  ${PETSC_DIR}/share/petsc/xml/performance_xml2html.xsl to the current
1990:   directory then open filename.xml with your browser. Specific notes for certain browsers
1991: .vb
1992:     Firefox and Internet explorer - simply open the file
1993:     Google Chrome - you must start up Chrome with the option --allow-file-access-from-files
1994:     Safari - see https://ccm.net/faq/36342-safari-how-to-enable-local-file-access
1995: .ve
1996:   or one can use the package <http://xmlsoft.org/XSLT/xsltproc2.html> to translate the xml file to html and then open it with
1997:   your browser.
1998:   Alternatively, use the script ${PETSC_DIR}/lib/petsc/bin/petsc-performance-view to automatically open a new browser
1999:   window and render the XML log file contents.

2001:   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS

2003:   The Flame Graph output can be visualised using either the original Flame Graph script <https://github.com/brendangregg/FlameGraph>
2004:   or using speedscope <https://www.speedscope.app>.
2005:   Old XML profiles may be converted into this format using the script ${PETSC_DIR}/lib/petsc/bin/xml2flamegraph.py.

2007: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2008: @*/
2009: PetscErrorCode PetscLogView(PetscViewer viewer)
2010: {
2011:   PetscBool         isascii;
2012:   PetscViewerFormat format;
2013:   int               stage;
2014:   PetscLogState     state;
2015:   PetscIntStack     temp_stack;
2016:   PetscLogHandler   handler;
2017:   PetscBool         is_empty;

2019:   PetscFunctionBegin;
2020:   PetscCall(PetscLogGetState(&state));
2021:   /* Pop off any stages the user forgot to remove */
2022:   PetscCall(PetscIntStackCreate(&temp_stack));
2023:   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2024:   while (stage >= 0) {
2025:     PetscCall(PetscLogStagePop());
2026:     PetscCall(PetscIntStackPush(temp_stack, stage));
2027:     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2028:   }
2029:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2030:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2031:   PetscCall(PetscViewerGetFormat(viewer, &format));
2032:   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2033:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
2034:     PetscCall(PetscLogHandlerView(handler, viewer));
2035:   } else {
2036:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
2037:     PetscCall(PetscLogHandlerView(handler, viewer));
2038:   }
2039:   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2040:   while (!is_empty) {
2041:     PetscCall(PetscIntStackPop(temp_stack, &stage));
2042:     PetscCall(PetscLogStagePush(stage));
2043:     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2044:   }
2045:   PetscCall(PetscIntStackDestroy(temp_stack));
2046:   PetscFunctionReturn(PETSC_SUCCESS);
2047: }

2049: /*@C
2050:   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.

2052:   Collective on `PETSC_COMM_WORLD`

2054:   Level: developer

2056: .seealso: [](ch_profiling), `PetscLogView()`
2057: @*/
2058: PetscErrorCode PetscLogViewFromOptions(void)
2059: {
2060:   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
2061:   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2062:   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2063:   PetscBool         flg;

2065:   PetscFunctionBegin;
2066:   PetscCall(PetscOptionsGetViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
2067:   for (PetscInt i = 0; i < n_max; i++) {
2068:     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
2069:     PetscCall(PetscLogView(viewers[i]));
2070:     PetscCall(PetscViewerPopFormat(viewers[i]));
2071:     PetscCall(PetscOptionsRestoreViewer(&viewers[i]));
2072:   }
2073:   PetscFunctionReturn(PETSC_SUCCESS);
2074: }

2076: PETSC_INTERN PetscErrorCode PetscLogHandlerNestedSetThreshold(PetscLogHandler, PetscLogDouble, PetscLogDouble *);

2078: /*@
2079:   PetscLogSetThreshold - Set the threshold time for logging the events; this is a percentage out of 100, so 1. means any event
2080:   that takes 1 or more percent of the time.

2082:   Logically Collective on `PETSC_COMM_WORLD`

2084:   Input Parameter:
2085: . newThresh - the threshold to use

2087:   Output Parameter:
2088: . oldThresh - the previously set threshold value

2090:   Options Database Keys:
2091: . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file

2093:   Example Usage:
2094: .vb
2095:   PetscInitialize(...);
2096:   PetscLogNestedBegin();
2097:   PetscLogSetThreshold(0.1,&oldthresh);
2098:   // ... code ...
2099:   PetscLogView(viewer);
2100:   PetscFinalize();
2101: .ve

2103:   Level: advanced

2105:   Note:
2106:   This threshold is only used by the nested log handler

2108: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
2109:           `PetscLogNestedBegin()`
2110: @*/
2111: PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
2112: {
2113:   PetscLogHandler handler;

2115:   PetscFunctionBegin;
2116:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
2117:   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
2118:   PetscFunctionReturn(PETSC_SUCCESS);
2119: }

2121: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2122: /*@C
2123:   PetscGetFlops - Returns the number of flops used on this processor
2124:   since the program began.

2126:   Not Collective

2128:   Output Parameter:
2129: . flops - number of floating point operations

2131:   Level: intermediate

2133:   Notes:
2134:   A global counter logs all PETSc flop counts.  The user can use
2135:   `PetscLogFlops()` to increment this counter to include flops for the
2136:   application code.

2138:   A separate counter `PetscLogGpuFlops()` logs the flops that occur on any GPU associated with this MPI rank

2140: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscTime()`, `PetscLogFlops()`
2141: @*/
2142: PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
2143: {
2144:   PetscFunctionBegin;
2145:   *flops = petsc_TotalFlops;
2146:   PetscFunctionReturn(PETSC_SUCCESS);
2147: }

2149: /*@C
2150:   PetscLogObjectState - Record information about an object with the default log handler

2152:   Not Collective

2154:   Input Parameters:
2155: + obj    - the `PetscObject`
2156: . format - a printf-style format string
2157: - ...    - printf arguments to format

2159:   Level: developer

2161: .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`, `PetscLogGetDefaultHandler()`
2162: @*/
2163: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
2164: {
2165:   PetscFunctionBegin;
2166:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2167:     PetscLogHandler h = PetscLogHandlers[i].handler;

2169:     if (h) {
2170:       va_list Argp;
2171:       va_start(Argp, format);
2172:       PetscCall(PetscLogHandlerLogObjectState_Internal(h, obj, format, Argp));
2173:       va_end(Argp);
2174:     }
2175:   }
2176:   PetscFunctionReturn(PETSC_SUCCESS);
2177: }

2179: /*MC
2180:   PetscLogFlops - Adds floating point operations to the global counter.

2182:   Synopsis:
2183: #include <petsclog.h>
2184:   PetscErrorCode PetscLogFlops(PetscLogDouble f)

2186:   Not Collective

2188:   Input Parameter:
2189: . f - flop counter

2191:   Example Usage:
2192: .vb
2193:   PetscLogEvent USER_EVENT;

2195:   PetscLogEventRegister("User event", 0, &USER_EVENT);
2196:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
2197:   [code segment to monitor]
2198:   PetscLogFlops(user_flops)
2199:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
2200: .ve

2202:   Level: intermediate

2204:   Note:
2205:    A global counter logs all PETSc flop counts. The user can use PetscLogFlops() to increment
2206:    this counter to include flops for the application code.

2208: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscGetFlops()`
2209: M*/

2211: /*MC
2212:   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
2213:   timings

2215:   Synopsis:
2216: #include <petsclog.h>
2217:   void PetscPreLoadBegin(PetscBool flag, char *name);

2219:   Not Collective

2221:   Input Parameters:
2222: + flag - `PETSC_TRUE` to run twice, `PETSC_FALSE` to run once, may be overridden with command
2223:          line option `-preload true|false`
2224: - name - name of first stage (lines of code timed separately with `-log_view`) to be preloaded

2226:   Example Usage:
2227: .vb
2228:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2229:   // lines of code
2230:   PetscPreLoadStage("second stage");
2231:   // lines of code
2232:   PetscPreLoadEnd();
2233: .ve

2235:   Level: intermediate

2237:   Note:
2238:   Only works in C/C++, not Fortran

2240:   Flags available within the macro\:
2241: + PetscPreLoadingUsed - `PETSC_TRUE` if we are or have done preloading
2242: . PetscPreLoadingOn   - `PETSC_TRUE` if it is CURRENTLY doing preload
2243: . PetscPreLoadIt      - `0` for the first computation (with preloading turned off it is only
2244:                         `0`) `1`  for the second
2245: - PetscPreLoadMax     - number of times it will do the computation, only one when preloading is
2246:                         turned on

2248:   The first two variables are available throughout the program, the second two only between the
2249:   `PetscPreLoadBegin()` and `PetscPreLoadEnd()`

2251: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
2252: M*/

2254: /*MC
2255:   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
2256:   timings

2258:   Synopsis:
2259: #include <petsclog.h>
2260:   void PetscPreLoadEnd(void);

2262:   Not Collective

2264:   Example Usage:
2265: .vb
2266:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2267:   // lines of code
2268:   PetscPreLoadStage("second stage");
2269:   // lines of code
2270:   PetscPreLoadEnd();
2271: .ve

2273:   Level: intermediate

2275:   Note:
2276:   Only works in C/C++ not Fortran

2278: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadStage()`
2279: M*/

2281: /*MC
2282:   PetscPreLoadStage - Start a new segment of code to be timed separately to get accurate timings

2284:   Synopsis:
2285: #include <petsclog.h>
2286:   void PetscPreLoadStage(char *name);

2288:   Not Collective

2290:   Example Usage:
2291: .vb
2292:   PetscPreLoadBegin(PETSC_TRUE,"first stage");
2293:   // lines of code
2294:   PetscPreLoadStage("second stage");
2295:   // lines of code
2296:   PetscPreLoadEnd();
2297: .ve

2299:   Level: intermediate

2301:   Note:
2302:   Only works in C/C++ not Fortran

2304: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`
2305: M*/

2307:   #if PetscDefined(HAVE_DEVICE)
2308: #include <petsc/private/deviceimpl.h>

2310: /*@C
2311:   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels

2313:   Options Database Key:
2314: . -log_view_gpu_time - provide the GPU times for all events in the `-log_view` output

2316:   Level: advanced

2318:   Notes:
2319:   Turning on the timing of the GPU kernels can slow down the entire computation and should only
2320:   be used when studying the performance of individual operations on GPU such as vector operations and
2321:   matrix-vector operations.

2323:   If this option is not used then times for most of the events in the `-log_view` output will be listed as Nan, indicating the times are not available

2325:   This routine should only be called once near the beginning of the program. Once it is started
2326:   it cannot be turned off.

2328: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
2329: @*/
2330: PetscErrorCode PetscLogGpuTime(void)
2331: {
2332:   PetscFunctionBegin;
2333:   PetscCheck(petsc_gtime == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU logging has already been turned on");
2334:   PetscLogGpuTimeFlag = PETSC_TRUE;
2335:   PetscFunctionReturn(PETSC_SUCCESS);
2336: }

2338: /*@C
2339:   PetscLogGpuTimeBegin - Start timer for device

2341:   Level: intermediate

2343:   Notes:
2344:   When CUDA or HIP is enabled, the timer is run on the GPU, it is a separate logging of time
2345:   devoted to GPU computations (excluding kernel launch times).

2347:   When CUDA or HIP is not available, the timer is run on the CPU, it is a separate logging of
2348:   time devoted to GPU computations (including kernel launch times).

2350:   There is no need to call WaitForCUDA() or WaitForHIP() between `PetscLogGpuTimeBegin()` and
2351:   `PetscLogGpuTimeEnd()`

2353:   This timer should NOT include times for data transfers between the GPU and CPU, nor setup
2354:   actions such as allocating space.

2356:   The regular logging captures the time for data transfers and any CPU activities during the
2357:   event. It is used to compute the flop rate on the GPU as it is actively engaged in running a
2358:   kernel.

2360:   Developer Notes:
2361:   The GPU event timer captures the execution time of all the kernels launched in the default
2362:   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()`.

2364:   `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()` insert the begin and end events into the
2365:   default stream (stream 0). The device will record a time stamp for the event when it reaches
2366:   that event in the stream. The function xxxEventSynchronize() is called in
2367:   `PetsLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
2368:   timer event is recorded.

2370: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2371: @*/
2372: PetscErrorCode PetscLogGpuTimeBegin(void)
2373: {
2374:   PetscBool isActive;

2376:   PetscFunctionBegin;
2377:   PetscCall(PetscLogEventBeginIsActive(&isActive));
2378:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2379:   if (PetscDefined(HAVE_DEVICE)) {
2380:     PetscDeviceContext dctx;

2382:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2383:     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2384:   } else {
2385:     PetscCall(PetscTimeSubtract(&petsc_gtime));
2386:   }
2387:   PetscFunctionReturn(PETSC_SUCCESS);
2388: }

2390: /*@C
2391:   PetscLogGpuTimeEnd - Stop timer for device

2393:   Level: intermediate

2395: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2396: @*/
2397: PetscErrorCode PetscLogGpuTimeEnd(void)
2398: {
2399:   PetscBool isActive;

2401:   PetscFunctionBegin;
2402:   PetscCall(PetscLogEventEndIsActive(&isActive));
2403:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2404:   if (PetscDefined(HAVE_DEVICE)) {
2405:     PetscDeviceContext dctx;
2406:     PetscLogDouble     elapsed;

2408:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2409:     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
2410:     petsc_gtime += (elapsed / 1000.0);
2411:   } else {
2412:     PetscCall(PetscTimeAdd(&petsc_gtime));
2413:   }
2414:   PetscFunctionReturn(PETSC_SUCCESS);
2415: }

2417:   #endif /* end of PETSC_HAVE_DEVICE */

2419: #endif /* PETSC_USE_LOG*/

2421: /* -- Utility functions for logging from Fortran -- */

2423: PETSC_EXTERN PetscErrorCode PetscASend(int count, int datatype)
2424: {
2425:   PetscFunctionBegin;
2426: #if PetscDefined(USE_LOG)
2427:   PetscCall(PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1));
2428:   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2429:   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_send_len, &petsc_send_len_th));
2430:   #endif
2431: #endif
2432:   PetscFunctionReturn(PETSC_SUCCESS);
2433: }

2435: PETSC_EXTERN PetscErrorCode PetscARecv(int count, int datatype)
2436: {
2437:   PetscFunctionBegin;
2438: #if PetscDefined(USE_LOG)
2439:   PetscCall(PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1));
2440:   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2441:   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_recv_len, &petsc_recv_len_th));
2442:   #endif
2443: #endif
2444:   PetscFunctionReturn(PETSC_SUCCESS);
2445: }

2447: PETSC_EXTERN PetscErrorCode PetscAReduce(void)
2448: {
2449:   PetscFunctionBegin;
2450:   if (PetscDefined(USE_LOG)) PetscCall(PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, 1));
2451:   PetscFunctionReturn(PETSC_SUCCESS);
2452: }

2454: PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2455: PetscClassId PETSC_OBJECT_CLASSID  = 0;

2457: static PetscBool PetscLogInitializeCalled = PETSC_FALSE;

2459: PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
2460: {
2461:   int stage;

2463:   PetscFunctionBegin;
2464:   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
2465:   PetscLogInitializeCalled = PETSC_TRUE;
2466:   if (PetscDefined(USE_LOG)) {
2467:     /* Setup default logging structures */
2468:     PetscCall(PetscLogStateCreate(&petsc_log_state));
2469:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2470:       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
2471:     }
2472:     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
2473:     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
2474: #if defined(PETSC_HAVE_THREADSAFETY)
2475:     petsc_log_tid = 0;
2476:     petsc_log_gid = 0;
2477: #endif

2479:     /* All processors sync here for more consistent logging */
2480:     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2481:     PetscCall(PetscTime(&petsc_BaseTime));
2482:     PetscCall(PetscLogStagePush(stage));
2483:   }
2484:   PetscFunctionReturn(PETSC_SUCCESS);
2485: }

2487: PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
2488: {
2489:   PetscFunctionBegin;
2490:   if (PetscDefined(USE_LOG)) {
2491:     /* Resetting phase */
2492:     // pop remaining stages
2493:     if (petsc_log_state) {
2494:       while (petsc_log_state->current_stage >= 0) { PetscCall(PetscLogStagePop()); }
2495:     }
2496:     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
2497:     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
2498:     PetscCall(PetscLogStateDestroy(&petsc_log_state));

2500:     petsc_TotalFlops         = 0.0;
2501:     petsc_BaseTime           = 0.0;
2502:     petsc_TotalFlops         = 0.0;
2503:     petsc_send_ct            = 0.0;
2504:     petsc_recv_ct            = 0.0;
2505:     petsc_send_len           = 0.0;
2506:     petsc_recv_len           = 0.0;
2507:     petsc_isend_ct           = 0.0;
2508:     petsc_irecv_ct           = 0.0;
2509:     petsc_isend_len          = 0.0;
2510:     petsc_irecv_len          = 0.0;
2511:     petsc_wait_ct            = 0.0;
2512:     petsc_wait_any_ct        = 0.0;
2513:     petsc_wait_all_ct        = 0.0;
2514:     petsc_sum_of_waits_ct    = 0.0;
2515:     petsc_allreduce_ct       = 0.0;
2516:     petsc_gather_ct          = 0.0;
2517:     petsc_scatter_ct         = 0.0;
2518:     petsc_TotalFlops_th      = 0.0;
2519:     petsc_send_ct_th         = 0.0;
2520:     petsc_recv_ct_th         = 0.0;
2521:     petsc_send_len_th        = 0.0;
2522:     petsc_recv_len_th        = 0.0;
2523:     petsc_isend_ct_th        = 0.0;
2524:     petsc_irecv_ct_th        = 0.0;
2525:     petsc_isend_len_th       = 0.0;
2526:     petsc_irecv_len_th       = 0.0;
2527:     petsc_wait_ct_th         = 0.0;
2528:     petsc_wait_any_ct_th     = 0.0;
2529:     petsc_wait_all_ct_th     = 0.0;
2530:     petsc_sum_of_waits_ct_th = 0.0;
2531:     petsc_allreduce_ct_th    = 0.0;
2532:     petsc_gather_ct_th       = 0.0;
2533:     petsc_scatter_ct_th      = 0.0;

2535:     petsc_ctog_ct    = 0.0;
2536:     petsc_gtoc_ct    = 0.0;
2537:     petsc_ctog_sz    = 0.0;
2538:     petsc_gtoc_sz    = 0.0;
2539:     petsc_gflops     = 0.0;
2540:     petsc_gtime      = 0.0;
2541:     petsc_ctog_ct_th = 0.0;
2542:     petsc_gtoc_ct_th = 0.0;
2543:     petsc_ctog_sz_th = 0.0;
2544:     petsc_gtoc_sz_th = 0.0;
2545:     petsc_gflops_th  = 0.0;
2546:     petsc_gtime_th   = 0.0;
2547:   }
2548:   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
2549:   PETSC_OBJECT_CLASSID     = 0;
2550:   PetscLogInitializeCalled = PETSC_FALSE;
2551:   PetscFunctionReturn(PETSC_SUCCESS);
2552: }

2554: /*@C
2555:   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.

2557:   Not Collective

2559:   Input Parameter:
2560: . name - The class name

2562:   Output Parameter:
2563: . oclass - The class id or classid

2565:   Level: developer

2567: .seealso: [](ch_profiling), `PetscLogEventRegister()`
2568: @*/
2569: PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
2570: {
2571:   PetscFunctionBegin;
2572:   *oclass = ++PETSC_LARGEST_CLASSID;
2573: #if defined(PETSC_USE_LOG)
2574:   {
2575:     PetscLogState state;
2576:     PetscLogClass logclass;

2578:     PetscCall(PetscLogGetState(&state));
2579:     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
2580:   }
2581: #endif
2582:   PetscFunctionReturn(PETSC_SUCCESS);
2583: }