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 <petsc/private/deviceimpl.h>

 17: #if PetscDefined(HAVE_THREADSAFETY)

 19: PetscInt           petsc_log_gid = -1; /* Global threadId counter */
 20: PETSC_TLS PetscInt petsc_log_tid = -1; /* Local threadId */

 22: /* shared variables */
 23: PetscSpinlock PetscLogSpinLock;

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

 35: #endif

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

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

 74: PetscLogDouble petsc_ctog_ct        = 0.0; /* The total number of CPU to GPU copies */
 75: PetscLogDouble petsc_gtoc_ct        = 0.0; /* The total number of GPU to CPU copies */
 76: PetscLogDouble petsc_ctog_sz        = 0.0; /* The total size of CPU to GPU copies */
 77: PetscLogDouble petsc_gtoc_sz        = 0.0; /* The total size of GPU to CPU copies */
 78: PetscLogDouble petsc_ctog_ct_scalar = 0.0; /* The total number of CPU to GPU copies */
 79: PetscLogDouble petsc_gtoc_ct_scalar = 0.0; /* The total number of GPU to CPU copies */
 80: PetscLogDouble petsc_ctog_sz_scalar = 0.0; /* The total size of CPU to GPU copies */
 81: PetscLogDouble petsc_gtoc_sz_scalar = 0.0; /* The total size of GPU to CPU copies */
 82: PetscLogDouble petsc_gflops         = 0.0; /* The flops done on a GPU */
 83: PetscLogDouble petsc_gtime          = 0.0; /* The time spent on a GPU */
 84: PetscLogDouble petsc_genergy        = 0.0; /* The energy (estimated with power*gtime) consumed on a GPU */
 85: PetscLogDouble petsc_genergy_meter  = 0.0; /* Readings from the energy meter on a GPU */

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

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

101: PetscBool PetscLogGpuTimeFlag        = PETSC_FALSE;
102: PetscBool PetscLogGpuEnergyFlag      = PETSC_FALSE;
103: PetscBool PetscLogGpuEnergyMeterFlag = PETSC_FALSE;

105: PetscInt PetscLogNumViewersCreated   = 0;
106: PetscInt PetscLogNumViewersDestroyed = 0;

108: PetscLogState petsc_log_state = NULL;

110: #define PETSC_LOG_HANDLER_HOT_BLANK {NULL, NULL, NULL, NULL, NULL, NULL}

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

119: #undef PETSC_LOG_HANDLERS_HOT_BLANK

121: #if PetscDefined(USE_LOG)
122: #include <../src/sys/logging/handler/impls/default/logdefault.h>

124:   #if PetscDefined(HAVE_THREADSAFETY)
125: /*@
126:   PetscAddLogDouble - Atomically add a `PetscLogDouble` value to both a global counter and its per-thread counterpart

128:   Not Collective; No Fortran Support

130:   Input Parameters:
131: + tot    - pointer to the global counter to update
132: . tot_th - pointer to the per-thread counter to update
133: - value  - the value to add to both counters

135:   Level: developer

137:   Note:
138:   When PETSc is built without thread safety this is a fast macro that performs the same update without locking.

140: .seealso: `PetscAddLogDoubleCnt()`, `PetscLogFlops()`, `PetscLogDouble`
141: @*/
142: PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble value)
143: {
144:   *tot_th += value;
145:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
146:   *tot += value;
147:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
148:   return PETSC_SUCCESS;
149: }

151: /*@
152:   PetscAddLogDoubleCnt - Atomically update both a count pair and a size pair of `PetscLogDouble` counters (global and per-thread)

154:   Not Collective; No Fortran Support

156:   Input Parameters:
157: + cnt    - pointer to the global count counter to increment by one
158: . tot    - pointer to the global size counter to update
159: . cnt_th - pointer to the per-thread count counter to increment by one
160: . tot_th - pointer to the per-thread size counter to update
161: - value  - the size value to add to the size counters

163:   Level: developer

165: .seealso: `PetscAddLogDouble()`, `PetscLogFlops()`, `PetscLogDouble`
166: @*/
167: PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble value)
168: {
169:   *cnt_th = *cnt_th + 1;
170:   *tot_th += value;
171:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
172:   *tot += (PetscLogDouble)value;
173:   *cnt += *cnt + 1;
174:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
175:   return PETSC_SUCCESS;
176: }

178:   #endif

180: static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
181: {
182:   PetscFunctionBegin;
183:   PetscAssertPointer(handler, 2);
184:   *handler = NULL;
185:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
186:     PetscLogHandler h = PetscLogHandlers[i].handler;
187:     if (h) {
188:       PetscBool match;

190:       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
191:       if (match) {
192:         *handler = PetscLogHandlers[i].handler;
193:         PetscFunctionReturn(PETSC_SUCCESS);
194:       }
195:     }
196:   }
197:   PetscFunctionReturn(PETSC_SUCCESS);
198: }

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

203:   Not collective

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

208:   Level: developer

210:   Notes:
211:   The default handler is started with `PetscLogDefaultBegin()`,
212:   if the options flags `-log_all` or `-log_view` is given without arguments,
213:   or for `-log_view :output:format` if `format` is not `ascii_xml` or `ascii_flamegraph`.

215: .seealso: [](ch_profiling)
216: @*/
217: PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
218: {
219:   PetscFunctionBegin;
220:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
221:   PetscFunctionReturn(PETSC_SUCCESS);
222: }

224: static PetscErrorCode PetscLogGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
225: {
226:   PetscFunctionBegin;
227:   PetscAssertPointer(handler, 2);
228:   PetscCall(PetscLogTryGetHandler(type, handler));
229:   PetscCheck(*handler != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "A PetscLogHandler of type %s has not been started.", type);
230:   PetscFunctionReturn(PETSC_SUCCESS);
231: }

233: /*@
234:   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
235:   by all default log handlers (`PetscLogDefaultBegin()`,
236:   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
237:   `PetscLogPerfstubsBegin()`).

239:   Collective on `PETSC_COMM_WORLD`

241:   Output Parameter:
242: . state - The `PetscLogState` changed by registrations (such as
243:           `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or
244:           `PetscLogStagePush()`), or `NULL` if logging is not active

246:   Level: developer

248: .seealso: [](ch_profiling), `PetscLogState`
249: @*/
250: PetscErrorCode PetscLogGetState(PetscLogState *state)
251: {
252:   PetscFunctionBegin;
253:   PetscAssertPointer(state, 1);
254:   *state = petsc_log_state;
255:   PetscFunctionReturn(PETSC_SUCCESS);
256: }

258: static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
259: {
260:   PetscFunctionBegin;
261:   hot->handler       = h;
262:   hot->eventBegin    = h->ops->eventbegin;
263:   hot->eventEnd      = h->ops->eventend;
264:   hot->eventSync     = h->ops->eventsync;
265:   hot->objectCreate  = h->ops->objectcreate;
266:   hot->objectDestroy = h->ops->objectdestroy;
267:   PetscFunctionReturn(PETSC_SUCCESS);
268: }

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

273:   Logically collective

275:   Input Parameters:
276: . h - a `PetscLogHandler`

278:   Level: developer

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

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

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

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

294: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`, `PetscInitialize()`
295: @*/
296: PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
297: {
298:   PetscFunctionBegin;
299:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
300:     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
301:   }
302:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
303:     if (PetscLogHandlers[i].handler == NULL) {
304:       PetscCall(PetscObjectReference((PetscObject)h));
305:       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
306:       if (petsc_log_state) {
307:         PetscLogStage stack_height;
308:         PetscIntStack orig_stack, temp_stack;

310:         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
311:         stack_height = petsc_log_state->stage_stack->top + 1;
312:         PetscCall(PetscIntStackCreate(&temp_stack));
313:         orig_stack                     = petsc_log_state->stage_stack;
314:         petsc_log_state->stage_stack   = temp_stack;
315:         petsc_log_state->current_stage = -1;
316:         for (int s = 0; s < stack_height; s++) {
317:           PetscLogStage stage = orig_stack->stack[s];
318:           PetscCall(PetscLogHandlerStagePush(h, stage));
319:           PetscCall(PetscIntStackPush(temp_stack, stage));
320:           petsc_log_state->current_stage = stage;
321:         }
322:         PetscCall(PetscIntStackDestroy(temp_stack));
323:         petsc_log_state->stage_stack = orig_stack;
324:       }
325:       PetscFunctionReturn(PETSC_SUCCESS);
326:     }
327:   }
328:   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
329:   PetscFunctionReturn(PETSC_SUCCESS);
330: }

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

335:   Logically collective

337:   Input Parameters:
338: . h - a `PetscLogHandler`

340:   Level: developer

342:   Note:
343:   After `PetscLogHandlerStop()`, the handler can still access the global logging state
344:   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
345:   (for instance, in `PetscLogHandlerView()`),

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

350: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
351: @*/
352: PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
353: {
354:   PetscFunctionBegin;
355:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
356:     if (PetscLogHandlers[i].handler == h) {
357:       if (petsc_log_state) {
358:         PetscLogState state;
359:         PetscLogStage stack_height;
360:         PetscIntStack orig_stack, temp_stack;

362:         PetscCall(PetscLogHandlerGetState(h, &state));
363:         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
364:         stack_height = petsc_log_state->stage_stack->top + 1;
365:         PetscCall(PetscIntStackCreate(&temp_stack));
366:         orig_stack                   = petsc_log_state->stage_stack;
367:         petsc_log_state->stage_stack = temp_stack;
368:         for (int s = 0; s < stack_height; s++) {
369:           PetscLogStage stage = orig_stack->stack[s];

371:           PetscCall(PetscIntStackPush(temp_stack, stage));
372:         }
373:         for (int s = 0; s < stack_height; s++) {
374:           PetscLogStage stage;
375:           PetscBool     empty;

377:           PetscCall(PetscIntStackPop(temp_stack, &stage));
378:           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
379:           if (!empty) PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
380:           else petsc_log_state->current_stage = -1;
381:           PetscCall(PetscLogHandlerStagePop(h, stage));
382:         }
383:         PetscCall(PetscIntStackDestroy(temp_stack));
384:         petsc_log_state->stage_stack = orig_stack;
385:         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
386:       }
387:       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
388:       PetscCall(PetscObjectDereference((PetscObject)h));
389:     }
390:   }
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: /*@
395:   PetscLogIsActive - Check if logging (profiling) is currently in progress.

397:   Not Collective

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

402:   Level: beginner

404: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
405: @*/
406: PetscErrorCode PetscLogIsActive(PetscBool *isActive)
407: {
408:   PetscFunctionBegin;
409:   *isActive = PETSC_FALSE;
410:   if (petsc_log_state) {
411:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
412:       if (PetscLogHandlers[i].handler) {
413:         *isActive = PETSC_TRUE;
414:         PetscFunctionReturn(PETSC_SUCCESS);
415:       }
416:     }
417:   }
418:   PetscFunctionReturn(PETSC_SUCCESS);
419: }

421: PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
422: {
423:   PetscFunctionBegin;
424:   *isActive = PETSC_FALSE;
425:   if (petsc_log_state) {
426:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
427:       if (PetscLogHandlers[i].eventBegin) {
428:         *isActive = PETSC_TRUE;
429:         PetscFunctionReturn(PETSC_SUCCESS);
430:       }
431:     }
432:   }
433:   PetscFunctionReturn(PETSC_SUCCESS);
434: }

436: PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
437: {
438:   PetscFunctionBegin;
439:   *isActive = PETSC_FALSE;
440:   if (petsc_log_state) {
441:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
442:       if (PetscLogHandlers[i].eventEnd) {
443:         *isActive = PETSC_TRUE;
444:         PetscFunctionReturn(PETSC_SUCCESS);
445:       }
446:     }
447:   }
448:   PetscFunctionReturn(PETSC_SUCCESS);
449: }

451: PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
452: {
453:   PetscLogHandler handler;

455:   PetscFunctionBegin;
456:   PetscCall(PetscLogTryGetHandler(type, &handler));
457:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
458:   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
459:   PetscCall(PetscLogHandlerSetType(handler, type));
460:   PetscCall(PetscLogHandlerStart(handler));
461:   PetscCall(PetscLogHandlerDestroy(&handler));
462:   PetscFunctionReturn(PETSC_SUCCESS);
463: }

465: /*@
466:   PetscLogDefaultBegin - Turns on logging (profiling) of PETSc code using the default log handler (profiler). This logs time, flop
467:   rates, and object creation and should not slow programs down too much.

469:   Logically Collective on `PETSC_COMM_WORLD`

471:   Options Database Key:
472: . -log_view viewer_specification - Displays summary of flop and timing (profiling) information (for PETSc configured `--with-log`, which is the default).
473:                                    This option must be provided before `PetscInitialize()`. See `PetscOptionsCreateViewer()` for the
474:                                    format of `viewer_specification`

476:   Example Usage:
477: .vb
478:       PetscInitialize(...);
479:       PetscLogDefaultBegin();
480:        ... code ...
481:       PetscLogView(viewer); or PetscLogDump();
482:       PetscFinalize();
483: .ve

485:   Level: advanced

487:   Notes:
488:   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
489:   the logging information.

491:   This routine may be called more than once.

493:   To provide the `-log_view` option in your source code you must call  PetscCall(PetscOptionsSetValue(NULL, "-log_view", NULL));
494:   before you call `PetscInitialize()`

496: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
497: @*/
498: PetscErrorCode PetscLogDefaultBegin(void)
499: {
500:   PetscFunctionBegin;
501:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
502:   PetscFunctionReturn(PETSC_SUCCESS);
503: }

505: /*@
506:   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
507:   begins or ends, the event name is printed.

509:   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support

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

514:   Options Database Key:
515: . -log_trace [filename] - Begins `PetscLogTraceBegin()`

517:   Level: intermediate

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

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

527: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
528: @*/
529: PetscErrorCode PetscLogTraceBegin(FILE *file)
530: {
531:   PetscLogHandler handler;

533:   PetscFunctionBegin;
534:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
535:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
536:   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
537:   PetscCall(PetscLogHandlerStart(handler));
538:   PetscCall(PetscLogHandlerDestroy(&handler));
539:   PetscFunctionReturn(PETSC_SUCCESS);
540: }

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

544: /*@
545:   PetscLogNestedBegin - Turns on nested logging of objects and events. This logs flop
546:   rates and object creation and should not slow programs down much.

548:   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support

550:   Options Database Key:
551: . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file `filename.xml`.
552:                                       See `PetscOptionsCreateViewer()` for other possible viewer specifications

554:   Example Usage:
555: .vb
556:       PetscInitialize(...);
557:       PetscLogNestedBegin();
558:        ... code ...
559:       PetscLogView(viewer);
560:       PetscFinalize();
561: .ve

563:   Level: advanced

565: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
566: @*/
567: PetscErrorCode PetscLogNestedBegin(void)
568: {
569:   PetscFunctionBegin;
570:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
571:   PetscFunctionReturn(PETSC_SUCCESS);
572: }

574: /*@
575:   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
576:   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
577:   `PetscLogPHC`, `PetscLogPHD`.

579:   Logically Collective on `PETSC_COMM_WORLD`

581:   Input Parameters:
582: + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
583: . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
584: . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
585: - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)

587:   Calling sequence of `PetscLogPLB`:
588: + e  - a `PetscLogEvent` that is beginning
589: . _i - deprecated, unused
590: . o1 - a `PetscObject` associated with `e` (or `NULL`)
591: . o2 - a `PetscObject` associated with `e` (or `NULL`)
592: . o3 - a `PetscObject` associated with `e` (or `NULL`)
593: - o4 - a `PetscObject` associated with `e` (or `NULL`)

595:   Calling sequence of `PetscLogPLE`:
596: + e  - a `PetscLogEvent` that is beginning
597: . _i - deprecated, unused
598: . o1 - a `PetscObject` associated with `e` (or `NULL`)
599: . o2 - a `PetscObject` associated with `e` (or `NULL`)
600: . o3 - a `PetscObject` associated with `e` (or `NULL`)
601: - o4 - a `PetscObject` associated with `e` (or `NULL`)

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

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

609:   Level: advanced

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

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

618: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
619: @*/
620: 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))
621: {
622:   PetscLogHandler handler;

624:   PetscFunctionBegin;
625:   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
626:   PetscCall(PetscLogHandlerStart(handler));
627:   PetscCall(PetscLogHandlerDestroy(&handler));
628:   PetscFunctionReturn(PETSC_SUCCESS);
629: }

631:   #if PetscDefined(HAVE_MPE)
632:     #include <mpe.h>
633: static PetscBool PetscBeganMPE = PETSC_FALSE;
634:   #endif

636: /*@
637:   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
638:   program down.

640:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

642:   Options Database Key:
643: . -log_mpe - Prints extensive log information

645:   Level: advanced

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

652: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
653:           `PetscLogEventDeactivate()`
654: @*/
655: PetscErrorCode PetscLogMPEBegin(void)
656: {
657:   PetscFunctionBegin;
658:   #if PetscDefined(HAVE_MPE)
659:   /* Do MPE initialization */
660:   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
661:     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
662:     PetscCall(MPE_Init_log());

664:     PetscBeganMPE = PETSC_TRUE;
665:   } else {
666:     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
667:   }
668:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
669:   #else
670:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
671:   #endif
672:   PetscFunctionReturn(PETSC_SUCCESS);
673: }

675:   #if PetscDefined(HAVE_TAU_PERFSTUBS)
676: #include <../src/sys/perfstubs/timer.h>
677:   #endif

679: /*@
680:   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.

682:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

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

687:   Level: advanced

689: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
690: @*/
691: PetscErrorCode PetscLogPerfstubsBegin(void)
692: {
693:   PetscFunctionBegin;
694:   #if PetscDefined(HAVE_TAU_PERFSTUBS)
695:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
696:   #else
697:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
698:   #endif
699:   PetscFunctionReturn(PETSC_SUCCESS);
700: }

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

705:   Not Collective

707:   Input Parameter:
708: . flag - `PETSC_TRUE` if actions are to be logged

710:   Options Database Key:
711: + -log_exclude_actions - (deprecated) Does nothing
712: - -log_include_actions - Turn on action logging

714:   Level: intermediate

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

720: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
721: @*/
722: PetscErrorCode PetscLogActions(PetscBool flag)
723: {
724:   PetscFunctionBegin;
725:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
726:     PetscLogHandler h = PetscLogHandlers[i].handler;

728:     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
729:   }
730:   PetscFunctionReturn(PETSC_SUCCESS);
731: }

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

736:   Not Collective

738:   Input Parameter:
739: . flag - `PETSC_TRUE` if objects are to be logged

741:   Options Database Key:
742: + -log_exclude_objects - (deprecated) Does nothing
743: - -log_include_objects - Turns on object logging

745:   Level: intermediate

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

751: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
752: @*/
753: PetscErrorCode PetscLogObjects(PetscBool flag)
754: {
755:   PetscFunctionBegin;
756:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
757:     PetscLogHandler h = PetscLogHandlers[i].handler;

759:     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
760:   }
761:   PetscFunctionReturn(PETSC_SUCCESS);
762: }

764: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
765: /*@
766:   PetscLogStageRegister - Attaches a character string name to a logging stage.

768:   Not Collective

770:   Input Parameter:
771: . sname - The name to associate with that stage

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

776:   Level: intermediate

778: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
779: @*/
780: PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
781: {
782:   PetscLogState state;

784:   PetscFunctionBegin;
785:   *stage = -1;
786:   PetscCall(PetscLogGetState(&state));
787:   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
788:   PetscFunctionReturn(PETSC_SUCCESS);
789: }

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

794:   Not Collective

796:   Input Parameter:
797: . stage - The stage on which to log

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

814:   Level: intermediate

816:   Note:
817:   Use `PetscLogStageRegister()` to register a stage.

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

825:   PetscFunctionBegin;
826:   PetscCall(PetscLogGetState(&state));
827:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
828:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
829:     PetscLogHandler h = PetscLogHandlers[i].handler;
830:     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
831:   }
832:   PetscCall(PetscLogStateStagePush(state, stage));
833:   PetscFunctionReturn(PETSC_SUCCESS);
834: }

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

839:   Not Collective

841:   Example Usage:
842:   If the option `-log_view` is used to run the program containing the
843:   following code, then 2 sets of summary data will be printed during
844:   PetscFinalize().
845: .vb
846:       PetscInitialize(int *argc,char ***args,0,0);
847:       [stage 0 of code]
848:       PetscLogStagePush(1);
849:       [stage 1 of code]
850:       PetscLogStagePop();
851:       PetscBarrier(...);
852:       [more stage 0 of code]
853:       PetscFinalize();
854: .ve

856:   Level: intermediate

858: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
859: @*/
860: PetscErrorCode PetscLogStagePop(void)
861: {
862:   PetscLogState state;
863:   PetscLogStage current_stage;

865:   PetscFunctionBegin;
866:   PetscCall(PetscLogGetState(&state));
867:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
868:   current_stage = state->current_stage;
869:   PetscCall(PetscLogStateStagePop(state));
870:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
871:     PetscLogHandler h = PetscLogHandlers[i].handler;
872:     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
873:   }
874:   PetscFunctionReturn(PETSC_SUCCESS);
875: }

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

880:   Not Collective

882:   Input Parameters:
883: + stage    - The stage
884: - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

886:   Level: intermediate

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

891: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
892: @*/
893: PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
894: {
895:   PetscLogState state;

897:   PetscFunctionBegin;
898:   PetscCall(PetscLogGetState(&state));
899:   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
900:   PetscFunctionReturn(PETSC_SUCCESS);
901: }

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

906:   Not Collective

908:   Input Parameter:
909: . stage - The stage

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

914:   Level: intermediate

916: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
917: @*/
918: PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
919: {
920:   PetscLogState state;

922:   PetscFunctionBegin;
923:   *isActive = PETSC_FALSE;
924:   PetscCall(PetscLogGetState(&state));
925:   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
926:   PetscFunctionReturn(PETSC_SUCCESS);
927: }

929: /*@
930:   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`

932:   Not Collective

934:   Input Parameters:
935: + stage     - The stage
936: - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

938:   Level: intermediate

940:   Developer Notes:
941:   Visibility only affects the default log handler in `PetscLogView()`; stages that are
942:   set to invisible are suppressed from output.

944: .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
945: @*/
946: PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
947: {
948:   PetscFunctionBegin;
949:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
950:     PetscLogHandler h = PetscLogHandlers[i].handler;

952:     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
953:   }
954:   PetscFunctionReturn(PETSC_SUCCESS);
955: }

957: /*@
958:   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`

960:   Not Collective

962:   Input Parameter:
963: . stage - The stage

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

968:   Level: intermediate

970: .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
971: @*/
972: PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
973: {
974:   PetscLogHandler handler;

976:   PetscFunctionBegin;
977:   *isVisible = PETSC_FALSE;
978:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
979:   if (handler) PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible));
980:   PetscFunctionReturn(PETSC_SUCCESS);
981: }

983: /*@
984:   PetscLogStageGetId - Returns the stage id when given the stage name.

986:   Not Collective

988:   Input Parameter:
989: . name - The stage name

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

994:   Level: intermediate

996: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`
997: @*/
998: PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
999: {
1000:   PetscLogState state;

1002:   PetscFunctionBegin;
1003:   *stage = -1;
1004:   PetscCall(PetscLogGetState(&state));
1005:   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
1006:   PetscFunctionReturn(PETSC_SUCCESS);
1007: }

1009: /*@
1010:   PetscLogStageGetName - Returns the stage name when given the stage id.

1012:   Not Collective

1014:   Input Parameter:
1015: . stage - The stage

1017:   Output Parameter:
1018: . name - The stage name

1020:   Level: intermediate

1022: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`
1023: @*/
1024: PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char *name[])
1025: {
1026:   PetscLogStageInfo stage_info;
1027:   PetscLogState     state;

1029:   PetscFunctionBegin;
1030:   *name = NULL;
1031:   PetscCall(PetscLogGetState(&state));
1032:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1033:   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
1034:   *name = stage_info.name;
1035:   PetscFunctionReturn(PETSC_SUCCESS);
1036: }

1038: /*------------------------------------------------ Event Functions --------------------------------------------------*/

1040: /*@
1041:   PetscLogEventRegister - Registers an event name for logging operations

1043:   Not Collective

1045:   Input Parameters:
1046: + name    - The name associated with the event
1047: - classid - The classid associated to the class for this event, obtain either with
1048:             `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
1049:             are only available in C code

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

1054:   Example Usage:
1055: .vb
1056:       PetscLogEvent USER_EVENT;
1057:       PetscClassId classid;
1058:       PetscLogDouble user_event_flops;
1059:       PetscClassIdRegister("class name",&classid);
1060:       PetscLogEventRegister("User event name",classid,&USER_EVENT);
1061:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
1062:          [code segment to monitor]
1063:          PetscLogFlops(user_event_flops);
1064:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
1065: .ve

1067:   Level: intermediate

1069:   Notes:
1070:   PETSc automatically logs library events if the code has been
1071:   configured with `--with-log` (which is the default) and
1072:   `-log_view` or `-log_all` is specified.  `PetscLogEventRegister()` is
1073:   intended for logging user events to supplement this PETSc
1074:   information.

1076:   PETSc can gather data for use with the utilities Jumpshot
1077:   (part of the MPICH distribution).  If PETSc has been compiled
1078:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
1079:   MPICH), the user can employ another command line option, `-log_mpe`,
1080:   to create a logfile, "mpe.log", which can be visualized
1081:   Jumpshot.

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

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

1091: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1092:           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1093: @*/
1094: PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1095: {
1096:   PetscLogState state;

1098:   PetscFunctionBegin;
1099:   *event = -1;
1100:   PetscCall(PetscLogGetState(&state));
1101:   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

1105: /*@
1106:   PetscLogEventSetCollective - Indicates that a particular event is collective.

1108:   Logically Collective

1110:   Input Parameters:
1111: + event      - The event id
1112: - collective - `PetscBool` indicating whether a particular event is collective

1114:   Level: developer

1116:   Notes:
1117:   New events returned from `PetscLogEventRegister()` are collective by default.

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

1123: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1124: @*/
1125: PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1126: {
1127:   PetscLogState state;

1129:   PetscFunctionBegin;
1130:   PetscCall(PetscLogGetState(&state));
1131:   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1132:   PetscFunctionReturn(PETSC_SUCCESS);
1133: }

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

1138:   Not Collective

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

1144:   Level: developer

1146: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1147: */
1148: static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1149: {
1150:   PetscLogState state;

1152:   PetscFunctionBegin;
1153:   PetscCall(PetscLogGetState(&state));
1154:   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1155:   PetscFunctionReturn(PETSC_SUCCESS);
1156: }

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

1161:   Not Collective

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

1166:   Level: developer

1168: .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1169: @*/
1170: PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1171: {
1172:   PetscFunctionBegin;
1173:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
1174:   PetscFunctionReturn(PETSC_SUCCESS);
1175: }

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

1180:   Not Collective

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

1185:   Level: developer

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

1190: .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1191: @*/
1192: PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1193: {
1194:   PetscFunctionBegin;
1195:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
1196:   PetscFunctionReturn(PETSC_SUCCESS);
1197: }

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

1202:   Not Collective

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

1209:   Usage:
1210: .vb
1211:       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
1212:         [code where you do not want to log VecSetValues()]
1213:       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
1214:         [code where you do want to log VecSetValues()]
1215: .ve

1217:   Level: advanced

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

1223: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1224: */
1225: static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1226: {
1227:   PetscLogState state;

1229:   PetscFunctionBegin;
1230:   PetscCall(PetscLogGetState(&state));
1231:   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1232:   PetscFunctionReturn(PETSC_SUCCESS);
1233: }

1235: /*@
1236:   PetscLogEventActivate - Indicates that a particular event should be logged.

1238:   Not Collective

1240:   Input Parameter:
1241: . event - The event id

1243:   Example Usage:
1244: .vb
1245:       PetscLogEventDeactivate(VEC_SetValues);
1246:         [code where you do not want to log VecSetValues()]
1247:       PetscLogEventActivate(VEC_SetValues);
1248:         [code where you do want to log VecSetValues()]
1249: .ve

1251:   Level: advanced

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

1257: .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1258: @*/
1259: PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1260: {
1261:   PetscFunctionBegin;
1262:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
1263:   PetscFunctionReturn(PETSC_SUCCESS);
1264: }

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

1269:   Not Collective

1271:   Input Parameter:
1272: . event - The event id

1274:   Example Usage:
1275: .vb
1276:       PetscLogEventDeactivate(VEC_SetValues);
1277:         [code where you do not want to log VecSetValues()]
1278:       PetscLogEventActivate(VEC_SetValues);
1279:         [code where you do want to log VecSetValues()]
1280: .ve

1282:   Level: advanced

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

1288: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1289: @*/
1290: PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1291: {
1292:   PetscFunctionBegin;
1293:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
1294:   PetscFunctionReturn(PETSC_SUCCESS);
1295: }

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

1300:   Not Collective

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

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

1313:   Level: advanced

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

1319:   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.

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

1329:     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1330:   }
1331:   PetscFunctionReturn(PETSC_SUCCESS);
1332: }

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

1337:   Not Collective

1339:   Input Parameter:
1340: . event - The event id

1342:   Example Usage:
1343: .vb
1344:       PetscLogEventDeactivatePush(VEC_SetValues);
1345:         [code where you do not want to log VecSetValues()]
1346:       PetscLogEventDeactivatePop(VEC_SetValues);
1347:         [code where you do want to log VecSetValues()]
1348: .ve

1350:   Level: advanced

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

1356: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1357: @*/
1358: PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1359: {
1360:   PetscFunctionBegin;
1361:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1362:     PetscLogHandler h = PetscLogHandlers[i].handler;

1364:     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1365:   }
1366:   PetscFunctionReturn(PETSC_SUCCESS);
1367: }

1369: /*@
1370:   PetscLogEventSetActiveAll - Turns on logging of all events

1372:   Not Collective

1374:   Input Parameters:
1375: + event    - The event id
1376: - isActive - The activity flag determining whether the event is logged

1378:   Level: advanced

1380: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1381: @*/
1382: PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1383: {
1384:   PetscLogState state;

1386:   PetscFunctionBegin;
1387:   PetscCall(PetscLogGetState(&state));
1388:   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1389:   PetscFunctionReturn(PETSC_SUCCESS);
1390: }

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

1395:   Not Collective

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

1402:   Level: developer

1404: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1405: */
1406: static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1407: {
1408:   PetscLogState state;

1410:   PetscFunctionBegin;
1411:   PetscCall(PetscLogGetState(&state));
1412:   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1413:   PetscFunctionReturn(PETSC_SUCCESS);
1414: }

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

1419:   Not Collective

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

1424:   Level: developer

1426: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1427: @*/
1428: PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1429: {
1430:   PetscFunctionBegin;
1431:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
1432:   PetscFunctionReturn(PETSC_SUCCESS);
1433: }

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

1438:   Not Collective

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

1443:   Level: developer

1445: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1446: @*/
1447: PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1448: {
1449:   PetscFunctionBegin;
1450:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
1451:   PetscFunctionReturn(PETSC_SUCCESS);
1452: }

1454: /*MC
1455:   PetscLogEventSync - Synchronizes the beginning of an event.

1457:   Synopsis:
1458: #include <petsclog.h>
1459:   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)

1461:   Collective

1463:   Input Parameters:
1464: + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1465: - comm - an MPI communicator

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

1471:   PetscLogEventRegister("User event", 0, &USER_EVENT);
1472:   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1473:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1474:   [code segment to monitor]
1475:   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1476: .ve

1478:   Level: developer

1480:   Note:
1481:   This routine should be called only if there is not a `PetscObject` available to pass to
1482:   `PetscLogEventBegin()`.

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

1487: /*MC
1488:   PetscLogEventBegin - Logs the beginning of an event.

1490:   Synopsis:
1491: #include <petsclog.h>
1492:   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

1494:   Not Collective

1496:   Input Parameters:
1497: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1498: . o1 - object associated with the event, or `NULL`
1499: . o2 - object associated with the event, or `NULL`
1500: . o3 - object associated with the event, or `NULL`
1501: - o4 - object associated with the event, or `NULL`

1503:   Fortran Synopsis:
1504:   void PetscLogEventBegin(int e, PetscErrorCode ierr)

1506:   Example Usage:
1507: .vb
1508:   PetscLogEvent USER_EVENT;

1510:   PetscLogDouble user_event_flops;
1511:   PetscLogEventRegister("User event",0, &USER_EVENT);
1512:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1513:   [code segment to monitor]
1514:   PetscLogFlops(user_event_flops);
1515:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1516: .ve

1518:   Level: intermediate

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

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

1529: /*MC
1530:   PetscLogEventEnd - Log the end of an event.

1532:   Synopsis:
1533: #include <petsclog.h>
1534:   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

1536:   Not Collective

1538:   Input Parameters:
1539: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1540: . o1 - object associated with the event, or `NULL`
1541: . o2 - object associated with the event, or `NULL`
1542: . o3 - object associated with the event, or `NULL`
1543: - o4 - object associated with the event, or `NULL`

1545:   Fortran Synopsis:
1546:   void PetscLogEventEnd(int e, PetscErrorCode ierr)

1548:   Example Usage:
1549: .vb
1550:   PetscLogEvent USER_EVENT;

1552:   PetscLogDouble user_event_flops;
1553:   PetscLogEventRegister("User event", 0, &USER_EVENT);
1554:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1555:   [code segment to monitor]
1556:   PetscLogFlops(user_event_flops);
1557:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1558: .ve

1560:   Level: intermediate

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

1565: /*@
1566:   PetscLogStageGetPerfInfo - Return the performance information about the given stage

1568:   No Fortran Support

1570:   Input Parameters:
1571: . stage - The stage number or `PETSC_DETERMINE` for the current stage

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

1576:   Level: intermediate

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

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

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

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

1605: /*@
1606:   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage

1608:   No Fortran Support

1610:   Input Parameters:
1611: + stage - The stage number or `PETSC_DETERMINE` for the current stage
1612: - event - The event number

1614:   Output Parameter:
1615: . info - This structure is filled with the performance information

1617:   Level: intermediate

1619:   Note:
1620:   This is a low level routine used by the logging functions in PETSc

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

1626: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1627: @*/
1628: PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
1629: {
1630:   PetscLogHandler     handler;
1631:   PetscEventPerfInfo *event_info;

1633:   PetscFunctionBegin;
1634:   PetscAssertPointer(info, 3);
1635:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1636:   if (handler) {
1637:     PetscCall(PetscLogHandlerGetEventPerfInfo(handler, stage, event, &event_info));
1638:     *info = *event_info;
1639:   } else {
1640:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogEventGetPerfInfo() returning zeros\n"));
1641:     PetscCall(PetscMemzero(info, sizeof(*info)));
1642:   }
1643:   PetscFunctionReturn(PETSC_SUCCESS);
1644: }

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

1649:   Not Collective

1651:   Input Parameters:
1652: + event - The event id to log
1653: . n     - The dof index, in [0, 8)
1654: - dof   - The number of dofs

1656:   Level: developer

1658:   Note:
1659:   This is to enable logging of convergence

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

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

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

1680: /*@
1681:   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event

1683:   Not Collective

1685:   Input Parameters:
1686: + event - The event id to log
1687: . n     - The error index, in [0, 8)
1688: - error - The error

1690:   Level: developer

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

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

1698: .seealso: `PetscLogEventSetDof()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1699: @*/
1700: PetscErrorCode PetscLogEventSetError(PetscLogEvent event, PetscInt n, PetscLogDouble error)
1701: {
1702:   PetscFunctionBegin;
1703:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1704:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1705:     PetscLogHandler h = PetscLogHandlers[i].handler;

1707:     if (h) {
1708:       PetscEventPerfInfo *event_info;

1710:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1711:       if (event_info) event_info->errors[n] = error;
1712:     }
1713:   }
1714:   PetscFunctionReturn(PETSC_SUCCESS);
1715: }

1717: /*@
1718:   PetscLogEventGetId - Returns the event id when given the event name.

1720:   Not Collective

1722:   Input Parameter:
1723: . name - The event name

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

1728:   Level: intermediate

1730: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1731: @*/
1732: PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1733: {
1734:   PetscLogState state;

1736:   PetscFunctionBegin;
1737:   *event = -1;
1738:   PetscCall(PetscLogGetState(&state));
1739:   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1740:   PetscFunctionReturn(PETSC_SUCCESS);
1741: }

1743: /*@
1744:   PetscLogEventGetName - Returns the event name when given the event id.

1746:   Not Collective

1748:   Input Parameter:
1749: . event - The event

1751:   Output Parameter:
1752: . name - The event name

1754:   Level: intermediate

1756: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1757: @*/
1758: PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char *name[])
1759: {
1760:   PetscLogEventInfo event_info;
1761:   PetscLogState     state;

1763:   PetscFunctionBegin;
1764:   *name = NULL;
1765:   PetscCall(PetscLogGetState(&state));
1766:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1767:   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1768:   *name = event_info.name;
1769:   PetscFunctionReturn(PETSC_SUCCESS);
1770: }

1772: /*@
1773:   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.

1775:   Not collective

1777:   Level: advanced

1779:   Notes:
1780:   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()`).

1782:   Other log handlers (such as `PetscLogNestedBegin()`) will ignore this function.

1784: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
1785: @*/
1786: PetscErrorCode PetscLogEventsPause(void)
1787: {
1788:   PetscFunctionBegin;
1789:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1790:     PetscLogHandler h = PetscLogHandlers[i].handler;

1792:     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1793:   }
1794:   PetscFunctionReturn(PETSC_SUCCESS);
1795: }

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

1800:   Not collective

1802:   Level: advanced

1804: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
1805: @*/
1806: PetscErrorCode PetscLogEventsResume(void)
1807: {
1808:   PetscFunctionBegin;
1809:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1810:     PetscLogHandler h = PetscLogHandlers[i].handler;

1812:     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1813:   }
1814:   PetscFunctionReturn(PETSC_SUCCESS);
1815: }

1817: /*------------------------------------------------ Class Functions --------------------------------------------------*/

1819: /*MC
1820:    PetscLogObjectCreate - Log the creation of a `PetscObject`

1822:    Synopsis:
1823: #include <petsclog.h>
1824:    PetscErrorCode PetscLogObjectCreate(PetscObject h)

1826:    Not Collective

1828:    Input Parameters:
1829: .  h - A `PetscObject`

1831:    Level: developer

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

1837: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1838: M*/

1840: /*MC
1841:    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`

1843:    Synopsis:
1844: #include <petsclog.h>
1845:    PetscErrorCode PetscLogObjectDestroy(PetscObject h)

1847:    Not Collective

1849:    Input Parameters:
1850: .  h - A `PetscObject`

1852:    Level: developer

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

1858: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1859: M*/

1861: /*@
1862:   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.

1864:   Not Collective

1866:   Input Parameter:
1867: . name - The class name

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

1872:   Level: intermediate

1874: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1875: @*/
1876: PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1877: {
1878:   PetscLogClass     log_class;
1879:   PetscLogClassInfo class_info;
1880:   PetscLogState     state;

1882:   PetscFunctionBegin;
1883:   *classid = -1;
1884:   PetscCall(PetscLogGetState(&state));
1885:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1886:   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1887:   if (log_class < 0) {
1888:     *classid = -1;
1889:     PetscFunctionReturn(PETSC_SUCCESS);
1890:   }
1891:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1892:   *classid = class_info.classid;
1893:   PetscFunctionReturn(PETSC_SUCCESS);
1894: }

1896: /*@
1897:   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.

1899:   Not Collective

1901:   Input Parameter:
1902: . classid - A `PetscClassId`

1904:   Output Parameter:
1905: . name - The class name

1907:   Level: intermediate

1909: .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`
1910: @*/
1911: PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char *name[])
1912: {
1913:   PetscLogClass     log_class;
1914:   PetscLogClassInfo class_info;
1915:   PetscLogState     state;

1917:   PetscFunctionBegin;
1918:   PetscCall(PetscLogGetState(&state));
1919:   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1920:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1921:   *name = class_info.name;
1922:   PetscFunctionReturn(PETSC_SUCCESS);
1923: }

1925: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1926: /*@
1927:   PetscLogDump - Dumps logs of objects to a file. There is currently no utility to read the dump file.

1929:   Collective on `PETSC_COMM_WORLD`

1931:   Input Parameter:
1932: . sname - an optional file name

1934:   Example Usage:
1935: .vb
1936:   PetscInitialize(...);
1937:   PetscLogDefaultBegin();
1938:   // ... code ...
1939:   PetscLogDump(filename);
1940:   PetscFinalize();
1941: .ve

1943:   Level: advanced

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

1949: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1950: @*/
1951: PetscErrorCode PetscLogDump(const char sname[])
1952: {
1953:   PetscLogHandler handler;

1955:   PetscFunctionBegin;
1956:   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1957:   PetscCall(PetscLogHandlerDump(handler, sname));
1958:   PetscFunctionReturn(PETSC_SUCCESS);
1959: }

1961: /*@
1962:   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.

1964:   Collective on `PETSC_COMM_WORLD`

1966:   Input Parameter:
1967: . sname - filename for the MPE logfile

1969:   Level: advanced

1971: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
1972: @*/
1973: PetscErrorCode PetscLogMPEDump(const char sname[])
1974: {
1975:   PetscFunctionBegin;
1976:   #if PetscDefined(HAVE_MPE)
1977:   if (PetscBeganMPE) {
1978:     char name[PETSC_MAX_PATH_LEN];

1980:     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
1981:     if (sname) {
1982:       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
1983:     } else {
1984:       PetscCall(PetscGetProgramName(name, sizeof(name)));
1985:     }
1986:     PetscCall(MPE_Finish_log(name));
1987:   } else {
1988:     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
1989:   }
1990:   #else
1991:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
1992:   #endif
1993:   PetscFunctionReturn(PETSC_SUCCESS);
1994: }

1996: /*@
1997:   PetscLogView - Prints a summary of the logging.

1999:   Collective

2001:   Input Parameter:
2002: . viewer - an ASCII viewer

2004:   Options Database Keys:
2005: + -log_view viewer_specification - Views summary of the logging at the conclusion of the program, see `PetscOptionsCreateViewer()` for the format of `viewer_specification`
2006: . -log_view_memory (true|false)  - Also display memory usage in each event
2007: . -log_view_gpu_time             - Also display time in each event for GPU kernels (Note this may slow the computation)
2008: . -log_view_gpu_energy           - Also display energy (estimated with power*gtime) in Joules for GPU kernels
2009: . -log_view_gpu_energy_meter     - [Experimental] Also display energy (readings from energy meters) in Joules for GPU kernels.
2010:                                    This option is ignored if `-log_view_gpu_energy` is provided.
2011: . -log_all [filename]            - Saves a file `Log.rank` for each MPI process with details of each step of the computation, where
2012:                                    `rank` is the rank of each MPI process
2013: - -log_trace [filename]          - Displays a trace of what each process is doing

2015:   Level: beginner

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

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

2023:   If PETSc is configured with `--with-log=0` then this functionality is not available

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

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

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

2043:   Example Usage:
2044: .vb
2045:  -log_view :filename                      - Prints summary of log information to a file
2046:  -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
2047:  -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see above for how to view it)
2048:  -log_view :filename.txt:ascii_flamegraph - Saves logging information in a format suitable for visualising as a Flame Graph (see above for how to view it)
2049:  -log_view :filename.csv:ascii_csv        - Saves logging information as a comma-separated values file
2050: .ve

2052: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2053: @*/
2054: PetscErrorCode PetscLogView(PetscViewer viewer)
2055: {
2056:   PetscBool         isascii;
2057:   PetscViewerFormat format;
2058:   int               stage;
2059:   PetscLogState     state;
2060:   PetscIntStack     temp_stack;
2061:   PetscLogHandler   handler;
2062:   PetscBool         is_empty;

2064:   PetscFunctionBegin;
2065:   PetscCall(PetscLogGetState(&state));
2066:   /* Pop off any stages the user forgot to remove */
2067:   PetscCall(PetscIntStackCreate(&temp_stack));
2068:   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2069:   while (stage >= 0) {
2070:     PetscCall(PetscLogStagePop());
2071:     PetscCall(PetscIntStackPush(temp_stack, stage));
2072:     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2073:   }
2074:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2075:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2076:   PetscCall(PetscViewerGetFormat(viewer, &format));
2077:   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2078:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
2079:     PetscCall(PetscLogHandlerView(handler, viewer));
2080:   } else {
2081:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
2082:     PetscCall(PetscLogHandlerView(handler, viewer));
2083:   }
2084:   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2085:   while (!is_empty) {
2086:     PetscCall(PetscIntStackPop(temp_stack, &stage));
2087:     PetscCall(PetscLogStagePush(stage));
2088:     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2089:   }
2090:   PetscCall(PetscIntStackDestroy(temp_stack));
2091:   PetscFunctionReturn(PETSC_SUCCESS);
2092: }

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

2097:   Collective on `PETSC_COMM_WORLD`

2099:   Options Database Key:
2100: . -log_view viewer_specification,viewer_specification - list of up to four specifications of viewers, see `PetscOptionsCreateViewer()` for their format

2102:   Level: developer

2104:   Note:
2105:   This function has a different API and behavior than `PetscObjectViewFromOptions()`

2107: .seealso: [](ch_profiling), `PetscLogView()`
2108: @*/
2109: PetscErrorCode PetscLogViewFromOptions(void)
2110: {
2111:   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
2112:   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2113:   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2114:   PetscBool         flg;

2116:   PetscFunctionBegin;
2117:   PetscCall(PetscOptionsCreateViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
2118:   /*
2119:      PetscLogHandlerView_Default_Info() wants to be sure that the only objects still around are these viewers, so keep track of how many there are
2120:    */
2121:   PetscLogNumViewersCreated = n_max;
2122:   for (PetscInt i = 0; i < n_max; i++) {
2123:     PetscInt refct;

2125:     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
2126:     PetscCall(PetscLogView(viewers[i]));
2127:     PetscCall(PetscViewerPopFormat(viewers[i]));
2128:     PetscCall(PetscObjectGetReference((PetscObject)viewers[i], &refct));
2129:     PetscCall(PetscViewerDestroy(&viewers[i]));
2130:     if (refct == 1) PetscLogNumViewersDestroyed++;
2131:   }
2132:   PetscLogNumViewersDestroyed = 0;
2133:   PetscFunctionReturn(PETSC_SUCCESS);
2134: }

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

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

2142:   Logically Collective on `PETSC_COMM_WORLD`

2144:   Input Parameter:
2145: . newThresh - the threshold to use

2147:   Output Parameter:
2148: . oldThresh - the previously set threshold value

2150:   Options Database Key:
2151: . -log_threshold threshold - provide the threshold

2153:   Example Usage:
2154: .vb
2155:   PetscInitialize(...);
2156:   PetscLogNestedBegin();
2157:   PetscLogSetThreshold(0.1,&oldthresh);
2158:   // ... code ...
2159:   PetscLogView(viewer);
2160:   PetscFinalize();
2161: .ve

2163:   Level: advanced

2165:   Note:
2166:   This threshold is only used by the nested log handler

2168: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
2169:           `PetscLogNestedBegin()`
2170: @*/
2171: PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
2172: {
2173:   PetscLogHandler handler;

2175:   PetscFunctionBegin;
2176:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
2177:   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
2178:   PetscFunctionReturn(PETSC_SUCCESS);
2179: }

2181: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2182: /*@
2183:   PetscGetFlops - Returns the number of flops used on this processor
2184:   since the program began.

2186:   Not Collective

2188:   Output Parameter:
2189: . flops - number of floating point operations

2191:   Level: intermediate

2193:   Notes:
2194:   A global counter logs all PETSc flop counts.  The user can use
2195:   `PetscLogFlops()` to increment this counter to include flops for the
2196:   application code.

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

2200: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscTime()`, `PetscLogFlops()`
2201: @*/
2202: PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
2203: {
2204:   PetscFunctionBegin;
2205:   *flops = petsc_TotalFlops;
2206:   PetscFunctionReturn(PETSC_SUCCESS);
2207: }

2209: /*@
2210:   PetscLogObjectState - Record information about an object with the default log handler

2212:   Not Collective

2214:   Input Parameters:
2215: + obj    - the `PetscObject`
2216: . format - a printf-style format string
2217: - ...    - `printf()` arguments to format

2219:   Level: developer

2221: .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`, `PetscLogGetDefaultHandler()`
2222: @*/
2223: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
2224: {
2225:   PetscFunctionBegin;
2226:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2227:     PetscLogHandler h = PetscLogHandlers[i].handler;

2229:     if (h) {
2230:       va_list Argp;
2231:       va_start(Argp, format);
2232:       PetscCall(PetscLogHandlerLogObjectState_Internal(h, obj, format, Argp));
2233:       va_end(Argp);
2234:     }
2235:   }
2236:   PetscFunctionReturn(PETSC_SUCCESS);
2237: }

2239: /*MC
2240:   PetscLogFlops - Adds floating point operations to the global counter.

2242:   Synopsis:
2243: #include <petsclog.h>
2244:   PetscErrorCode PetscLogFlops(PetscLogDouble f)

2246:   Not Collective

2248:   Input Parameter:
2249: . f - flop counter

2251:   Example Usage:
2252: .vb
2253:   PetscLogEvent USER_EVENT;

2255:   PetscLogEventRegister("User event", 0, &USER_EVENT);
2256:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
2257:   [code segment to monitor]
2258:   PetscLogFlops(user_flops)
2259:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
2260: .ve

2262:   Level: intermediate

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

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

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

2274: /*@
2275:   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels

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

2280:   Level: advanced

2282:   Notes:
2283:   Turning on the timing of the GPU kernels can slow down the entire computation and should only
2284:   be used when studying the performance of individual operations on GPU such as vector operations and
2285:   matrix-vector operations.

2287:   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

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

2292: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
2293: @*/
2294: PetscErrorCode PetscLogGpuTime(void)
2295: {
2296:   PetscFunctionBegin;
2297:   PetscCheck(petsc_gtime == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU logging has already been turned on");
2298:   PetscLogGpuTimeFlag = PETSC_TRUE;
2299:   PetscFunctionReturn(PETSC_SUCCESS);
2300: }

2302: /*@
2303:   PetscLogGpuTimeBegin - Start timer for device

2305:   Level: intermediate

2307:   Notes:
2308:   When GPU is enabled, the timer is run on the GPU, it is a separate logging of time
2309:   devoted to GPU computations (excluding kernel launch times).

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

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

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

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

2324:   Developer Notes:
2325:   The GPU event timer captures the execution time of all the kernels launched in the default
2326:   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()`.

2328:   `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()` insert the begin and end events into the
2329:   default stream (stream 0). The device will record a time stamp for the event when it reaches
2330:   that event in the stream. The function xxxEventSynchronize() is called in
2331:   `PetscLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
2332:   timer event is recorded.

2334: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2335: @*/
2336: PetscErrorCode PetscLogGpuTimeBegin(void)
2337: {
2338:   PetscBool isActive;

2340:   PetscFunctionBegin;
2341:   PetscCall(PetscLogEventBeginIsActive(&isActive));
2342:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2343:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
2344:     PetscDeviceContext dctx;

2346:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2347:     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2348:   } else {
2349:     PetscCall(PetscTimeSubtract(&petsc_gtime));
2350:   }
2351:   PetscFunctionReturn(PETSC_SUCCESS);
2352: }

2354: /*@
2355:   PetscLogGpuTimeEnd - Stop timer for device

2357:   Level: intermediate

2359: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2360: @*/
2361: PetscErrorCode PetscLogGpuTimeEnd(void)
2362: {
2363:   PetscBool isActive;

2365:   PetscFunctionBegin;
2366:   PetscCall(PetscLogEventEndIsActive(&isActive));
2367:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2368:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
2369:     PetscDeviceContext dctx;
2370:     PetscLogDouble     elapsed;

2372:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2373:     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
2374:     petsc_gtime += (elapsed / 1000.0);
2375:     #if PetscDefined(HAVE_NVML)
2376:     if (PetscLogGpuEnergyFlag) {
2377:       PetscLogDouble power;
2378:       PetscCall(PetscDeviceContextGetPower_Internal(dctx, &power));
2379:       petsc_genergy += (power * elapsed / 1000000.0); // convert to Joules
2380:     }
2381:     #endif
2382:   } else {
2383:     PetscCall(PetscTimeAdd(&petsc_gtime));
2384:   }
2385:   PetscFunctionReturn(PETSC_SUCCESS);
2386: }

2388: /*@
2389:   PetscLogGpuEnergy - turn on the logging of GPU energy (estimated with power*gtime) for GPU kernels

2391:   Options Database Key:
2392: . -log_view_gpu_energy - provide the GPU energy consumption (estimated with power*gtime) for all events in the `-log_view` output

2394:   Level: advanced

2396:   Note:
2397:   This option is mutually exclusive to `-log_view_gpu_energy_meter`.

2399:   Developer Note:
2400:   Requires configuring with `--with-cuda-nvml=1` (CUDA >= 12.2). The energy consumption is estimated as
2401:   instant_power * gpu_kernel_time. Due to the delay in NVML power sampling, we read the instantaneous power draw at the end of each
2402:   event using `nvmlDeviceGetFieldValues()` with the field ID `NVML_FI_DEV_POWER_INSTANT`.

2404: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeter()`
2405: @*/
2406: PetscErrorCode PetscLogGpuEnergy(void)
2407: {
2408:   PetscFunctionBegin;
2409:   PetscCheck(PetscDefined(HAVE_NVML), PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "-log_view_gpu_energy requires a CUDA build of PETSc configured with --with-cuda-nvml=1 (not used by default)");
2410:   PetscCheck(petsc_genergy == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU energy logging has already been turned on");
2411:   PetscLogGpuEnergyFlag      = PETSC_TRUE;
2412:   PetscLogGpuEnergyMeterFlag = PETSC_FALSE;
2413:   PetscFunctionReturn(PETSC_SUCCESS);
2414: }

2416: /*@
2417:   PetscLogGpuEnergyMeter - turn on the logging of GPU energy (readings from energy meters) for GPU kernels

2419:   Options Database Key:
2420: . -log_view_gpu_energy_meter - provide the GPU energy (readings from energy meters) consumption for all events in the `-log_view` output

2422:   Level: advanced

2424:   Note:
2425:   This option is mutually exclusive to `-log_view_gpu_energy`.

2427:   Developer Note:
2428:   Requires configuring with `--with-cuda-nvml=1` (CUDA >= 12.2). The energy consumption is measured directly using the NVML API
2429:   `nvmlDeviceGetTotalEnergyConsumption()`, which returns the total energy used by the GPU since the driver was last initialized.
2430:   For newer GPUs, energy readings are updated every 20-100ms, so this approach may be inaccurate for short-duration GPU events.

2432: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterEnd()`, `PetscLogGpuEnergyMeterBegin()`
2433: @*/
2434: PetscErrorCode PetscLogGpuEnergyMeter(void)
2435: {
2436:   PetscFunctionBegin;
2437:   PetscCheck(PetscDefined(HAVE_NVML), PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "-log_view_gpu_energy_meter requires a CUDA build of PETSc configured with --with-cuda-nvml=1 (not used by default)");
2438:   PetscCheck(petsc_genergy == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU energy logging has already been turned on");
2439:   PetscLogGpuEnergyMeterFlag = PETSC_TRUE;
2440:   PetscLogGpuEnergyFlag      = PETSC_FALSE;
2441:   PetscFunctionReturn(PETSC_SUCCESS);
2442: }

2444: /*@
2445:   PetscLogGpuEnergyMeterBegin - Start energy meter for device

2447:   Level: intermediate

2449:   Notes:
2450:   The GPU event energy meter captures the energy used by the GPU between `PetscLogGpuEnergyMeterBegin()` and `PetscLogGpuEnergyMeterEnd()`.

2452:   `PetscLogGpuEnergyMeterBegin()` and `PetscLogGpuEnergyMeterEnd()` collect the energy readings using `nvmlDeviceGetTotalEnergyConsumption()`.
2453:   The function `cupmStreamSynchronize()` is called before the energy query to ensure completion.

2455: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterEnd()`, `PetscLogGpuEnergyMeter()`
2456: @*/
2457: PetscErrorCode PetscLogGpuEnergyMeterBegin(void)
2458: {
2459:   PetscBool isActive;

2461:   PetscFunctionBegin;
2462:   PetscCall(PetscLogEventBeginIsActive(&isActive));
2463:   if (!isActive || !PetscLogGpuEnergyMeterFlag) PetscFunctionReturn(PETSC_SUCCESS);
2464:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
2465:     PetscDeviceContext dctx;

2467:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2468:     PetscCall(PetscDeviceContextBeginEnergyMeter_Internal(dctx));
2469:   }
2470:   PetscFunctionReturn(PETSC_SUCCESS);
2471: }

2473: /*@
2474:   PetscLogGpuEnergyMeterEnd - Stop energy meter for device

2476:   Level: intermediate

2478: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterBegin()`
2479: @*/
2480: PetscErrorCode PetscLogGpuEnergyMeterEnd(void)
2481: {
2482:   PetscBool isActive;

2484:   PetscFunctionBegin;
2485:   PetscCall(PetscLogEventEndIsActive(&isActive));
2486:   if (!isActive || !PetscLogGpuEnergyMeterFlag) PetscFunctionReturn(PETSC_SUCCESS);
2487:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
2488:     PetscDeviceContext dctx;
2489:     PetscLogDouble     energy;

2491:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2492:     PetscCall(PetscDeviceContextEndEnergyMeter_Internal(dctx, &energy));
2493:     petsc_genergy_meter += (energy / 1000.0); // convert to Joules
2494:   }
2495:   PetscFunctionReturn(PETSC_SUCCESS);
2496: }
2497:   #endif /* end of PETSC_HAVE_DEVICE */

2499: #endif /* PETSC_USE_LOG*/

2501: PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2502: PetscClassId PETSC_OBJECT_CLASSID  = 0;

2504: static PetscBool PetscLogInitializeCalled = PETSC_FALSE;

2506: PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
2507: {
2508:   int stage;

2510:   PetscFunctionBegin;
2511:   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
2512:   PetscLogInitializeCalled = PETSC_TRUE;
2513:   if (PetscDefined(USE_LOG)) {
2514:     /* Setup default logging structures */
2515:     PetscCall(PetscLogStateCreate(&petsc_log_state));
2516:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2517:       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
2518:     }
2519:     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
2520:     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
2521: #if PetscDefined(HAVE_THREADSAFETY)
2522:     petsc_log_tid = 0;
2523:     petsc_log_gid = 0;
2524: #endif

2526:     /* All processors sync here for more consistent logging */
2527:     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2528:     PetscCall(PetscTime(&petsc_BaseTime));
2529:     PetscCall(PetscLogStagePush(stage));
2530:   }
2531:   PetscFunctionReturn(PETSC_SUCCESS);
2532: }

2534: PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
2535: {
2536:   PetscFunctionBegin;
2537:   if (PetscDefined(USE_LOG)) {
2538:     /* Resetting phase */
2539:     // pop remaining stages
2540:     if (petsc_log_state) {
2541:       while (petsc_log_state->current_stage >= 0) PetscCall(PetscLogStagePop());
2542:     }
2543:     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
2544:     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
2545:     PetscCall(PetscLogStateDestroy(&petsc_log_state));

2547:     petsc_TotalFlops         = 0.0;
2548:     petsc_BaseTime           = 0.0;
2549:     petsc_TotalFlops         = 0.0;
2550:     petsc_send_ct            = 0.0;
2551:     petsc_recv_ct            = 0.0;
2552:     petsc_send_len           = 0.0;
2553:     petsc_recv_len           = 0.0;
2554:     petsc_isend_ct           = 0.0;
2555:     petsc_irecv_ct           = 0.0;
2556:     petsc_isend_len          = 0.0;
2557:     petsc_irecv_len          = 0.0;
2558:     petsc_wait_ct            = 0.0;
2559:     petsc_wait_any_ct        = 0.0;
2560:     petsc_wait_all_ct        = 0.0;
2561:     petsc_sum_of_waits_ct    = 0.0;
2562:     petsc_allreduce_ct       = 0.0;
2563:     petsc_gather_ct          = 0.0;
2564:     petsc_scatter_ct         = 0.0;
2565:     petsc_TotalFlops_th      = 0.0;
2566:     petsc_send_ct_th         = 0.0;
2567:     petsc_recv_ct_th         = 0.0;
2568:     petsc_send_len_th        = 0.0;
2569:     petsc_recv_len_th        = 0.0;
2570:     petsc_isend_ct_th        = 0.0;
2571:     petsc_irecv_ct_th        = 0.0;
2572:     petsc_isend_len_th       = 0.0;
2573:     petsc_irecv_len_th       = 0.0;
2574:     petsc_wait_ct_th         = 0.0;
2575:     petsc_wait_any_ct_th     = 0.0;
2576:     petsc_wait_all_ct_th     = 0.0;
2577:     petsc_sum_of_waits_ct_th = 0.0;
2578:     petsc_allreduce_ct_th    = 0.0;
2579:     petsc_gather_ct_th       = 0.0;
2580:     petsc_scatter_ct_th      = 0.0;

2582:     petsc_ctog_ct       = 0.0;
2583:     petsc_gtoc_ct       = 0.0;
2584:     petsc_ctog_sz       = 0.0;
2585:     petsc_gtoc_sz       = 0.0;
2586:     petsc_gflops        = 0.0;
2587:     petsc_gtime         = 0.0;
2588:     petsc_genergy       = 0.0;
2589:     petsc_genergy_meter = 0.0;
2590:     petsc_ctog_ct_th    = 0.0;
2591:     petsc_gtoc_ct_th    = 0.0;
2592:     petsc_ctog_sz_th    = 0.0;
2593:     petsc_gtoc_sz_th    = 0.0;
2594:     petsc_gflops_th     = 0.0;
2595:     petsc_gtime_th      = 0.0;
2596:   }
2597:   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
2598:   PETSC_OBJECT_CLASSID     = 0;
2599:   PetscLogInitializeCalled = PETSC_FALSE;
2600:   PetscFunctionReturn(PETSC_SUCCESS);
2601: }

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

2606:   Not Collective

2608:   Input Parameter:
2609: . name - The class name

2611:   Output Parameter:
2612: . oclass - The class id or classid

2614:   Level: developer

2616: .seealso: [](ch_profiling), `PetscLogEventRegister()`
2617: @*/
2618: PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
2619: {
2620:   PetscFunctionBegin;
2621:   *oclass = ++PETSC_LARGEST_CLASSID;
2622: #if PetscDefined(USE_LOG)
2623:   {
2624:     PetscLogState state;
2625:     PetscLogClass logclass;

2627:     PetscCall(PetscLogGetState(&state));
2628:     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
2629:   }
2630: #endif
2631:   PetscFunctionReturn(PETSC_SUCCESS);
2632: }