Actual source code: ex30.c
1: static char help[] = "Tests several PetscLogHandler implementations.\n\n";
3: #include <petscsys.h>
5: /* Create a phony perfstubs implementation for testing.
7: The dynamic loading in perfstubs is only enabled with the following flags,
8: so we only try to export these functions if they are present */
9: #if defined(__linux__) && PetscDefined(HAVE_DLFCN_H)
11: PETSC_EXTERN void ps_tool_initialize(void)
12: {
13: PetscFunctionBegin;
14: PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_initialize()\n"));
15: PetscFunctionReturnVoid();
16: }
18: PETSC_EXTERN void ps_tool_finalize(void)
19: {
20: PetscFunctionBegin;
21: PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_finalize()\n"));
22: PetscFunctionReturnVoid();
23: }
25: PETSC_EXTERN void *ps_tool_timer_create(const char name[])
26: {
27: PetscFunctionBegin;
28: PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_timer_create(\"%s\")\n", name));
29: PetscFunctionReturn((void *)name);
30: }
32: PETSC_EXTERN void *ps_tool_timer_start(void *arg)
33: {
34: const char *name = (const char *)arg;
36: PetscFunctionBegin;
37: PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_timer_start() [%s]\n", name));
38: PetscFunctionReturn(NULL);
39: }
41: PETSC_EXTERN void *ps_tool_timer_stop(void *arg)
42: {
43: const char *name = (const char *)arg;
45: PetscFunctionBegin;
46: PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_timer_stop() [%s]\n", name));
47: PetscFunctionReturn(NULL);
48: }
49: #endif
51: static PetscErrorCode CallEvents(PetscLogEvent event1, PetscLogEvent event2, PetscLogEvent event3)
52: {
53: char *data;
55: PetscFunctionBegin;
56: PetscCall(PetscLogEventBegin(event1, NULL, NULL, NULL, NULL));
57: PetscCall(PetscSleep(0.05));
58: PetscCall(PetscLogEventBegin(event2, NULL, NULL, NULL, NULL));
59: PetscCall(PetscSleep(0.1));
60: PetscCall(PetscLogEventBegin(event3, NULL, NULL, NULL, NULL));
61: PetscCall(PetscCalloc1(1048576, &data));
62: PetscCall(PetscFree(data));
63: PetscCall(PetscSleep(0.15));
64: PetscCall(PetscLogEventEnd(event3, NULL, NULL, NULL, NULL));
65: PetscCall(PetscLogEventEnd(event2, NULL, NULL, NULL, NULL));
66: PetscCall(PetscLogEventEnd(event1, NULL, NULL, NULL, NULL));
67: PetscFunctionReturn(PETSC_SUCCESS);
68: }
70: int main(int argc, char **argv)
71: {
72: PetscLogStage stage1, stage2, stage3 = -1;
73: PetscLogEvent event1, event2, event3;
74: PetscMPIInt rank;
75: PetscContainer container1, container2;
77: PetscFunctionBeginUser;
78: PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
79: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
80: if (rank) {
81: PetscCall(PetscLogEventRegister("Event3", 0, &event3));
82: PetscCall(PetscLogEventRegister("Event2", 0, &event2));
83: PetscCall(PetscLogEventRegister("Event1", PETSC_CONTAINER_CLASSID, &event1));
84: PetscCall(PetscLogStageRegister("Stage2", &stage2));
85: PetscCall(PetscLogStageRegister("Stage1", &stage1));
86: PetscCall(PetscLogStageRegister("Stage3", &stage3));
87: (void)stage3; // stage3 intentionally not used
88: } else {
89: PetscCall(PetscLogEventRegister("Event2", 0, &event2));
90: PetscCall(PetscLogEventRegister("Event1", PETSC_CONTAINER_CLASSID, &event1));
91: PetscCall(PetscLogEventRegister("Event3", 0, &event3));
92: PetscCall(PetscLogStageRegister("Stage1", &stage1));
93: PetscCall(PetscLogStageRegister("Stage2", &stage2));
94: }
96: for (PetscInt i = 0; i < 8; i++) {
97: PetscCall(PetscLogEventSetDof(event3, i, (PetscLogDouble)i));
98: PetscCall(PetscLogEventSetError(event3, i, (PetscLogDouble)i + 8));
99: }
101: PetscCall(CallEvents(event1, event2, event3));
103: PetscCall(PetscLogStagePush(stage1));
104: {
105: PetscCall(PetscSleep(0.1));
106: PetscCall(CallEvents(event1, event2, event3));
107: }
108: PetscCall(PetscLogStagePop());
110: PetscCall(PetscContainerCreate(PETSC_COMM_WORLD, &container1));
111: PetscCall(PetscContainerCreate(PETSC_COMM_WORLD, &container2));
112: PetscCall(PetscObjectSetName((PetscObject)container2, "Container 2"));
113: PetscCall(PetscLogObjectState((PetscObject)container1, "Setting object state for testing purposes with %d self-referential format argument", 1));
115: PetscCall(PetscLogStagePush(stage2));
116: {
117: PetscCall(PetscSleep(0.1));
118: PetscCall(CallEvents(event1, event2, event3));
120: PetscCall(PetscLogStagePush(stage1));
121: {
122: PetscCall(PetscSleep(0.1));
123: PetscCall(CallEvents(event1, event2, event3));
124: }
125: PetscCall(PetscLogStagePop());
127: PetscCall(PetscLogEventSync(event1, PETSC_COMM_WORLD));
128: PetscCall(PetscLogEventBegin(event1, container1, container2, NULL, NULL));
129: {
130: PetscCall(PetscSleep(0.1));
131: PetscCall(PetscLogStagePush(stage1));
132: {
133: PetscCall(PetscSleep(0.1));
134: PetscCall(CallEvents(event1, event2, event3));
135: }
136: PetscCall(PetscLogStagePop());
137: }
138: PetscCall(PetscLogEventEnd(event1, container1, container2, NULL, NULL));
139: }
140: PetscCall(PetscLogStagePop());
142: PetscCall(PetscContainerDestroy(&container2));
143: PetscCall(PetscContainerDestroy(&container1));
145: PetscCall(PetscFinalize());
146: return 0;
147: }
149: /*TEST
151: # smoke test: does this program run with / without PETSC_USE_LOG?
152: test:
153: suffix: 0
154: nsize: {{1 2}}
156: # flamegraph: times of PetscSleep() are designed so the flamegraph should have reproducible entries
157: test:
158: suffix: 1
159: nsize: {{1 2}}
160: requires: defined(PETSC_USE_LOG)
161: args: -log_view ::ascii_flamegraph
162: filter: sed -E "s/ [0-9]+/ time_removed/g"
164: test:
165: suffix: 2
166: requires: defined(PETSC_USE_LOG)
167: nsize: 1
168: args: -log_trace
170: # test PetscLogDump() with action and object logging
171: test:
172: suffix: 3
173: nsize: 1
174: requires: defined(PETSC_USE_LOG)
175: args: -log_include_actions -log_include_objects -log_all
176: temporaries: Log.0
177: filter: cat Log.0 | grep "\\(Actions accomplished\\|Objects created\\|Name\\|Info\\)"
179: # -log_sync is not necessary for csv output, this is just a convenient test to add sync testing to
180: test:
181: suffix: 4
182: nsize: 2
183: requires: defined(PETSC_USE_LOG)
184: args: -log_view ::ascii_csv -log_sync
185: filter: grep "Event[123]" | grep -v "PCMPI"
187: # we don't guarantee clog2print is available, so we just verify that our events are in the output file
188: test:
189: suffix: 5
190: nsize: 1
191: requires: defined(PETSC_USE_LOG) defined(PETSC_HAVE_MPE)
192: args: -log_mpe ex30_mpe
193: temporaries: ex30_mpe.clog2
194: filter: strings ex30_mpe.clog2 | grep "Event[123]"
196: # we don't have tau as a dependency, so we test a dummy perfstubs tool
197: test:
198: suffix: 6
199: nsize: 1
200: requires: tau_perfstubs linux dlfcn_h defined(PETSC_USE_LOG) defined(PETSC_USE_SHARED_LIBRARIES)
201: args: -log_perfstubs
202: filter: grep "\\(Main Stage\\|Event1\\|Event2\\|Event3\\|Stage1\\|Stage2\\)"
204: test:
205: suffix: 7
206: nsize: 1
207: requires: defined(PETSC_USE_LOG)
208: args: -log_view ::ascii_info_detail -log_handler_default_use_threadsafe_events
209: filter: grep "Event[123]" | grep "\\(Main Stage\\|Stage[123]\\)"
211: # test the sync warning
212: test:
213: suffix: 8
214: nsize: 2
215: requires: defined(PETSC_USE_LOG)
216: args: -log_view -log_sync
217: filter: grep "This program was run with logging synchronization"
219: # test -log_trace with an output file
220: test:
221: suffix: 9
222: requires: defined(PETSC_USE_LOG)
223: nsize: 1
224: output_file: output/ex30_2.out
225: args: -log_trace trace.log
226: temporaries: trace.log
227: filter: cat trace.log.0
229: # test -log_nvtx
230: test:
231: suffix: 10
232: requires: cuda defined(PETSC_USE_LOG)
233: args: -device_enable eager -log_nvtx -info :loghandler
235: TEST*/