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*/