1 #include <petsc/private/logimpl.h> /*I "petscsys.h" I*/ 2 #include <petsc/private/loghandlerimpl.h> 3 #include <../src/sys/perfstubs/timer.h> 4 5 typedef struct _n_PetscEventPS { 6 void *timer; 7 int depth; 8 } PetscEventPS; 9 10 PETSC_LOG_RESIZABLE_ARRAY(PSArray, PetscEventPS, void *, NULL, NULL, NULL) 11 12 typedef struct _n_PetscLogHandler_Perfstubs *PetscLogHandler_Perfstubs; 13 14 struct _n_PetscLogHandler_Perfstubs { 15 PetscLogPSArray events; 16 PetscLogPSArray stages; 17 PetscBool started_perfstubs; 18 }; 19 20 static PetscErrorCode PetscLogHandlerContextCreate_Perfstubs(PetscLogHandler_Perfstubs *ps_p) 21 { 22 PetscLogHandler_Perfstubs ps; 23 24 PetscFunctionBegin; 25 PetscCall(PetscNew(ps_p)); 26 ps = *ps_p; 27 PetscCall(PetscLogPSArrayCreate(128, &ps->events)); 28 PetscCall(PetscLogPSArrayCreate(8, &ps->stages)); 29 PetscFunctionReturn(PETSC_SUCCESS); 30 } 31 32 static PetscErrorCode PetscLogHandlerDestroy_Perfstubs(PetscLogHandler h) 33 { 34 PetscInt num_events, num_stages; 35 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)h->data; 36 37 PetscFunctionBegin; 38 PetscCall(PetscLogPSArrayGetSize(ps->events, &num_events, NULL)); 39 for (PetscInt i = 0; i < num_events; i++) { 40 PetscEventPS event = {NULL, 0}; 41 42 PetscCall(PetscLogPSArrayGet(ps->events, i, &event)); 43 PetscStackCallExternalVoid("ps_timer_destroy_", ps_timer_destroy_(event.timer)); 44 } 45 PetscCall(PetscLogPSArrayDestroy(&ps->events)); 46 47 PetscCall(PetscLogPSArrayGetSize(ps->stages, &num_stages, NULL)); 48 for (PetscInt i = 0; i < num_stages; i++) { 49 PetscEventPS stage = {NULL, 0}; 50 51 PetscCall(PetscLogPSArrayGet(ps->stages, i, &stage)); 52 PetscStackCallExternalVoid("ps_timer_destroy_", ps_timer_destroy_(stage.timer)); 53 } 54 PetscCall(PetscLogPSArrayDestroy(&ps->stages)); 55 56 if (ps->started_perfstubs) PetscStackCallExternalVoid("ps_finalize_", ps_finalize_()); 57 PetscCall(PetscFree(ps)); 58 PetscFunctionReturn(PETSC_SUCCESS); 59 } 60 61 static PetscErrorCode PetscLogHandlerPSUpdateEvents(PetscLogHandler h) 62 { 63 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)h->data; 64 PetscLogState state; 65 PetscInt num_events, num_events_old; 66 67 PetscFunctionBegin; 68 PetscCall(PetscLogHandlerGetState(h, &state)); 69 PetscCall(PetscLogStateGetNumEvents(state, &num_events)); 70 PetscCall(PetscLogPSArrayGetSize(ps->events, &num_events_old, NULL)); 71 for (PetscInt i = num_events_old; i < num_events; i++) { 72 PetscLogEventInfo event_info = {NULL, -1, PETSC_FALSE}; 73 PetscEventPS ps_event = {NULL, 0}; 74 75 PetscCall(PetscLogStateEventGetInfo(state, (PetscLogEvent)i, &event_info)); 76 PetscStackCallExternalVoid("ps_timer_create_", ps_event.timer = ps_timer_create_(event_info.name)); 77 ps_event.depth = 0; 78 PetscCall(PetscLogPSArrayPush(ps->events, ps_event)); 79 } 80 PetscFunctionReturn(PETSC_SUCCESS); 81 } 82 83 static PetscErrorCode PetscLogHandlerPSUpdateStages(PetscLogHandler h) 84 { 85 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)h->data; 86 PetscLogState state; 87 PetscInt num_stages, num_stages_old; 88 89 PetscFunctionBegin; 90 PetscCall(PetscLogHandlerGetState(h, &state)); 91 PetscCall(PetscLogStateGetNumStages(state, &num_stages)); 92 PetscCall(PetscLogPSArrayGetSize(ps->stages, &num_stages_old, NULL)); 93 for (PetscInt i = num_stages_old; i < num_stages; i++) { 94 PetscLogStageInfo stage_info = {NULL}; 95 PetscEventPS ps_stage = {NULL, 0}; 96 97 PetscCall(PetscLogStateStageGetInfo(state, (PetscLogStage)i, &stage_info)); 98 PetscStackCallExternalVoid("ps_timer_create_", ps_stage.timer = ps_timer_create_(stage_info.name)); 99 ps_stage.depth = 0; 100 PetscCall(PetscLogPSArrayPush(ps->stages, ps_stage)); 101 } 102 PetscFunctionReturn(PETSC_SUCCESS); 103 } 104 105 static PetscErrorCode PetscLogHandlerEventBegin_Perfstubs(PetscLogHandler handler, PetscLogEvent event, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) 106 { 107 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)handler->data; 108 PetscEventPS ps_event = {NULL, 0}; 109 110 PetscFunctionBegin; 111 if (event >= ps->events->num_entries) PetscCall(PetscLogHandlerPSUpdateEvents(handler)); 112 PetscCall(PetscLogPSArrayGet(ps->events, event, &ps_event)); 113 ps_event.depth++; 114 PetscCall(PetscLogPSArraySet(ps->events, event, ps_event)); 115 if (ps_event.depth == 1 && ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_start_", ps_timer_start_(ps_event.timer)); 116 PetscFunctionReturn(PETSC_SUCCESS); 117 } 118 119 static PetscErrorCode PetscLogHandlerEventEnd_Perfstubs(PetscLogHandler handler, PetscLogEvent event, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) 120 { 121 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)handler->data; 122 PetscEventPS ps_event = {NULL, 0}; 123 124 PetscFunctionBegin; 125 if (event >= ps->events->num_entries) PetscCall(PetscLogHandlerPSUpdateEvents(handler)); 126 PetscCall(PetscLogPSArrayGet(ps->events, event, &ps_event)); 127 ps_event.depth--; 128 PetscCall(PetscLogPSArraySet(ps->events, event, ps_event)); 129 if (ps_event.depth == 0 && ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_stop_", ps_timer_stop_(ps_event.timer)); 130 PetscFunctionReturn(PETSC_SUCCESS); 131 } 132 133 static PetscErrorCode PetscLogHandlerStagePush_Perfstubs(PetscLogHandler handler, PetscLogStage stage) 134 { 135 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)handler->data; 136 PetscEventPS ps_event = {NULL, 0}; 137 138 PetscFunctionBegin; 139 if (stage >= ps->stages->num_entries) PetscCall(PetscLogHandlerPSUpdateStages(handler)); 140 PetscCall(PetscLogPSArrayGet(ps->stages, stage, &ps_event)); 141 if (ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_start_", ps_timer_start_(ps_event.timer)); 142 PetscFunctionReturn(PETSC_SUCCESS); 143 } 144 145 static PetscErrorCode PetscLogHandlerStagePop_Perfstubs(PetscLogHandler handler, PetscLogStage stage) 146 { 147 PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)handler->data; 148 PetscEventPS ps_event = {NULL, 0}; 149 150 PetscFunctionBegin; 151 if (stage >= ps->stages->num_entries) PetscCall(PetscLogHandlerPSUpdateStages(handler)); 152 PetscCall(PetscLogPSArrayGet(ps->stages, stage, &ps_event)); 153 if (ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_stop_", ps_timer_stop_(ps_event.timer)); 154 PetscFunctionReturn(PETSC_SUCCESS); 155 } 156 157 /*MC 158 PETSCLOGHANDLERPERFSTUBS - PETSCLOGHANDLERPERFSTUBS = "perfstubs" - A 159 `PetscLogHandler` that collects data for the PerfStubs/TAU instrumentation 160 library. A log handler of this type is created and started by 161 `PetscLogPerfstubsBegin()`. 162 163 Level: developer 164 165 .seealso: [](ch_profiling), `PetscLogHandler` 166 M*/ 167 168 PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Perfstubs(PetscLogHandler handler) 169 { 170 PetscBool started_perfstubs; 171 PetscLogHandler_Perfstubs lps; 172 173 PetscFunctionBegin; 174 if (perfstubs_initialized == PERFSTUBS_UNKNOWN) { 175 PetscStackCallExternalVoid("ps_initialize_", ps_initialize_()); 176 started_perfstubs = PETSC_TRUE; 177 } else { 178 started_perfstubs = PETSC_FALSE; 179 } 180 PetscCheck(perfstubs_initialized == PERFSTUBS_SUCCESS, PetscObjectComm((PetscObject)handler), PETSC_ERR_LIB, "perfstubs could not be initialized"); 181 PetscCall(PetscLogHandlerContextCreate_Perfstubs(&lps)); 182 lps->started_perfstubs = started_perfstubs; 183 handler->data = (void *)lps; 184 handler->ops->destroy = PetscLogHandlerDestroy_Perfstubs; 185 handler->ops->eventbegin = PetscLogHandlerEventBegin_Perfstubs; 186 handler->ops->eventend = PetscLogHandlerEventEnd_Perfstubs; 187 handler->ops->stagepush = PetscLogHandlerStagePush_Perfstubs; 188 handler->ops->stagepop = PetscLogHandlerStagePop_Perfstubs; 189 PetscFunctionReturn(PETSC_SUCCESS); 190 } 191