1 static char help[] = "Tests several PetscLogHandler implementations.\n\n"; 2 3 #include <petscsys.h> 4 5 /* Create a phony perfstubs implementation for testing. 6 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) 10 11 PETSC_EXTERN void ps_tool_initialize(void) 12 { 13 PetscFunctionBegin; 14 PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_initialize()\n")); 15 PetscFunctionReturnVoid(); 16 } 17 18 PETSC_EXTERN void ps_tool_finalize(void) 19 { 20 PetscFunctionBegin; 21 PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_finalize()\n")); 22 PetscFunctionReturnVoid(); 23 } 24 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 } 31 32 PETSC_EXTERN void *ps_tool_timer_start(void *arg) 33 { 34 const char *name = (const char *)arg; 35 36 PetscFunctionBegin; 37 PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_timer_start() [%s]\n", name)); 38 PetscFunctionReturn(NULL); 39 } 40 41 PETSC_EXTERN void *ps_tool_timer_stop(void *arg) 42 { 43 const char *name = (const char *)arg; 44 45 PetscFunctionBegin; 46 PetscCallContinue(PetscPrintf(PETSC_COMM_SELF, "ps_tool_timer_stop() [%s]\n", name)); 47 PetscFunctionReturn(NULL); 48 } 49 #endif 50 51 static PetscErrorCode CallEvents(PetscLogEvent event1, PetscLogEvent event2, PetscLogEvent event3) 52 { 53 char *data; 54 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 } 69 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; 76 77 PetscFunctionBeginUser; 78 PetscCall(PetscInitialize(&argc, &argv, NULL, 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 } 95 96 for (PetscInt i = 0; i < 8; i++) { 97 PetscCall(PetscLogEventSetDof(event3, i, (PetscLogDouble)i)); 98 PetscCall(PetscLogEventSetError(event3, i, (PetscLogDouble)i + 8)); 99 } 100 101 PetscCall(CallEvents(event1, event2, event3)); 102 103 PetscCall(PetscLogStagePush(stage1)); 104 { 105 PetscCall(PetscSleep(0.1)); 106 PetscCall(CallEvents(event1, event2, event3)); 107 } 108 PetscCall(PetscLogStagePop()); 109 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)); 114 115 PetscCall(PetscLogStagePush(stage2)); 116 { 117 PetscCall(PetscSleep(0.3)); 118 PetscCall(CallEvents(event1, event2, event3)); 119 120 PetscCall(PetscLogStagePush(stage1)); 121 { 122 PetscCall(PetscSleep(0.1)); 123 PetscCall(CallEvents(event1, event2, event3)); 124 } 125 PetscCall(PetscLogStagePop()); 126 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()); 141 142 PetscCall(PetscContainerDestroy(&container2)); 143 PetscCall(PetscContainerDestroy(&container1)); 144 145 PetscCall(PetscFinalize()); 146 return 0; 147 } 148 149 /*TEST 150 151 # smoke test: does this program run with / without PETSC_USE_LOG? 152 test: 153 suffix: 0 154 nsize: {{1 2}} 155 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" 163 164 test: 165 suffix: 2 166 requires: defined(PETSC_USE_LOG) 167 nsize: 1 168 args: -log_trace 169 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\\)" 178 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" 186 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]" 195 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\\)" 203 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]\\)" 210 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" 218 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 228 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 234 235 TEST*/ 236