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