Actual source code: ex7.c

  1: const char help[] = "How to create a log handler using the PetscLogHandler interface";

  3: #include <petsc/private/hashmapi.h>
  4: #include <petsc/private/loghandlerimpl.h>

  6: /* Log handlers that use the PetscLogHandler interface get their information
  7:    from the PetscLogState available to each handler and the user-defined
  8:    context pointer.  Compare this example to src/sys/tutorials/ex6.c.

 10:    A logging event can be started multiple times before it stops: for example,
 11:    a linear solve may involve a subsolver, so PetscLogEventBegin() can be
 12:    called for the event KSP_Solve multiple times before a call to
 13:    PetscLogEventEnd().  The user defined handler in this example shows how many
 14:    times an event is running. */

 16: #define PETSCLOGHANDLEREX7 "ex7"

 18: typedef struct _HandlerCtx *HandlerCtx;

 20: struct _HandlerCtx {
 21:   PetscHMapI running;
 22:   PetscInt   num_objects_created;
 23:   PetscInt   num_objects_destroyed;
 24: };

 26: static PetscErrorCode HandlerCtxCreate(HandlerCtx *ctx_p)
 27: {
 28:   HandlerCtx ctx;

 30:   PetscFunctionBegin;
 31:   PetscCall(PetscNew(ctx_p));
 32:   ctx = *ctx_p;
 33:   PetscCall(PetscHMapICreate(&ctx->running));
 34:   PetscFunctionReturn(PETSC_SUCCESS);
 35: }

 37: static PetscErrorCode HandlerCtxDestroy(HandlerCtx *ctx_p)
 38: {
 39:   HandlerCtx ctx;

 41:   PetscFunctionBegin;
 42:   ctx    = *ctx_p;
 43:   *ctx_p = NULL;
 44:   PetscCall(PetscHMapIDestroy(&ctx->running));
 45:   PetscCall(PetscFree(ctx));
 46:   PetscFunctionReturn(PETSC_SUCCESS);
 47: }

 49: #define PrintData(format_string, ...) \
 50:   do { \
 51:     PetscMPIInt    _rank; \
 52:     PetscLogDouble _time; \
 53:     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &_rank)); \
 54:     PetscCall(PetscTime(&_time)); \
 55:     PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d:%-7g:%-33s] " format_string, _rank, _time, PETSC_FUNCTION_NAME, __VA_ARGS__)); \
 56:   } while (0)

 58: static PetscErrorCode PetscLogHandlerEventBegin_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
 59: {
 60:   HandlerCtx        ctx;
 61:   PetscInt          count;
 62:   PetscLogState     state;
 63:   PetscLogEventInfo event_info;
 64:   PetscBool         is_active;

 66:   PetscFunctionBegin;
 67:   // This callback will only be invoked if the event is active
 68:   PetscCall(PetscLogHandlerGetState(h, &state));
 69:   PetscCall(PetscLogStateEventGetActive(state, PETSC_DEFAULT, e, &is_active));
 70:   PetscAssert(is_active, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Event handler called for inactive event");

 72:   ctx = (HandlerCtx)h->data;
 73:   PetscCall(PetscHMapIGetWithDefault(ctx->running, e, 0, &count));
 74:   count += 1;
 75:   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
 76:   PrintData("Event \"%s\" started: now running %" PetscInt_FMT " times\n", event_info.name, count);
 77:   PetscCall(PetscHMapISet(ctx->running, e, count));
 78:   PetscFunctionReturn(PETSC_SUCCESS);
 79: }

 81: static PetscErrorCode PetscLogHandlerEventEnd_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
 82: {
 83:   HandlerCtx        ctx;
 84:   PetscInt          count;
 85:   PetscLogState     state;
 86:   PetscLogEventInfo event_info;

 88:   PetscFunctionBegin;
 89:   ctx = (HandlerCtx)h->data;
 90:   PetscCall(PetscLogHandlerGetState(h, &state));
 91:   PetscCall(PetscHMapIGetWithDefault(ctx->running, e, 0, &count));
 92:   count -= 1;
 93:   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
 94:   PrintData("Event \"%s\" stopped: now running %" PetscInt_FMT " times\n", event_info.name, count);
 95:   PetscCall(PetscHMapISet(ctx->running, e, count));
 96:   PetscFunctionReturn(PETSC_SUCCESS);
 97: }

 99: static PetscErrorCode PetscLogHandlerEventSync_Ex7(PetscLogHandler h, PetscLogEvent e, MPI_Comm comm)
100: {
101:   PetscLogState     state;
102:   PetscLogEventInfo event_info;
103:   PetscLogDouble    time = 0.0;

105:   PetscFunctionBegin;
106:   PetscCall(PetscTimeSubtract(&time));
107:   PetscCallMPI(MPI_Barrier(comm));
108:   PetscCall(PetscTimeAdd(&time));
109:   PetscCall(PetscLogHandlerGetState(h, &state));
110:   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
111:   PrintData("Event \"%s\" synced: took %g seconds\n", event_info.name, time);
112:   PetscFunctionReturn(PETSC_SUCCESS);
113: }

115: static PetscErrorCode PetscLogHandlerObjectCreate_Ex7(PetscLogHandler h, PetscObject obj)
116: {
117:   HandlerCtx ctx;

119:   PetscFunctionBegin;
120:   ctx = (HandlerCtx)h->data;
121:   ctx->num_objects_created++;
122:   PetscFunctionReturn(PETSC_SUCCESS);
123: }

125: static PetscErrorCode PetscLogHandlerObjectDestroy_Ex7(PetscLogHandler h, PetscObject obj)
126: {
127:   HandlerCtx ctx;

129:   PetscFunctionBegin;
130:   ctx = (HandlerCtx)h->data;
131:   ctx->num_objects_destroyed++;
132:   PetscFunctionReturn(PETSC_SUCCESS);
133: }

135: static PetscErrorCode PetscLogHandlerStagePush_Ex7(PetscLogHandler h, PetscLogStage new_stage)
136: {
137:   PetscLogStage     old_stage;
138:   PetscLogStageInfo new_info;
139:   PetscLogState     state;

141:   PetscFunctionBegin;
142:   PetscCall(PetscLogHandlerGetState(h, &state));
143:   PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
144:   PetscCall(PetscLogStateGetCurrentStage(state, &old_stage));
145:   if (old_stage >= 0) {
146:     PetscLogStageInfo old_info;
147:     PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
148:     PrintData("Pushing stage stage \"%s\" (replacing \"%s\")\n", new_info.name, old_info.name);
149:   } else {
150:     PrintData("Pushing initial stage \"%s\"\n", new_info.name);
151:   }
152:   PetscFunctionReturn(PETSC_SUCCESS);
153: }

155: static PetscErrorCode PetscLogHandlerStagePop_Ex7(PetscLogHandler h, PetscLogStage old_stage)
156: {
157:   PetscLogStage     new_stage;
158:   PetscLogStageInfo old_info;
159:   PetscLogState     state;

161:   PetscFunctionBegin;
162:   PetscCall(PetscLogHandlerGetState(h, &state));
163:   PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
164:   PetscCall(PetscLogStateGetCurrentStage(state, &new_stage));
165:   if (new_stage >= 0) {
166:     PetscLogStageInfo new_info;

168:     PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
169:     PrintData("Popping stage \"%s\" (back to \"%s\")\n", old_info.name, new_info.name);
170:   } else {
171:     PrintData("Popping initial stage \"%s\"\n", old_info.name);
172:   }
173:   PetscFunctionReturn(PETSC_SUCCESS);
174: }

176: static PetscErrorCode PetscLogHandlerView_Ex7(PetscLogHandler h, PetscViewer viewer)
177: {
178:   PetscBool is_ascii;

180:   PetscFunctionBegin;
181:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii));
182:   if (is_ascii) {
183:     HandlerCtx ctx;
184:     PetscInt   num_entries;

186:     ctx = (HandlerCtx)h->data;
187:     PetscCall(PetscHMapIGetSize(ctx->running, &num_entries));
188:     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " events were seen by the handler\n", num_entries));
189:     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " object(s) were created and %" PetscInt_FMT " object(s) were destroyed\n", ctx->num_objects_created, ctx->num_objects_destroyed));
190:   }
191:   PetscFunctionReturn(PETSC_SUCCESS);
192: }

194: // An example of overloading one of the methods defined using PetscObjectComposeFunction()
195: static PetscErrorCode PetscLogHandlerLogObjectState_Ex7(PetscLogHandler h, PetscObject obj, const char format[], va_list argp)
196: {
197:   const char *name;

199:   PetscFunctionBegin;
200:   PetscCall(PetscObjectGetName(obj, &name));
201:   PrintData("Logged state for \"%s\": ", name);
202:   PetscCall(PetscVFPrintf(PETSC_STDOUT, format, argp));
203:   PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
204:   PetscFunctionReturn(PETSC_SUCCESS);
205: }

207: static PetscErrorCode PetscLogHandlerDestroy_Ex7(PetscLogHandler h)
208: {
209:   HandlerCtx ctx;

211:   PetscFunctionBegin;
212:   ctx = (HandlerCtx)h->data;
213:   PetscCall(HandlerCtxDestroy(&ctx));
214:   PetscCall(PetscObjectComposeFunction((PetscObject)h, "PetscLogHandlerLogObjectState_C", NULL));
215:   PetscFunctionReturn(PETSC_SUCCESS);
216: }

218: static PetscErrorCode PetscLogHandlerCreate_Ex7(PetscLogHandler handler)
219: {
220:   HandlerCtx ctx;

222:   PetscFunctionBegin;
223:   PetscCall(HandlerCtxCreate(&ctx));
224:   handler->data               = (void *)ctx;
225:   handler->ops->destroy       = PetscLogHandlerDestroy_Ex7;
226:   handler->ops->view          = PetscLogHandlerView_Ex7;
227:   handler->ops->eventbegin    = PetscLogHandlerEventBegin_Ex7;
228:   handler->ops->eventend      = PetscLogHandlerEventEnd_Ex7;
229:   handler->ops->eventsync     = PetscLogHandlerEventSync_Ex7;
230:   handler->ops->objectcreate  = PetscLogHandlerObjectCreate_Ex7;
231:   handler->ops->objectdestroy = PetscLogHandlerObjectDestroy_Ex7;
232:   handler->ops->stagepush     = PetscLogHandlerStagePush_Ex7;
233:   handler->ops->stagepop      = PetscLogHandlerStagePop_Ex7;
234:   PetscCall(PetscObjectComposeFunction((PetscObject)handler, "PetscLogHandlerLogObjectState_C", PetscLogHandlerLogObjectState_Ex7));
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

238: int main(int argc, char **argv)
239: {
240:   PetscClassId        user_classid;
241:   PetscLogEvent       event_1, event_2;
242:   PetscLogStage       stage_1;
243:   PetscContainer      user_object;
244:   PetscLogHandler     h;
245:   PetscLogDouble      time;
246:   PetscLogHandlerType type;

248:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
249:   PetscCall(PetscLogHandlerRegister(PETSCLOGHANDLEREX7, PetscLogHandlerCreate_Ex7));

251:   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &h));
252:   PetscCall(PetscLogHandlerSetType(h, PETSCLOGHANDLEREX7));
253:   PetscCall(PetscLogHandlerGetType(h, &type));
254:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Log handler type is: %s\n", type));
255:   PetscCall(PetscLogHandlerStart(h));

257:   PetscCall(PetscClassIdRegister("User class", &user_classid));
258:   PetscCall(PetscLogEventRegister("Event 1", user_classid, &event_1));
259:   PetscCall(PetscLogEventRegister("Event 2", user_classid, &event_2));
260:   PetscCall(PetscLogStageRegister("Stage 1", &stage_1));

262:   PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
263:   PetscCall(PetscLogStagePush(stage_1));
264:   PetscCall(PetscLogEventBegin(event_2, NULL, NULL, NULL, NULL));
265:   PetscCall(PetscLogEventSync(event_1, PETSC_COMM_WORLD));
266:   PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
267:   PetscCall(PetscTime(&time));
268:   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &user_object));
269:   PetscCall(PetscObjectSetName((PetscObject)user_object, "User Container"));
270:   PetscCall(PetscLogHandlerLogObjectState(h, (PetscObject)user_object, "Created at %e", time));
271:   PetscCall(PetscContainerDestroy(&user_object));
272:   PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));
273:   PetscCall(PetscLogEventEnd(event_2, NULL, NULL, NULL, NULL));
274:   PetscCall(PetscLogStagePop());
275:   PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));

277:   PetscCall(PetscLogHandlerStop(h));
278:   PetscCall(PetscLogHandlerView(h, PETSC_VIEWER_STDOUT_WORLD));
279:   PetscCall(PetscLogHandlerDestroy(&h));
280:   PetscCall(PetscFinalize());
281:   return 0;
282: }

284: /*TEST

286:   test:
287:     requires: defined(PETSC_USE_LOG)
288:     suffix: 0
289:     filter: sed -E "s/:[^:]+:/:time_removed:/g"

291: TEST*/