Actual source code: logperfstubs.c

      1: #include <petsc/private/logimpl.h>
      2: #include <petsc/private/loghandlerimpl.h>
      3: #include <../src/sys/perfstubs/timer.h>

      5: typedef struct _n_PetscEventPS {
      6:   void *timer;
      7:   int   depth;
      8: } PetscEventPS;

     10: PETSC_LOG_RESIZABLE_ARRAY(PSArray, PetscEventPS, void *, NULL, NULL, NULL)

     12: typedef struct _n_PetscLogHandler_Perfstubs *PetscLogHandler_Perfstubs;

     14: struct _n_PetscLogHandler_Perfstubs {
     15:   PetscLogPSArray events;
     16:   PetscLogPSArray stages;
     17:   PetscBool       started_perfstubs;
     18: };

     20: static PetscErrorCode PetscLogHandlerContextCreate_Perfstubs(PetscLogHandler_Perfstubs *ps_p)
     21: {
     22:   PetscLogHandler_Perfstubs ps;

     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: }

     32: static PetscErrorCode PetscLogHandlerDestroy_Perfstubs(PetscLogHandler h)
     33: {
     34:   PetscInt                  num_events, num_stages;
     35:   PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)h->data;

     37:   PetscFunctionBegin;
     38:   PetscCall(PetscLogPSArrayGetSize(ps->events, &num_events, NULL));
     39:   for (PetscInt i = 0; i < num_events; i++) {
     40:     PetscEventPS event = {NULL, 0};

     42:     PetscCall(PetscLogPSArrayGet(ps->events, i, &event));
     43:     PetscStackCallExternalVoid("ps_timer_destroy_", ps_timer_destroy_(event.timer));
     44:   }
     45:   PetscCall(PetscLogPSArrayDestroy(&ps->events));

     47:   PetscCall(PetscLogPSArrayGetSize(ps->stages, &num_stages, NULL));
     48:   for (PetscInt i = 0; i < num_stages; i++) {
     49:     PetscEventPS stage = {NULL, 0};

     51:     PetscCall(PetscLogPSArrayGet(ps->stages, i, &stage));
     52:     PetscStackCallExternalVoid("ps_timer_destroy_", ps_timer_destroy_(stage.timer));
     53:   }
     54:   PetscCall(PetscLogPSArrayDestroy(&ps->stages));

     56:   if (ps->started_perfstubs) PetscStackCallExternalVoid("ps_finalize_", ps_finalize_());
     57:   PetscCall(PetscFree(ps));
     58:   PetscFunctionReturn(PETSC_SUCCESS);
     59: }

     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;

     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:     PetscLogEvent     ei;

     76:     PetscCall(PetscMPIIntCast(i, &ei));
     77:     PetscCall(PetscLogStateEventGetInfo(state, ei, &event_info));
     78:     PetscStackCallExternalVoid("ps_timer_create_", ps_event.timer = ps_timer_create_(event_info.name));
     79:     ps_event.depth = 0;
     80:     PetscCall(PetscLogPSArrayPush(ps->events, ps_event));
     81:   }
     82:   PetscFunctionReturn(PETSC_SUCCESS);
     83: }

     85: static PetscErrorCode PetscLogHandlerPSUpdateStages(PetscLogHandler h)
     86: {
     87:   PetscLogHandler_Perfstubs ps = (PetscLogHandler_Perfstubs)h->data;
     88:   PetscLogState             state;
     89:   PetscInt                  num_stages, num_stages_old;

     91:   PetscFunctionBegin;
     92:   PetscCall(PetscLogHandlerGetState(h, &state));
     93:   PetscCall(PetscLogStateGetNumStages(state, &num_stages));
     94:   PetscCall(PetscLogPSArrayGetSize(ps->stages, &num_stages_old, NULL));
     95:   for (PetscInt i = num_stages_old; i < num_stages; i++) {
     96:     PetscLogStageInfo stage_info = {NULL};
     97:     PetscEventPS      ps_stage   = {NULL, 0};
     98:     PetscLogEvent     si;

    100:     PetscCall(PetscMPIIntCast(i, &si));
    101:     PetscCall(PetscLogStateStageGetInfo(state, si, &stage_info));
    102:     PetscStackCallExternalVoid("ps_timer_create_", ps_stage.timer = ps_timer_create_(stage_info.name));
    103:     ps_stage.depth = 0;
    104:     PetscCall(PetscLogPSArrayPush(ps->stages, ps_stage));
    105:   }
    106:   PetscFunctionReturn(PETSC_SUCCESS);
    107: }

    109: static PetscErrorCode PetscLogHandlerEventBegin_Perfstubs(PetscLogHandler handler, PetscLogEvent event, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
    110: {
    111:   PetscLogHandler_Perfstubs ps       = (PetscLogHandler_Perfstubs)handler->data;
    112:   PetscEventPS              ps_event = {NULL, 0};

    114:   PetscFunctionBegin;
    115:   if (event >= ps->events->num_entries) PetscCall(PetscLogHandlerPSUpdateEvents(handler));
    116:   PetscCall(PetscLogPSArrayGet(ps->events, event, &ps_event));
    117:   ps_event.depth++;
    118:   PetscCall(PetscLogPSArraySet(ps->events, event, ps_event));
    119:   if (ps_event.depth == 1 && ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_start_", ps_timer_start_(ps_event.timer));
    120:   PetscFunctionReturn(PETSC_SUCCESS);
    121: }

    123: static PetscErrorCode PetscLogHandlerEventEnd_Perfstubs(PetscLogHandler handler, PetscLogEvent event, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
    124: {
    125:   PetscLogHandler_Perfstubs ps       = (PetscLogHandler_Perfstubs)handler->data;
    126:   PetscEventPS              ps_event = {NULL, 0};

    128:   PetscFunctionBegin;
    129:   if (event >= ps->events->num_entries) PetscCall(PetscLogHandlerPSUpdateEvents(handler));
    130:   PetscCall(PetscLogPSArrayGet(ps->events, event, &ps_event));
    131:   ps_event.depth--;
    132:   PetscCall(PetscLogPSArraySet(ps->events, event, ps_event));
    133:   if (ps_event.depth == 0 && ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_stop_", ps_timer_stop_(ps_event.timer));
    134:   PetscFunctionReturn(PETSC_SUCCESS);
    135: }

    137: static PetscErrorCode PetscLogHandlerStagePush_Perfstubs(PetscLogHandler handler, PetscLogStage stage)
    138: {
    139:   PetscLogHandler_Perfstubs ps       = (PetscLogHandler_Perfstubs)handler->data;
    140:   PetscEventPS              ps_event = {NULL, 0};

    142:   PetscFunctionBegin;
    143:   if (stage >= ps->stages->num_entries) PetscCall(PetscLogHandlerPSUpdateStages(handler));
    144:   PetscCall(PetscLogPSArrayGet(ps->stages, stage, &ps_event));
    145:   if (ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_start_", ps_timer_start_(ps_event.timer));
    146:   PetscFunctionReturn(PETSC_SUCCESS);
    147: }

    149: static PetscErrorCode PetscLogHandlerStagePop_Perfstubs(PetscLogHandler handler, PetscLogStage stage)
    150: {
    151:   PetscLogHandler_Perfstubs ps       = (PetscLogHandler_Perfstubs)handler->data;
    152:   PetscEventPS              ps_event = {NULL, 0};

    154:   PetscFunctionBegin;
    155:   if (stage >= ps->stages->num_entries) PetscCall(PetscLogHandlerPSUpdateStages(handler));
    156:   PetscCall(PetscLogPSArrayGet(ps->stages, stage, &ps_event));
    157:   if (ps_event.timer != NULL) PetscStackCallExternalVoid("ps_timer_stop_", ps_timer_stop_(ps_event.timer));
    158:   PetscFunctionReturn(PETSC_SUCCESS);
    159: }

    161: /*MC
    162:   PETSCLOGHANDLERPERFSTUBS - PETSCLOGHANDLERPERFSTUBS = "perfstubs" -  A
    163:   `PetscLogHandler` that collects data for the PerfStubs/TAU instrumentation
    164:   library.  A log handler of this type is created and started by
    165:   `PetscLogPerfstubsBegin()`.

    167:   Level: developer

    169: .seealso: [](ch_profiling), `PetscLogHandler`
    170: M*/

    172: PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Perfstubs(PetscLogHandler handler)
    173: {
    174:   PetscBool                 started_perfstubs;
    175:   PetscLogHandler_Perfstubs lps;

    177:   PetscFunctionBegin;
    178:   if (perfstubs_initialized == PERFSTUBS_UNKNOWN) {
    179:     PetscStackCallExternalVoid("ps_initialize_", ps_initialize_());
    180:     started_perfstubs = PETSC_TRUE;
    181:   } else {
    182:     started_perfstubs = PETSC_FALSE;
    183:   }
    184:   PetscCheck(perfstubs_initialized == PERFSTUBS_SUCCESS, PetscObjectComm((PetscObject)handler), PETSC_ERR_LIB, "perfstubs could not be initialized");
    185:   PetscCall(PetscLogHandlerContextCreate_Perfstubs(&lps));
    186:   lps->started_perfstubs   = started_perfstubs;
    187:   handler->data            = (void *)lps;
    188:   handler->ops->destroy    = PetscLogHandlerDestroy_Perfstubs;
    189:   handler->ops->eventbegin = PetscLogHandlerEventBegin_Perfstubs;
    190:   handler->ops->eventend   = PetscLogHandlerEventEnd_Perfstubs;
    191:   handler->ops->stagepush  = PetscLogHandlerStagePush_Perfstubs;
    192:   handler->ops->stagepop   = PetscLogHandlerStagePop_Perfstubs;
    193:   PetscFunctionReturn(PETSC_SUCCESS);
    194: }