Date: 2013-07-02T14:39:13+00:00

Actual source code: plog.c
petsc-3.4.2 2013-07-02

      2: /*
      3:       PETSc code to log object creation and destruction and PETSc events.

      5:       This provides the public API used by the rest of PETSc and by users.

      7:       These routines use a private API that is not used elsewhere in PETSc and is not
      8:       accessible to users. The private API is defined in logimpl.h and the utils directory.

     10: */
     11: #include <petsc-private/logimpl.h>        /*I    "petscsys.h"   I*/
     12: #include <petsctime.h>
     13: #include <petscviewer.h>
     14: #include <petscthreadcomm.h>

     16: PetscLogEvent PETSC_LARGEST_EVENT = PETSC_EVENT;

     18: #if defined(PETSC_CLANGUAGE_CXX)
     19: std::map<std::string,PETSc::LogEvent> PETSc::Log::event_registry;
     20: std::map<std::string,PETSc::LogStage> PETSc::Log::stage_registry;
     21: #endif

     23: #if defined(PETSC_USE_LOG)
     24: #include <petscmachineinfo.h>
     25: #include <petscconfiginfo.h>

     27: /* used in the MPI_XXX() count macros in petsclog.h */

     29: /* Action and object logging variables */
     30: Action    *petsc_actions            = NULL;
     31: Object    *petsc_objects            = NULL;
     32: PetscBool petsc_logActions          = PETSC_FALSE;
     33: PetscBool petsc_logObjects          = PETSC_FALSE;
     34: int       petsc_numActions          = 0, petsc_maxActions = 100;
     35: int       petsc_numObjects          = 0, petsc_maxObjects = 100;
     36: int       petsc_numObjectsDestroyed = 0;

     38: /* Global counters */
     39: PetscLogDouble petsc_BaseTime        = 0.0;
     40: PetscLogDouble petsc_TotalFlops      = 0.0;  /* The number of flops */
     41: PetscLogDouble petsc_tmp_flops       = 0.0;  /* The incremental number of flops */
     42: PetscLogDouble petsc_send_ct         = 0.0;  /* The number of sends */
     43: PetscLogDouble petsc_recv_ct         = 0.0;  /* The number of receives */
     44: PetscLogDouble petsc_send_len        = 0.0;  /* The total length of all sent messages */
     45: PetscLogDouble petsc_recv_len        = 0.0;  /* The total length of all received messages */
     46: PetscLogDouble petsc_isend_ct        = 0.0;  /* The number of immediate sends */
     47: PetscLogDouble petsc_irecv_ct        = 0.0;  /* The number of immediate receives */
     48: PetscLogDouble petsc_isend_len       = 0.0;  /* The total length of all immediate send messages */
     49: PetscLogDouble petsc_irecv_len       = 0.0;  /* The total length of all immediate receive messages */
     50: PetscLogDouble petsc_wait_ct         = 0.0;  /* The number of waits */
     51: PetscLogDouble petsc_wait_any_ct     = 0.0;  /* The number of anywaits */
     52: PetscLogDouble petsc_wait_all_ct     = 0.0;  /* The number of waitalls */
     53: PetscLogDouble petsc_sum_of_waits_ct = 0.0;  /* The total number of waits */
     54: PetscLogDouble petsc_allreduce_ct    = 0.0;  /* The number of reductions */
     55: PetscLogDouble petsc_gather_ct       = 0.0;  /* The number of gathers and gathervs */
     56: PetscLogDouble petsc_scatter_ct      = 0.0;  /* The number of scatters and scattervs */

     58: /* Logging functions */
     59: PetscErrorCode (*PetscLogPHC)(PetscObject) = NULL;
     60: PetscErrorCode (*PetscLogPHD)(PetscObject) = NULL;
     61: PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
     62: PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;

     64: /* Tracing event logging variables */
     65: FILE             *petsc_tracefile            = NULL;
     66: int              petsc_tracelevel            = 0;
     67: const char       *petsc_traceblanks          = "                                                                                                    ";
     68: char             petsc_tracespace[128]       = " ";
     69: PetscLogDouble   petsc_tracetime             = 0.0;
     70: static PetscBool PetscLogBegin_PrivateCalled = PETSC_FALSE;

     72: /*---------------------------------------------- General Functions --------------------------------------------------*/
     75: /*@C
     76:   PetscLogDestroy - Destroys the object and event logging data and resets the global counters.

     78:   Not Collective

     80:   Notes:
     81:   This routine should not usually be used by programmers. Instead employ
     82:   PetscLogStagePush() and PetscLogStagePop().

     84:   Level: developer

     86: .keywords: log, destroy
     87: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogView(), PetscLogStagePush(), PlogStagePop()
     88: @*/
     89: PetscErrorCode  PetscLogDestroy(void)
     90: {
     91:   PetscStageLog  stageLog;

     95:   PetscFree(petsc_actions);
     96:   PetscFree(petsc_objects);
     97:   PetscLogSet(NULL, NULL);

     99:   /* Resetting phase */
    100:   PetscLogGetStageLog(&stageLog);
    101:   PetscStageLogDestroy(stageLog);

    103:   petsc_TotalFlops            = 0.0;
    104:   petsc_numActions            = 0;
    105:   petsc_numObjects            = 0;
    106:   petsc_numObjectsDestroyed   = 0;
    107:   petsc_maxActions            = 100;
    108:   petsc_maxObjects            = 100;
    109:   petsc_actions               = NULL;
    110:   petsc_objects               = NULL;
    111:   petsc_logActions            = PETSC_FALSE;
    112:   petsc_logObjects            = PETSC_FALSE;
    113:   petsc_BaseTime              = 0.0;
    114:   petsc_TotalFlops            = 0.0;
    115:   petsc_tmp_flops             = 0.0;
    116:   petsc_send_ct               = 0.0;
    117:   petsc_recv_ct               = 0.0;
    118:   petsc_send_len              = 0.0;
    119:   petsc_recv_len              = 0.0;
    120:   petsc_isend_ct              = 0.0;
    121:   petsc_irecv_ct              = 0.0;
    122:   petsc_isend_len             = 0.0;
    123:   petsc_irecv_len             = 0.0;
    124:   petsc_wait_ct               = 0.0;
    125:   petsc_wait_any_ct           = 0.0;
    126:   petsc_wait_all_ct           = 0.0;
    127:   petsc_sum_of_waits_ct       = 0.0;
    128:   petsc_allreduce_ct          = 0.0;
    129:   petsc_gather_ct             = 0.0;
    130:   petsc_scatter_ct            = 0.0;
    131:   PETSC_LARGEST_EVENT         = PETSC_EVENT;
    132:   PetscLogPHC                 = NULL;
    133:   PetscLogPHD                 = NULL;
    134:   petsc_tracefile             = NULL;
    135:   petsc_tracelevel            = 0;
    136:   petsc_traceblanks           = "                                                                                                    ";
    137:   petsc_tracespace[0]         = ' '; petsc_tracespace[1] = 0;
    138:   petsc_tracetime             = 0.0;
    139:   PETSC_LARGEST_CLASSID       = PETSC_SMALLEST_CLASSID;
    140:   PETSC_OBJECT_CLASSID        = 0;
    141:   petsc_stageLog              = 0;
    142:   PetscLogBegin_PrivateCalled = PETSC_FALSE;
    143:   return(0);
    144: }

    148: /*@C
    149:   PetscLogSet - Sets the logging functions called at the beginning and ending of every event.

    151:   Not Collective

    153:   Input Parameters:
    154: + b - The function called at beginning of event
    155: - e - The function called at end of event

    157:   Level: developer

    159: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogAllBegin(), PetscLogTraceBegin()
    160: @*/
    161: PetscErrorCode  PetscLogSet(PetscErrorCode (*b)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject),
    162:                             PetscErrorCode (*e)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject))
    163: {
    165:   PetscLogPLB = b;
    166:   PetscLogPLE = e;
    167:   return(0);
    168: }

    170: #if defined(PETSC_HAVE_CHUD)
    171: #include <CHUD/CHUD.h>
    172: #endif
    173: #if defined(PETSC_HAVE_PAPI)
    174: #include <papi.h>
    175: int PAPIEventSet = PAPI_NULL;
    176: #endif

    178: /*------------------------------------------- Initialization Functions ----------------------------------------------*/
    181: PetscErrorCode  PetscLogBegin_Private(void)
    182: {
    183:   int            stage;
    184:   PetscBool      opt;

    188:   if (PetscLogBegin_PrivateCalled) return(0);
    189:   PetscLogBegin_PrivateCalled = PETSC_TRUE;

    191:   PetscOptionsHasName(NULL, "-log_exclude_actions", &opt);
    192:   if (opt) petsc_logActions = PETSC_FALSE;
    193:   PetscOptionsHasName(NULL, "-log_exclude_objects", &opt);
    194:   if (opt) petsc_logObjects = PETSC_FALSE;
    195:   if (petsc_logActions) {
    196:     PetscMalloc(petsc_maxActions * sizeof(Action), &petsc_actions);
    197:   }
    198:   if (petsc_logObjects) {
    199:     PetscMalloc(petsc_maxObjects * sizeof(Object), &petsc_objects);
    200:   }
    201:   PetscLogPHC = PetscLogObjCreateDefault;
    202:   PetscLogPHD = PetscLogObjDestroyDefault;
    203:   /* Setup default logging structures */
    204:   PetscStageLogCreate(&petsc_stageLog);
    205:   PetscStageLogRegister(petsc_stageLog, "Main Stage", &stage);
    206: #if defined(PETSC_HAVE_CHUD)
    207:   chudInitialize();
    208:   chudAcquireSamplingFacility(CHUD_BLOCKING);
    209:   chudSetSamplingDevice(chudCPU1Dev);
    210:   chudSetStartDelay(0,chudNanoSeconds);
    211:   chudClearPMCMode(chudCPU1Dev,chudUnused);
    212:   chudClearPMCs();
    213:   /* chudSetPMCMuxPosition(chudCPU1Dev,0,0); */
    214:   printf("%s\n",chudGetEventName(chudCPU1Dev,PMC_1,193));
    215:   printf("%s\n",chudGetEventDescription(chudCPU1Dev,PMC_1,193));
    216:   printf("%s\n",chudGetEventNotes(chudCPU1Dev,PMC_1,193));
    217:   chudSetPMCEvent(chudCPU1Dev,PMC_1,193);
    218:   chudSetPMCMode(chudCPU1Dev,PMC_1,chudCounter);
    219:   chudSetPrivilegeFilter(chudCPU1Dev,PMC_1,chudCountUserEvents);
    220:   chudSetPMCEventMask(chudCPU1Dev,PMC_1,0xFE);
    221:   if (!chudIsEventValid(chudCPU1Dev,PMC_1,193)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Event is not valid %d",193);
    222:   chudStartPMCs();
    223: #endif
    224: #if defined(PETSC_HAVE_PAPI)
    225:   PAPI_library_init(PAPI_VER_CURRENT);
    226:   if (ierr != PAPI_VER_CURRENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot initialize PAPI");
    227:   PAPI_query_event(PAPI_FP_INS);
    228:   PAPI_create_eventset(&PAPIEventSet);
    229:   PAPI_add_event(PAPIEventSet,PAPI_FP_INS);
    230:   PAPI_start(PAPIEventSet);
    231: #endif

    233:   /* All processors sync here for more consistent logging */
    234:   MPI_Barrier(PETSC_COMM_WORLD);
    235:   PetscTime(&petsc_BaseTime);
    236:   PetscLogStagePush(stage);
    237:   return(0);
    238: }

    242: /*@C
    243:   PetscLogBegin - Turns on logging of objects and events. This logs flop
    244:   rates and object creation and should not slow programs down too much.
    245:   This routine may be called more than once.

    247:   Logically Collective over PETSC_COMM_WORLD

    249:   Options Database Keys:
    250: + -log_summary - Prints summary of flop and timing information to the
    251:                   screen (for code compiled with PETSC_USE_LOG)
    252: - -log - Prints detailed log information (for code compiled with PETSC_USE_LOG)

    254:   Usage:
    255: .vb
    256:       PetscInitialize(...);
    257:       PetscLogBegin();
    258:        ... code ...
    259:       PetscLogView(viewer); or PetscLogDump();
    260:       PetscFinalize();
    261: .ve

    263:   Notes:
    264:   PetscLogView(viewer) or PetscLogDump() actually cause the printing of
    265:   the logging information.

    267:   Level: advanced

    269: .keywords: log, begin
    270: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogView(), PetscLogTraceBegin()
    271: @*/
    272: PetscErrorCode  PetscLogBegin(void)
    273: {

    277:   PetscLogSet(PetscLogEventBeginDefault, PetscLogEventEndDefault);
    278:   PetscLogBegin_Private();
    279:   return(0);
    280: }

    284: /*@C
    285:   PetscLogAllBegin - Turns on extensive logging of objects and events. Logs
    286:   all events. This creates large log files and slows the program down.

    288:   Logically Collective on PETSC_COMM_WORLD

    290:   Options Database Keys:
    291: . -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)

    293:   Usage:
    294: .vb
    295:      PetscInitialize(...);
    296:      PetscLogAllBegin();
    297:      ... code ...
    298:      PetscLogDump(filename);
    299:      PetscFinalize();
    300: .ve

    302:   Notes:
    303:   A related routine is PetscLogBegin() (with the options key -log), which is
    304:   intended for production runs since it logs only flop rates and object
    305:   creation (and shouldn't significantly slow the programs).

    307:   Level: advanced

    309: .keywords: log, all, begin
    310: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogTraceBegin()
    311: @*/
    312: PetscErrorCode  PetscLogAllBegin(void)
    313: {

    317:   PetscLogSet(PetscLogEventBeginComplete, PetscLogEventEndComplete);
    318:   PetscLogBegin_Private();
    319:   return(0);
    320: }

    324: /*@
    325:   PetscLogTraceBegin - Activates trace logging.  Every time a PETSc event
    326:   begins or ends, the event name is printed.

    328:   Logically Collective on PETSC_COMM_WORLD

    330:   Input Parameter:
    331: . file - The file to print trace in (e.g. stdout)

    333:   Options Database Key:
    334: . -log_trace [filename] - Activates PetscLogTraceBegin()

    336:   Notes:
    337:   PetscLogTraceBegin() prints the processor number, the execution time (sec),
    338:   then "Event begin:" or "Event end:" followed by the event name.

    340:   PetscLogTraceBegin() allows tracing of all PETSc calls, which is useful
    341:   to determine where a program is hanging without running in the
    342:   debugger.  Can be used in conjunction with the -info option.

    344:   Level: intermediate

    346: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogView(), PetscLogBegin()
    347: @*/
    348: PetscErrorCode  PetscLogTraceBegin(FILE *file)
    349: {

    353:   petsc_tracefile = file;

    355:   PetscLogSet(PetscLogEventBeginTrace, PetscLogEventEndTrace);
    356:   PetscLogBegin_Private();
    357:   return(0);
    358: }

    362: /*@
    363:   PetscLogActions - Determines whether actions are logged for the graphical viewer.

    365:   Not Collective

    367:   Input Parameter:
    368: . flag - PETSC_TRUE if actions are to be logged

    370:   Level: intermediate

    372:   Note: Logging of actions continues to consume more memory as the program
    373:   runs. Long running programs should consider turning this feature off.

    375:   Options Database Keys:
    376: . -log_exclude_actions - Turns off actions logging

    378: .keywords: log, stage, register
    379: .seealso: PetscLogStagePush(), PetscLogStagePop()
    380: @*/
    381: PetscErrorCode  PetscLogActions(PetscBool flag)
    382: {
    384:   petsc_logActions = flag;
    385:   return(0);
    386: }

    390: /*@
    391:   PetscLogObjects - Determines whether objects are logged for the graphical viewer.

    393:   Not Collective

    395:   Input Parameter:
    396: . flag - PETSC_TRUE if objects are to be logged

    398:   Level: intermediate

    400:   Note: Logging of objects continues to consume more memory as the program
    401:   runs. Long running programs should consider turning this feature off.

    403:   Options Database Keys:
    404: . -log_exclude_objects - Turns off objects logging

    406: .keywords: log, stage, register
    407: .seealso: PetscLogStagePush(), PetscLogStagePop()
    408: @*/
    409: PetscErrorCode  PetscLogObjects(PetscBool flag)
    410: {
    412:   petsc_logObjects = flag;
    413:   return(0);
    414: }

    416: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
    419: /*@C
    420:   PetscLogStageRegister - Attaches a charactor string name to a logging stage.

    422:   Not Collective

    424:   Input Parameter:
    425: . sname - The name to associate with that stage

    427:   Output Parameter:
    428: . stage - The stage number

    430:   Level: intermediate

    432: .keywords: log, stage, register
    433: .seealso: PetscLogStagePush(), PetscLogStagePop()
    434: @*/
    435: PetscErrorCode  PetscLogStageRegister(const char sname[],PetscLogStage *stage)
    436: {
    437:   PetscStageLog  stageLog;
    438:   PetscLogEvent  event;

    442:   PetscLogGetStageLog(&stageLog);
    443:   PetscStageLogRegister(stageLog, sname, stage);
    444:   /* Copy events already changed in the main stage, this sucks */
    445:   EventPerfLogEnsureSize(stageLog->stageInfo[*stage].eventLog, stageLog->eventLog->numEvents);
    446:   for (event = 0; event < stageLog->eventLog->numEvents; event++) {
    447:     EventPerfInfoCopy(&stageLog->stageInfo[0].eventLog->eventInfo[event],&stageLog->stageInfo[*stage].eventLog->eventInfo[event]);
    448:   }
    449:   ClassPerfLogEnsureSize(stageLog->stageInfo[*stage].classLog, stageLog->classLog->numClasses);
    450:   return(0);
    451: }

    455: /*@C
    456:   PetscLogStagePush - This function pushes a stage on the stack.

    458:   Not Collective

    460:   Input Parameter:
    461: . stage - The stage on which to log

    463:   Usage:
    464:   If the option -log_sumary is used to run the program containing the
    465:   following code, then 2 sets of summary data will be printed during
    466:   PetscFinalize().
    467: .vb
    468:       PetscInitialize(int *argc,char ***args,0,0);
    469:       [stage 0 of code]
    470:       PetscLogStagePush(1);
    471:       [stage 1 of code]
    472:       PetscLogStagePop();
    473:       PetscBarrier(...);
    474:       [more stage 0 of code]
    475:       PetscFinalize();
    476: .ve

    478:   Notes:
    479:   Use PetscLogStageRegister() to register a stage.

    481:   Level: intermediate

    483: .keywords: log, push, stage
    484: .seealso: PetscLogStagePop(), PetscLogStageRegister(), PetscBarrier()
    485: @*/
    486: PetscErrorCode  PetscLogStagePush(PetscLogStage stage)
    487: {
    488:   PetscStageLog  stageLog;

    492:   PetscLogGetStageLog(&stageLog);
    493:   PetscStageLogPush(stageLog, stage);
    494:   return(0);
    495: }

    499: /*@C
    500:   PetscLogStagePop - This function pops a stage from the stack.

    502:   Not Collective

    504:   Usage:
    505:   If the option -log_sumary is used to run the program containing the
    506:   following code, then 2 sets of summary data will be printed during
    507:   PetscFinalize().
    508: .vb
    509:       PetscInitialize(int *argc,char ***args,0,0);
    510:       [stage 0 of code]
    511:       PetscLogStagePush(1);
    512:       [stage 1 of code]
    513:       PetscLogStagePop();
    514:       PetscBarrier(...);
    515:       [more stage 0 of code]
    516:       PetscFinalize();
    517: .ve

    519:   Notes:
    520:   Use PetscLogStageRegister() to register a stage.

    522:   Level: intermediate

    524: .keywords: log, pop, stage
    525: .seealso: PetscLogStagePush(), PetscLogStageRegister(), PetscBarrier()
    526: @*/
    527: PetscErrorCode  PetscLogStagePop(void)
    528: {
    529:   PetscStageLog  stageLog;

    533:   PetscLogGetStageLog(&stageLog);
    534:   PetscStageLogPop(stageLog);
    535:   return(0);
    536: }

    540: /*@
    541:   PetscLogStageSetActive - Determines stage activity for PetscLogEventBegin() and PetscLogEventEnd().

    543:   Not Collective

    545:   Input Parameters:
    546: + stage    - The stage
    547: - isActive - The activity flag, PETSC_TRUE for logging, else PETSC_FALSE (defaults to PETSC_TRUE)

    549:   Level: intermediate

    551: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogEventBegin(), PetscLogEventEnd(), PetscPreLoadBegin(), PetscPreLoadEnd(), PetscPreLoadStage()
    552: @*/
    553: PetscErrorCode  PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
    554: {
    555:   PetscStageLog  stageLog;

    559:   PetscLogGetStageLog(&stageLog);
    560:   PetscStageLogSetActive(stageLog, stage, isActive);
    561:   return(0);
    562: }

    566: /*@
    567:   PetscLogStageGetActive - Returns stage activity for PetscLogEventBegin() and PetscLogEventEnd().

    569:   Not Collective

    571:   Input Parameter:
    572: . stage    - The stage

    574:   Output Parameter:
    575: . isActive - The activity flag, PETSC_TRUE for logging, else PETSC_FALSE (defaults to PETSC_TRUE)

    577:   Level: intermediate

    579: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogEventBegin(), PetscLogEventEnd(), PetscPreLoadBegin(), PetscPreLoadEnd(), PetscPreLoadStage()
    580: @*/
    581: PetscErrorCode  PetscLogStageGetActive(PetscLogStage stage, PetscBool  *isActive)
    582: {
    583:   PetscStageLog  stageLog;

    587:   PetscLogGetStageLog(&stageLog);
    588:   PetscStageLogGetActive(stageLog, stage, isActive);
    589:   return(0);
    590: }

    594: /*@
    595:   PetscLogStageSetVisible - Determines stage visibility in PetscLogView()

    597:   Not Collective

    599:   Input Parameters:
    600: + stage     - The stage
    601: - isVisible - The visibility flag, PETSC_TRUE to print, else PETSC_FALSE (defaults to PETSC_TRUE)

    603:   Level: intermediate

    605: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogView()
    606: @*/
    607: PetscErrorCode  PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
    608: {
    609:   PetscStageLog  stageLog;

    613:   PetscLogGetStageLog(&stageLog);
    614:   PetscStageLogSetVisible(stageLog, stage, isVisible);
    615:   return(0);
    616: }

    620: /*@
    621:   PetscLogStageGetVisible - Returns stage visibility in PetscLogView()

    623:   Not Collective

    625:   Input Parameter:
    626: . stage     - The stage

    628:   Output Parameter:
    629: . isVisible - The visibility flag, PETSC_TRUE to print, else PETSC_FALSE (defaults to PETSC_TRUE)

    631:   Level: intermediate

    633: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogView()
    634: @*/
    635: PetscErrorCode  PetscLogStageGetVisible(PetscLogStage stage, PetscBool  *isVisible)
    636: {
    637:   PetscStageLog  stageLog;

    641:   PetscLogGetStageLog(&stageLog);
    642:   PetscStageLogGetVisible(stageLog, stage, isVisible);
    643:   return(0);
    644: }

    648: /*@C
    649:   PetscLogStageGetId - Returns the stage id when given the stage name.

    651:   Not Collective

    653:   Input Parameter:
    654: . name  - The stage name

    656:   Output Parameter:
    657: . stage - The stage

    659:   Level: intermediate

    661: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscPreLoadBegin(), PetscPreLoadEnd(), PetscPreLoadStage()
    662: @*/
    663: PetscErrorCode  PetscLogStageGetId(const char name[], PetscLogStage *stage)
    664: {
    665:   PetscStageLog  stageLog;

    669:   PetscLogGetStageLog(&stageLog);
    670:   PetscStageLogGetStage(stageLog, name, stage);
    671:   return(0);
    672: }

    674: /*------------------------------------------------ Event Functions --------------------------------------------------*/
    677: /*@C
    678:   PetscLogEventRegister - Registers an event name for logging operations in an application code.

    680:   Not Collective

    682:   Input Parameter:
    683: + name   - The name associated with the event
    684: - classid - The classid associated to the class for this event, obtain either with
    685:            PetscClassIdRegister() or use a predefined one such as KSP_CLASSID, SNES_CLASSID, the predefined ones
    686:            are only available in C code

    688:   Output Parameter:
    689: . event - The event id for use with PetscLogEventBegin() and PetscLogEventEnd().

    691:   Example of Usage:
    692: .vb
    693:       PetscLogEvent USER_EVENT;
    694:       PetscClassId classid;
    695:       PetscLogDouble user_event_flops;
    696:       PetscClassIdRegister("class name",&classid);
    697:       PetscLogEventRegister("User event name",classid,&USER_EVENT);
    698:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
    699:          [code segment to monitor]
    700:          PetscLogFlops(user_event_flops);
    701:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
    702: .ve

    704:   Notes:
    705:   PETSc automatically logs library events if the code has been
    706:   compiled with -DPETSC_USE_LOG (which is the default) and -log,
    707:   -log_summary, or -log_all are specified.  PetscLogEventRegister() is
    708:   intended for logging user events to supplement this PETSc
    709:   information.

    711:   PETSc can gather data for use with the utilities Jumpshot
    712:   (part of the MPICH distribution).  If PETSc has been compiled
    713:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
    714:   MPICH), the user can employ another command line option, -log_mpe,
    715:   to create a logfile, "mpe.log", which can be visualized
    716:   Jumpshot.

    718:   The classid is associated with each event so that classes of events
    719:   can be disabled simultaneously, such as all matrix events. The user
    720:   can either use an existing classid, such as MAT_CLASSID, or create
    721:   their own as shown in the example.

    723:   Level: intermediate

    725: .keywords: log, event, register
    726: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogFlops(),
    727:           PetscLogEventMPEActivate(), PetscLogEventMPEDeactivate(),
    728:           PetscLogEventActivate(), PetscLogEventDeactivate(), PetscClassIdRegister()
    729: @*/
    730: PetscErrorCode  PetscLogEventRegister(const char name[],PetscClassId classid,PetscLogEvent *event)
    731: {
    732:   PetscStageLog  stageLog;
    733:   int            stage;

    737:   *event = PETSC_DECIDE;
    738:   PetscLogGetStageLog(&stageLog);
    739:   EventRegLogRegister(stageLog->eventLog, name, classid, event);
    740:   for (stage = 0; stage < stageLog->numStages; stage++) {
    741:     EventPerfLogEnsureSize(stageLog->stageInfo[stage].eventLog, stageLog->eventLog->numEvents);
    742:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
    743:   }
    744:   return(0);
    745: }

    749: /*@
    750:   PetscLogEventActivate - Indicates that a particular event should be logged.

    752:   Not Collective

    754:   Input Parameter:
    755: . event - The event id

    757:   Usage:
    758: .vb
    759:       PetscLogEventDeactivate(VEC_SetValues);
    760:         [code where you do not want to log VecSetValues()]
    761:       PetscLogEventActivate(VEC_SetValues);
    762:         [code where you do want to log VecSetValues()]
    763: .ve

    765:   Note:
    766:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
    767:   or an event number obtained with PetscLogEventRegister().

    769:   Level: advanced

    771: .keywords: log, event, activate
    772: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventDeactivate()
    773: @*/
    774: PetscErrorCode  PetscLogEventActivate(PetscLogEvent event)
    775: {
    776:   PetscStageLog  stageLog;
    777:   int            stage;

    781:   PetscLogGetStageLog(&stageLog);
    782:   PetscStageLogGetCurrent(stageLog, &stage);
    783:   EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
    784:   return(0);
    785: }

    789: /*@
    790:   PetscLogEventDeactivate - Indicates that a particular event should not be logged.

    792:   Not Collective

    794:   Input Parameter:
    795: . event - The event id

    797:   Usage:
    798: .vb
    799:       PetscLogEventDeactivate(VEC_SetValues);
    800:         [code where you do not want to log VecSetValues()]
    801:       PetscLogEventActivate(VEC_SetValues);
    802:         [code where you do want to log VecSetValues()]
    803: .ve

    805:   Note:
    806:   The event may be either a pre-defined PETSc event (found in
    807:   include/petsclog.h) or an event number obtained with PetscLogEventRegister()).

    809:   Level: advanced

    811: .keywords: log, event, deactivate
    812: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventActivate()
    813: @*/
    814: PetscErrorCode  PetscLogEventDeactivate(PetscLogEvent event)
    815: {
    816:   PetscStageLog  stageLog;
    817:   int            stage;

    821:   PetscLogGetStageLog(&stageLog);
    822:   PetscStageLogGetCurrent(stageLog, &stage);
    823:   EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
    824:   return(0);
    825: }

    829: /*@
    830:   PetscLogEventSetActiveAll - Sets the event activity in every stage.

    832:   Not Collective

    834:   Input Parameters:
    835: + event    - The event id
    836: - isActive - The activity flag determining whether the event is logged

    838:   Level: advanced

    840: .keywords: log, event, activate
    841: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventActivate(),PlogEventDeactivate()
    842: @*/
    843: PetscErrorCode  PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
    844: {
    845:   PetscStageLog  stageLog;
    846:   int            stage;

    850:   PetscLogGetStageLog(&stageLog);
    851:   for (stage = 0; stage < stageLog->numStages; stage++) {
    852:     if (isActive) {
    853:       EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
    854:     } else {
    855:       EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
    856:     }
    857:   }
    858:   return(0);
    859: }

    863: /*@
    864:   PetscLogEventActivateClass - Activates event logging for a PETSc object class.

    866:   Not Collective

    868:   Input Parameter:
    869: . classid - The event class, for example MAT_CLASSID, SNES_CLASSID, etc.

    871:   Level: developer

    873: .keywords: log, event, activate, class
    874: .seealso: PetscInfoActivate(),PetscInfo(),PetscInfoAllow(),PetscLogEventDeactivateClass(), PetscLogEventActivate(),PetscLogEventDeactivate()
    875: @*/
    876: PetscErrorCode  PetscLogEventActivateClass(PetscClassId classid)
    877: {
    878:   PetscStageLog  stageLog;
    879:   int            stage;

    883:   PetscLogGetStageLog(&stageLog);
    884:   PetscStageLogGetCurrent(stageLog, &stage);
    885:   EventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid);
    886:   return(0);
    887: }

    891: /*@
    892:   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class.

    894:   Not Collective

    896:   Input Parameter:
    897: . classid - The event class, for example MAT_CLASSID, SNES_CLASSID, etc.

    899:   Level: developer

    901: .keywords: log, event, deactivate, class
    902: .seealso: PetscInfoActivate(),PetscInfo(),PetscInfoAllow(),PetscLogEventActivateClass(), PetscLogEventActivate(),PetscLogEventDeactivate()
    903: @*/
    904: PetscErrorCode  PetscLogEventDeactivateClass(PetscClassId classid)
    905: {
    906:   PetscStageLog  stageLog;
    907:   int            stage;

    911:   PetscLogGetStageLog(&stageLog);
    912:   PetscStageLogGetCurrent(stageLog, &stage);
    913:   EventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid);
    914:   return(0);
    915: }

    917: /*MC
    918:    PetscLogEventBegin - Logs the beginning of a user event.

    920:    Synopsis:
    921:    #include "petsclog.h"
    922:    PetscErrorCode PetscLogEventBegin(int e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4)

    924:    Not Collective

    926:    Input Parameters:
    927: +  e - integer associated with the event obtained from PetscLogEventRegister()
    928: -  o1,o2,o3,o4 - objects associated with the event, or 0

    931:    Fortran Synopsis:
    932:    void PetscLogEventBegin(int e,PetscErrorCode ierr)

    934:    Usage:
    935: .vb
    936:      PetscLogEvent USER_EVENT;
    937:      PetscLogDouble user_event_flops;
    938:      PetscLogEventRegister("User event",0,&USER_EVENT);
    939:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
    940:         [code segment to monitor]
    941:         PetscLogFlops(user_event_flops);
    942:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
    943: .ve

    945:    Notes:
    946:    You need to register each integer event with the command
    947:    PetscLogEventRegister().  The source code must be compiled with
    948:    -DPETSC_USE_LOG, which is the default.

    950:    PETSc automatically logs library events if the code has been
    951:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
    952:    specified.  PetscLogEventBegin() is intended for logging user events
    953:    to supplement this PETSc information.

    955:    Level: intermediate

    957: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops()

    959: .keywords: log, event, begin
    960: M*/

    962: /*MC
    963:    PetscLogEventEnd - Log the end of a user event.

    965:    Synopsis:
    966:    #include "petsclog.h"
    967:    PetscErrorCode PetscLogEventEnd(int e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4)

    969:    Not Collective

    971:    Input Parameters:
    972: +  e - integer associated with the event obtained with PetscLogEventRegister()
    973: -  o1,o2,o3,o4 - objects associated with the event, or 0

    976:    Fortran Synopsis:
    977:    void PetscLogEventEnd(int e,PetscErrorCode ierr)

    979:    Usage:
    980: .vb
    981:      PetscLogEvent USER_EVENT;
    982:      PetscLogDouble user_event_flops;
    983:      PetscLogEventRegister("User event",0,&USER_EVENT,);
    984:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
    985:         [code segment to monitor]
    986:         PetscLogFlops(user_event_flops);
    987:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
    988: .ve

    990:    Notes:
    991:    You should also register each additional integer event with the command
    992:    PetscLogEventRegister(). Source code must be compiled with
    993:    -DPETSC_USE_LOG, which is the default.

    995:    PETSc automatically logs library events if the code has been
    996:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
    997:    specified.  PetscLogEventEnd() is intended for logging user events
    998:    to supplement this PETSc information.

    1000:    Level: intermediate

    1002: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogFlops()

    1004: .keywords: log, event, end
    1005: M*/

    1007: /*MC
    1008:    PetscLogEventBarrierBegin - Logs the time in a barrier before an event.

    1010:    Synopsis:
    1011:    #include "petsclog.h"
    1012:    PetscErrorCode PetscLogEventBarrierBegin(int e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4,MPI_Comm comm)

    1014:    Not Collective

    1016:    Input Parameters:
    1017: .  e - integer associated with the event obtained from PetscLogEventRegister()
    1018: .  o1,o2,o3,o4 - objects associated with the event, or 0
    1019: .  comm - communicator the barrier takes place over

    1022:    Usage:
    1023: .vb
    1024:      PetscLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
    1025:        MPI_Allreduce()
    1026:      PetscLogEventBarrierEnd(VEC_NormBarrier,0,0,0,0,comm);
    1027: .ve

    1029:    Notes:
    1030:    This is for logging the amount of time spent in a barrier for an event
    1031:    that requires synchronization.

    1033:    Additional Notes:
    1034:    Synchronization events always come in pairs; for example, VEC_NormBarrier and
    1035:    VEC_NormComm = VEC_NormBarrier + 1

    1037:    Level: advanced

    1039: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventBegin(),
    1040:           PetscLogEventBarrierEnd()

    1042: .keywords: log, event, begin, barrier
    1043: M*/

    1045: /*MC
    1046:    PetscLogEventBarrierEnd - Logs the time in a barrier before an event.

    1048:    Synopsis:
    1049:    #include "petsclog.h"
    1050:    PetscErrorCode PetscLogEventBarrierEnd(int e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4,MPI_Comm comm)

    1052:    Logically Collective on MPI_Comm

    1054:    Input Parameters:
    1055: .  e - integer associated with the event obtained from PetscLogEventRegister()
    1056: .  o1,o2,o3,o4 - objects associated with the event, or 0
    1057: .  comm - communicator the barrier takes place over

    1060:     Usage:
    1061: .vb
    1062:      PetscLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
    1063:        MPI_Allreduce()
    1064:      PetscLogEventBarrierEnd(VEC_NormBarrier,0,0,0,0,comm);
    1065: .ve

    1067:    Notes:
    1068:    This is for logging the amount of time spent in a barrier for an event
    1069:    that requires synchronization.

    1071:    Additional Notes:
    1072:    Synchronization events always come in pairs; for example, VEC_NormBarrier and
    1073:    VEC_NormComm = VEC_NormBarrier + 1

    1075:    Level: advanced

    1077: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventBegin(),
    1078:           PetscLogEventBarrierBegin()

    1080: .keywords: log, event, begin, barrier
    1081: M*/

    1085: /*@C
    1086:   PetscLogEventGetId - Returns the event id when given the event name.

    1088:   Not Collective

    1090:   Input Parameter:
    1091: . name  - The event name

    1093:   Output Parameter:
    1094: . event - The event

    1096:   Level: intermediate

    1098: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogStageGetId()
    1099: @*/
    1100: PetscErrorCode  PetscLogEventGetId(const char name[], PetscLogEvent *event)
    1101: {
    1102:   PetscStageLog  stageLog;

    1106:   PetscLogGetStageLog(&stageLog);
    1107:   EventRegLogGetEvent(stageLog->eventLog, name, event);
    1108:   return(0);
    1109: }

    1112: /*------------------------------------------------ Output Functions -------------------------------------------------*/
    1115: /*@C
    1116:   PetscLogDump - Dumps logs of objects to a file. This file is intended to
    1117:   be read by bin/petscview. This program no longer exists.

    1119:   Collective on PETSC_COMM_WORLD

    1121:   Input Parameter:
    1122: . name - an optional file name

    1124:   Options Database Keys:
    1125: + -log     - Prints basic log information (for code compiled with PETSC_USE_LOG)
    1126: - -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)

    1128:   Usage:
    1129: .vb
    1130:      PetscInitialize(...);
    1131:      PetscLogBegin(); or PetscLogAllBegin();
    1132:      ... code ...
    1133:      PetscLogDump(filename);
    1134:      PetscFinalize();
    1135: .ve

    1137:   Notes:
    1138:   The default file name is
    1139: $    Log.<rank>
    1140:   where <rank> is the processor number. If no name is specified,
    1141:   this file will be used.

    1143:   Level: advanced

    1145: .keywords: log, dump
    1146: .seealso: PetscLogBegin(), PetscLogAllBegin(), PetscLogView()
    1147: @*/
    1148: PetscErrorCode  PetscLogDump(const char sname[])
    1149: {
    1150:   PetscStageLog      stageLog;
    1151:   PetscEventPerfInfo *eventInfo;
    1152:   FILE               *fd;
    1153:   char               file[PETSC_MAX_PATH_LEN], fname[PETSC_MAX_PATH_LEN];
    1154:   PetscLogDouble     flops, _TotalTime;
    1155:   PetscMPIInt        rank;
    1156:   int                action, object, curStage;
    1157:   PetscLogEvent      event;
    1158:   PetscErrorCode     ierr;

    1161:   /* Calculate the total elapsed time */
    1162:   PetscTime(&_TotalTime);
    1163:   _TotalTime -= petsc_BaseTime;
    1164:   /* Open log file */
    1165:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
    1166:   if (sname) sprintf(file, "%s.%d", sname, rank);
    1167:   else sprintf(file, "Log.%d", rank);
    1168:   PetscFixFilename(file, fname);
    1169:   PetscFOpen(PETSC_COMM_WORLD, fname, "w", &fd);
    1170:   if ((!rank) && (!fd)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN, "Cannot open file: %s", fname);
    1171:   /* Output totals */
    1172:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Total Flops %14e %16.8e\n", petsc_TotalFlops, _TotalTime);
    1173:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Clock Resolution %g\n", 0.0);
    1174:   /* Output actions */
    1175:   if (petsc_logActions) {
    1176:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Actions accomplished %d\n", petsc_numActions);
    1177:     for (action = 0; action < petsc_numActions; action++) {
    1178:       PetscFPrintf(PETSC_COMM_WORLD, fd, "%g %d %d %d %d %d %d %g %g %g\n",
    1179:                           petsc_actions[action].time, petsc_actions[action].action, (int)petsc_actions[action].event, (int)petsc_actions[action].classid, petsc_actions[action].id1,
    1180:                           petsc_actions[action].id2, petsc_actions[action].id3, petsc_actions[action].flops, petsc_actions[action].mem, petsc_actions[action].maxmem);
    1181:     }
    1182:   }
    1183:   /* Output objects */
    1184:   if (petsc_logObjects) {
    1185:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Objects created %d destroyed %d\n", petsc_numObjects, petsc_numObjectsDestroyed);
    1186:     for (object = 0; object < petsc_numObjects; object++) {
    1187:       PetscFPrintf(PETSC_COMM_WORLD, fd, "Parent ID: %d Memory: %d\n", petsc_objects[object].parent, (int) petsc_objects[object].mem);
    1188:       if (!petsc_objects[object].name[0]) {
    1189:         PetscFPrintf(PETSC_COMM_WORLD, fd,"No Name\n");
    1190:       } else {
    1191:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Name: %s\n", petsc_objects[object].name);
    1192:       }
    1193:       if (petsc_objects[object].info[0] != 0) {
    1194:         PetscFPrintf(PETSC_COMM_WORLD, fd, "No Info\n");
    1195:       } else {
    1196:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Info: %s\n", petsc_objects[object].info);
    1197:       }
    1198:     }
    1199:   }
    1200:   /* Output events */
    1201:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Event log:\n");
    1202:   PetscLogGetStageLog(&stageLog);
    1203:   PetscIntStackTop(stageLog->stack, &curStage);
    1204:   eventInfo = stageLog->stageInfo[curStage].eventLog->eventInfo;
    1205:   for (event = 0; event < stageLog->stageInfo[curStage].eventLog->numEvents; event++) {
    1206:     if (eventInfo[event].time != 0.0) flops = eventInfo[event].flops/eventInfo[event].time;
    1207:     else flops = 0.0;
    1208:     PetscFPrintf(PETSC_COMM_WORLD, fd, "%d %16d %16g %16g %16g\n", event, eventInfo[event].count,
    1209:                         eventInfo[event].flops, eventInfo[event].time, flops);
    1210:   }
    1211:   PetscFClose(PETSC_COMM_WORLD, fd);
    1212:   return(0);
    1213: }

    1217: /*@C
    1218:   PetscLogViewer - Prints a summary of the logging.

    1220:   Collective over MPI_Comm

    1222:   Input Parameter:
    1223: .  viewer - an ASCII viewer

    1225:   Options Database Keys:
    1226: . -log_summary - Prints summary of log information (for code compiled with PETSC_USE_LOG)

    1228:   Usage:
    1229: .vb
    1230:      PetscInitialize(...);
    1231:      PetscLogBegin();
    1232:      ... code ...
    1233:      PetscLogView(PetscViewer);
    1234:      PetscFinalize(...);
    1235: .ve

    1237:   Notes:
    1238:   By default the summary is printed to stdout.

    1240:   Level: beginner

    1242: .keywords: log, dump, print
    1243: .seealso: PetscLogBegin(), PetscLogDump()
    1244: @*/
    1245: PetscErrorCode  PetscLogView(PetscViewer viewer)
    1246: {
    1247:   FILE               *fd;
    1248:   PetscLogDouble     zero       = 0.0;
    1249:   PetscStageLog      stageLog;
    1250:   PetscStageInfo     *stageInfo = NULL;
    1251:   PetscEventPerfInfo *eventInfo = NULL;
    1252:   PetscClassPerfInfo *classInfo;
    1253:   char               arch[128],hostname[128],username[128],pname[PETSC_MAX_PATH_LEN],date[128];
    1254:   const char         *name;
    1255:   PetscLogDouble     locTotalTime, TotalTime, TotalFlops;
    1256:   PetscLogDouble     numMessages, messageLength, avgMessLen, numReductions;
    1257:   PetscLogDouble     stageTime, flops, flopr, mem, mess, messLen, red;
    1258:   PetscLogDouble     fracTime, fracFlops, fracMessages, fracLength, fracReductions, fracMess, fracMessLen, fracRed;
    1259:   PetscLogDouble     fracStageTime, fracStageFlops, fracStageMess, fracStageMessLen, fracStageRed;
    1260:   PetscLogDouble     min, max, tot, ratio, avg, x, y;
    1261:   PetscLogDouble     minf, maxf, totf, ratf, mint, maxt, tott, ratt, ratCt, totm, totml, totr;
    1262:   PetscMPIInt        minCt, maxCt;
    1263:   PetscMPIInt        size, rank;
    1264:   PetscBool          *localStageUsed,    *stageUsed;
    1265:   PetscBool          *localStageVisible, *stageVisible;
    1266:   int                numStages, localNumEvents, numEvents;
    1267:   int                stage, lastStage, oclass;
    1268:   PetscLogEvent      event;
    1269:   PetscErrorCode     ierr;
    1270:   char               version[256];
    1271:   MPI_Comm           comm;
    1272:   PetscInt           nthreads;

    1275:   PetscObjectGetComm((PetscObject)viewer,&comm);
    1276:   if (!PetscLogBegin_PrivateCalled) SETERRQ(comm, PETSC_ERR_ORDER, "No call to PetscLogBegin() before PetscLogView()");
    1277:   PetscViewerASCIIGetPointer(viewer,&fd);
    1278:   MPI_Comm_size(comm, &size);
    1279:   MPI_Comm_rank(comm, &rank);
    1280:   /* Pop off any stages the user forgot to remove */
    1281:   lastStage = 0;
    1282:   PetscLogGetStageLog(&stageLog);
    1283:   PetscStageLogGetCurrent(stageLog, &stage);
    1284:   while (stage >= 0) {
    1285:     lastStage = stage;
    1286:     PetscStageLogPop(stageLog);
    1287:     PetscStageLogGetCurrent(stageLog, &stage);
    1288:   }
    1289:   /* Get the total elapsed time */
    1290:   PetscTime(&locTotalTime);  locTotalTime -= petsc_BaseTime;

    1292:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
    1293:   PetscFPrintf(comm, fd, "***             WIDEN YOUR WINDOW TO 120 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document            ***\n");
    1294:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
    1295:   PetscFPrintf(comm, fd, "\n---------------------------------------------- PETSc Performance Summary: ----------------------------------------------\n\n");
    1296:   PetscGetArchType(arch,sizeof(arch));
    1297:   PetscGetHostName(hostname,sizeof(hostname));
    1298:   PetscGetUserName(username,sizeof(username));
    1299:   PetscGetProgramName(pname,sizeof(pname));
    1300:   PetscGetDate(date,sizeof(date));
    1301:   PetscGetVersion(version,sizeof(version));
    1302:   if (size == 1) {
    1303:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processor, by %s %s\n", pname, arch, hostname, size, username, date);
    1304:   } else {
    1305:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processors, by %s %s\n", pname, arch, hostname, size, username, date);
    1306:   }
    1307:   PetscThreadCommGetNThreads(PETSC_COMM_WORLD,&nthreads);
    1308:   if (nthreads > 1) {
    1309:     PetscFPrintf(comm,fd,"With %d threads per MPI_Comm\n", (int)nthreads);
    1310:   }

    1312:   PetscFPrintf(comm, fd, "Using %s\n", version);

    1314:   /* Must preserve reduction count before we go on */
    1315:   red = petsc_allreduce_ct + petsc_gather_ct + petsc_scatter_ct;

    1317:   /* Calculate summary information */
    1318:   PetscFPrintf(comm, fd, "\n                         Max       Max/Min        Avg      Total \n");
    1319:   /*   Time */
    1320:   MPI_Allreduce(&locTotalTime, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1321:   MPI_Allreduce(&locTotalTime, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1322:   MPI_Allreduce(&locTotalTime, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1323:   avg  = (tot)/((PetscLogDouble) size);
    1324:   if (min != 0.0) ratio = max/min;
    1325:   else ratio = 0.0;
    1326:   PetscFPrintf(comm, fd, "Time (sec):           %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
    1327:   TotalTime = tot;
    1328:   /*   Objects */
    1329:   avg  = (PetscLogDouble) petsc_numObjects;
    1330:   MPI_Allreduce(&avg,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1331:   MPI_Allreduce(&avg,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1332:   MPI_Allreduce(&avg,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1333:   avg  = (tot)/((PetscLogDouble) size);
    1334:   if (min != 0.0) ratio = max/min;
    1335:   else ratio = 0.0;
    1336:   PetscFPrintf(comm, fd, "Objects:              %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
    1337:   /*   Flops */
    1338:   MPI_Allreduce(&petsc_TotalFlops,  &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1339:   MPI_Allreduce(&petsc_TotalFlops,  &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1340:   MPI_Allreduce(&petsc_TotalFlops,  &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1341:   avg  = (tot)/((PetscLogDouble) size);
    1342:   if (min != 0.0) ratio = max/min;
    1343:   else ratio = 0.0;
    1344:   PetscFPrintf(comm, fd, "Flops:                %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
    1345:   TotalFlops = tot;
    1346:   /*   Flops/sec -- Must talk to Barry here */
    1347:   if (locTotalTime != 0.0) flops = petsc_TotalFlops/locTotalTime;
    1348:   else flops = 0.0;
    1349:   MPI_Allreduce(&flops,        &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1350:   MPI_Allreduce(&flops,        &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1351:   MPI_Allreduce(&flops,        &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1352:   avg  = (tot)/((PetscLogDouble) size);
    1353:   if (min != 0.0) ratio = max/min;
    1354:   else ratio = 0.0;
    1355:   PetscFPrintf(comm, fd, "Flops/sec:            %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
    1356:   /*   Memory */
    1357:   PetscMallocGetMaximumUsage(&mem);
    1358:   if (mem > 0.0) {
    1359:     MPI_Allreduce(&mem,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1360:     MPI_Allreduce(&mem,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1361:     MPI_Allreduce(&mem,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1362:     avg  = (tot)/((PetscLogDouble) size);
    1363:     if (min != 0.0) ratio = max/min;
    1364:     else ratio = 0.0;
    1365:     PetscFPrintf(comm, fd, "Memory:               %5.3e   %10.5f              %5.3e\n", max, ratio, tot);
    1366:   }
    1367:   /*   Messages */
    1368:   mess = 0.5*(petsc_irecv_ct + petsc_isend_ct + petsc_recv_ct + petsc_send_ct);
    1369:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1370:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1371:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1372:   avg  = (tot)/((PetscLogDouble) size);
    1373:   if (min != 0.0) ratio = max/min;
    1374:   else ratio = 0.0;
    1375:   PetscFPrintf(comm, fd, "MPI Messages:         %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
    1376:   numMessages = tot;
    1377:   /*   Message Lengths */
    1378:   mess = 0.5*(petsc_irecv_len + petsc_isend_len + petsc_recv_len + petsc_send_len);
    1379:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1380:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1381:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1382:   if (numMessages != 0) avg = (tot)/(numMessages);
    1383:   else avg = 0.0;
    1384:   if (min != 0.0) ratio = max/min;
    1385:   else ratio = 0.0;
    1386:   PetscFPrintf(comm, fd, "MPI Message Lengths:  %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
    1387:   messageLength = tot;
    1388:   /*   Reductions */
    1389:   MPI_Allreduce(&red,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1390:   MPI_Allreduce(&red,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1391:   MPI_Allreduce(&red,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1392:   if (min != 0.0) ratio = max/min;
    1393:   else ratio = 0.0;
    1394:   PetscFPrintf(comm, fd, "MPI Reductions:       %5.3e   %10.5f\n", max, ratio);
    1395:   numReductions = red; /* wrong because uses count from process zero */
    1396:   PetscFPrintf(comm, fd, "\nFlop counting convention: 1 flop = 1 real number operation of type (multiply/divide/add/subtract)\n");
    1397:   PetscFPrintf(comm, fd, "                            e.g., VecAXPY() for real vectors of length N --> 2N flops\n");
    1398:   PetscFPrintf(comm, fd, "                            and VecAXPY() for complex vectors of length N --> 8N flops\n");

    1400:   /* Get total number of stages --
    1401:        Currently, a single processor can register more stages than another, but stages must all be registered in order.
    1402:        We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
    1403:        This seems best accomplished by assoicating a communicator with each stage.
    1404:   */
    1405:   MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm);
    1406:   PetscMalloc(numStages * sizeof(PetscBool), &localStageUsed);
    1407:   PetscMalloc(numStages * sizeof(PetscBool), &stageUsed);
    1408:   PetscMalloc(numStages * sizeof(PetscBool), &localStageVisible);
    1409:   PetscMalloc(numStages * sizeof(PetscBool), &stageVisible);
    1410:   if (numStages > 0) {
    1411:     stageInfo = stageLog->stageInfo;
    1412:     for (stage = 0; stage < numStages; stage++) {
    1413:       if (stage < stageLog->numStages) {
    1414:         localStageUsed[stage]    = stageInfo[stage].used;
    1415:         localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
    1416:       } else {
    1417:         localStageUsed[stage]    = PETSC_FALSE;
    1418:         localStageVisible[stage] = PETSC_TRUE;
    1419:       }
    1420:     }
    1421:     MPI_Allreduce(localStageUsed,    stageUsed,    numStages, MPIU_BOOL, MPI_LOR,  comm);
    1422:     MPI_Allreduce(localStageVisible, stageVisible, numStages, MPIU_BOOL, MPI_LAND, comm);
    1423:     for (stage = 0; stage < numStages; stage++) {
    1424:       if (stageUsed[stage]) {
    1425:         PetscFPrintf(comm, fd, "\nSummary of Stages:   ----- Time ------  ----- Flops -----  --- Messages ---  -- Message Lengths --  -- Reductions --\n");
    1426:         PetscFPrintf(comm, fd, "                        Avg     %%Total     Avg     %%Total   counts   %%Total     Avg         %%Total   counts   %%Total \n");
    1427:         break;
    1428:       }
    1429:     }
    1430:     for (stage = 0; stage < numStages; stage++) {
    1431:       if (!stageUsed[stage]) continue;
    1432:       if (localStageUsed[stage]) {
    1433:         MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1434:         MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1435:         MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1436:         MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1437:         MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1438:         name = stageInfo[stage].name;
    1439:       } else {
    1440:         MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1441:         MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1442:         MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1443:         MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1444:         MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1445:         name = "";
    1446:       }
    1447:       mess *= 0.5; messLen *= 0.5; red /= size;
    1448:       if (TotalTime     != 0.0) fracTime       = stageTime/TotalTime;    else fracTime       = 0.0;
    1449:       if (TotalFlops    != 0.0) fracFlops      = flops/TotalFlops;       else fracFlops      = 0.0;
    1450:       /* Talk to Barry if (stageTime     != 0.0) flops          = (size*flops)/stageTime; else flops          = 0.0; */
    1451:       if (numMessages   != 0.0) fracMessages   = mess/numMessages;       else fracMessages   = 0.0;
    1452:       if (numMessages   != 0.0) avgMessLen     = messLen/numMessages;    else avgMessLen     = 0.0;
    1453:       if (messageLength != 0.0) fracLength     = messLen/messageLength;  else fracLength     = 0.0;
    1454:       if (numReductions != 0.0) fracReductions = red/numReductions;      else fracReductions = 0.0;
    1455:       PetscFPrintf(comm, fd, "%2d: %15s: %6.4e %5.1f%%  %6.4e %5.1f%%  %5.3e %5.1f%%  %5.3e      %5.1f%%  %5.3e %5.1f%% \n",
    1456:                           stage, name, stageTime/size, 100.0*fracTime, flops, 100.0*fracFlops,
    1457:                           mess, 100.0*fracMessages, avgMessLen, 100.0*fracLength, red, 100.0*fracReductions);
    1458:     }
    1459:   }

    1461:   PetscFPrintf(comm, fd,"\n------------------------------------------------------------------------------------------------------------------------\n");
    1462:   PetscFPrintf(comm, fd, "See the 'Profiling' chapter of the users' manual for details on interpreting output.\n");
    1463:   PetscFPrintf(comm, fd, "Phase summary info:\n");
    1464:   PetscFPrintf(comm, fd, "   Count: number of times phase was executed\n");
    1465:   PetscFPrintf(comm, fd, "   Time and Flops: Max - maximum over all processors\n");
    1466:   PetscFPrintf(comm, fd, "                   Ratio - ratio of maximum to minimum over all processors\n");
    1467:   PetscFPrintf(comm, fd, "   Mess: number of messages sent\n");
    1468:   PetscFPrintf(comm, fd, "   Avg. len: average message length (bytes)\n");
    1469:   PetscFPrintf(comm, fd, "   Reduct: number of global reductions\n");
    1470:   PetscFPrintf(comm, fd, "   Global: entire computation\n");
    1471:   PetscFPrintf(comm, fd, "   Stage: stages of a computation. Set stages with PetscLogStagePush() and PetscLogStagePop().\n");
    1472:   PetscFPrintf(comm, fd, "      %%T - percent time in this phase         %%F - percent flops in this phase\n");
    1473:   PetscFPrintf(comm, fd, "      %%M - percent messages in this phase     %%L - percent message lengths in this phase\n");
    1474:   PetscFPrintf(comm, fd, "      %%R - percent reductions in this phase\n");
    1475:   PetscFPrintf(comm, fd, "   Total Mflop/s: 10e-6 * (sum of flops over all processors)/(max time over all processors)\n");
    1476:   PetscFPrintf(comm, fd, "------------------------------------------------------------------------------------------------------------------------\n");

    1478: #if defined(PETSC_USE_DEBUG)
    1479:   PetscFPrintf(comm, fd, "\n\n");
    1480:   PetscFPrintf(comm, fd, "      ##########################################################\n");
    1481:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1482:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
    1483:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1484:   PetscFPrintf(comm, fd, "      #   This code was compiled with a debugging option,      #\n");
    1485:   PetscFPrintf(comm, fd, "      #   To get timing results run ./configure                #\n");
    1486:   PetscFPrintf(comm, fd, "      #   using --with-debugging=no, the performance will      #\n");
    1487:   PetscFPrintf(comm, fd, "      #   be generally two or three times faster.              #\n");
    1488:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1489:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
    1490: #endif
    1491: #if defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_FORTRAN_KERNELS)
    1492:   PetscFPrintf(comm, fd, "\n\n");
    1493:   PetscFPrintf(comm, fd, "      ##########################################################\n");
    1494:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1495:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
    1496:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1497:   PetscFPrintf(comm, fd, "      #   The code for various complex numbers numerical       #\n");
    1498:   PetscFPrintf(comm, fd, "      #   kernels uses C++, which generally is not well        #\n");
    1499:   PetscFPrintf(comm, fd, "      #   optimized.  For performance that is about 4-5 times  #\n");
    1500:   PetscFPrintf(comm, fd, "      #   faster, specify --with-fortran-kernels=1             #\n");
    1501:   PetscFPrintf(comm, fd, "      #   when running ./configure.py.                         #\n");
    1502:   PetscFPrintf(comm, fd, "      #                                                        #\n");
    1503:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
    1504: #endif

    1506:   /* Report events */
    1507:   PetscFPrintf(comm, fd,"Event                Count      Time (sec)     Flops                             --- Global ---  --- Stage ---   Total\n");
    1508:   PetscFPrintf(comm, fd,"                   Max Ratio  Max     Ratio   Max  Ratio  Mess   Avg len Reduct  %%T %%F %%M %%L %%R  %%T %%F %%M %%L %%R Mflop/s\n");
    1509:   PetscFPrintf(comm,fd,"------------------------------------------------------------------------------------------------------------------------\n");

    1511:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
    1512:   for (stage = 0; stage < numStages; stage++) {
    1513:     if (!stageVisible[stage]) continue;
    1514:     if (localStageUsed[stage]) {
    1515:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
    1516:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1517:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1518:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1519:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1520:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1521:     } else {
    1522:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
    1523:       MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1524:       MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1525:       MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1526:       MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1527:       MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1528:     }
    1529:     mess *= 0.5; messLen *= 0.5; red /= size;

    1531:     /* Get total number of events in this stage --
    1532:        Currently, a single processor can register more events than another, but events must all be registered in order,
    1533:        just like stages. We can removed this requirement if necessary by having a global event numbering and indirection
    1534:        on the event ID. This seems best accomplished by assoicating a communicator with each stage.

    1536:        Problem: If the event did not happen on proc 1, its name will not be available.
    1537:        Problem: Event visibility is not implemented
    1538:     */
    1539:     if (localStageUsed[stage]) {
    1540:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
    1541:       localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
    1542:     } else localNumEvents = 0;
    1543:     MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm);
    1544:     for (event = 0; event < numEvents; event++) {
    1545:       if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents) && (eventInfo[event].depth == 0)) {
    1546:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) flopr = eventInfo[event].flops;
    1547:         else flopr = 0.0;

    1549:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1550:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1551:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1552:         MPI_Allreduce(&eventInfo[event].time,          &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1553:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1554:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1555:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1556:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1557:         MPI_Allreduce(&eventInfo[event].numReductions, &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1558:         MPI_Allreduce(&eventInfo[event].count,         &minCt, 1, MPI_INT,             MPI_MIN, comm);
    1559:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, comm);
    1560:         name = stageLog->eventLog->eventInfo[event].name;
    1561:       } else {
    1562:         flopr = 0.0;
    1563:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1564:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1565:         MPI_Allreduce(&zero,                           &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1566:         MPI_Allreduce(&zero,                           &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
    1567:         MPI_Allreduce(&zero,                           &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
    1568:         MPI_Allreduce(&zero,                           &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1569:         MPI_Allreduce(&zero,                           &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1570:         MPI_Allreduce(&zero,                           &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1571:         MPI_Allreduce(&zero,                           &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    1572:         MPI_Allreduce(&ierr,                           &minCt, 1, MPI_INT,             MPI_MIN, comm);
    1573:         MPI_Allreduce(&ierr,                           &maxCt, 1, MPI_INT,             MPI_MAX, comm);
    1574:         name  = "";
    1575:       }
    1576:       if (mint < 0.0) {
    1577:         PetscFPrintf(comm, fd, "WARNING!!! Minimum time %g over all processors for %s is negative! This happens\n on some machines whose times cannot handle too rapid calls.!\n artificially changing minimum to zero.\n",mint,name);
    1578:         mint = 0;
    1579:       }
    1580:       if (minf < 0.0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Minimum flops %g over all processors for %s is negative! Not possible!",minf,name);
    1581:       totm *= 0.5; totml *= 0.5; totr /= size;

    1583:       if (maxCt != 0) {
    1584:         if (minCt         != 0)   ratCt            = ((PetscLogDouble) maxCt)/minCt; else ratCt            = 0.0;
    1585:         if (mint          != 0.0) ratt             = maxt/mint;                  else ratt             = 0.0;
    1586:         if (minf          != 0.0) ratf             = maxf/minf;                  else ratf             = 0.0;
    1587:         if (TotalTime     != 0.0) fracTime         = tott/TotalTime;             else fracTime         = 0.0;
    1588:         if (TotalFlops    != 0.0) fracFlops        = totf/TotalFlops;            else fracFlops        = 0.0;
    1589:         if (stageTime     != 0.0) fracStageTime    = tott/stageTime;             else fracStageTime    = 0.0;
    1590:         if (flops         != 0.0) fracStageFlops   = totf/flops;                 else fracStageFlops   = 0.0;
    1591:         if (numMessages   != 0.0) fracMess         = totm/numMessages;           else fracMess         = 0.0;
    1592:         if (messageLength != 0.0) fracMessLen      = totml/messageLength;        else fracMessLen      = 0.0;
    1593:         if (numReductions != 0.0) fracRed          = totr/numReductions;         else fracRed          = 0.0;
    1594:         if (mess          != 0.0) fracStageMess    = totm/mess;                  else fracStageMess    = 0.0;
    1595:         if (messLen       != 0.0) fracStageMessLen = totml/messLen;              else fracStageMessLen = 0.0;
    1596:         if (red           != 0.0) fracStageRed     = totr/red;                   else fracStageRed     = 0.0;
    1597:         if (totm          != 0.0) totml           /= totm;                       else totml            = 0.0;
    1598:         if (maxt          != 0.0) flopr            = totf/maxt;                  else flopr            = 0.0;
    1599:         if (fracStageTime > 1.00)  PetscFPrintf(comm, fd,"Warning -- total time of even greater than time of entire stage -- something is wrong with the timer\n");
    1600:         PetscFPrintf(comm, fd,
    1601:           "%-16s %7d%4.1f %5.4e%4.1f %3.2e%4.1f %2.1e %2.1e %2.1e%3.0f%3.0f%3.0f%3.0f%3.0f %3.0f%3.0f%3.0f%3.0f%3.0f %5.0f\n",
    1602:                             name, maxCt, ratCt, maxt, ratt, maxf, ratf, totm, totml, totr,
    1603:                             100.0*fracTime, 100.0*fracFlops, 100.0*fracMess, 100.0*fracMessLen, 100.0*fracRed,
    1604:                             100.0*fracStageTime, 100.0*fracStageFlops, 100.0*fracStageMess, 100.0*fracStageMessLen, 100.0*fracStageRed,
    1605:                             PetscAbsReal(flopr/1.0e6));
    1606:       }
    1607:     }
    1608:   }

    1610:   /* Memory usage and object creation */
    1611:   PetscFPrintf(comm, fd, "------------------------------------------------------------------------------------------------------------------------\n");
    1612:   PetscFPrintf(comm, fd, "\n");
    1613:   PetscFPrintf(comm, fd, "Memory usage is given in bytes:\n\n");

    1615:   /* Right now, only stages on the first processor are reported here, meaning only objects associated with
    1616:      the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
    1617:      stats for stages local to processor sets.
    1618:   */
    1619:   /* We should figure out the longest object name here (now 20 characters) */
    1620:   PetscFPrintf(comm, fd, "Object Type          Creations   Destructions     Memory  Descendants' Mem.\n");
    1621:   PetscFPrintf(comm, fd, "Reports information only for process 0.\n");
    1622:   for (stage = 0; stage < numStages; stage++) {
    1623:     if (localStageUsed[stage]) {
    1624:       classInfo = stageLog->stageInfo[stage].classLog->classInfo;
    1625:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
    1626:       for (oclass = 0; oclass < stageLog->stageInfo[stage].classLog->numClasses; oclass++) {
    1627:         if ((classInfo[oclass].creations > 0) || (classInfo[oclass].destructions > 0)) {
    1628:           PetscFPrintf(comm, fd, "%20s %5d          %5d  %11.0f     %g\n", stageLog->classLog->classInfo[oclass].name,
    1629:                               classInfo[oclass].creations, classInfo[oclass].destructions, classInfo[oclass].mem,
    1630:                               classInfo[oclass].descMem);
    1631:         }
    1632:       }
    1633:     } else {
    1634:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
    1635:     }
    1636:   }

    1638:   PetscFree(localStageUsed);
    1639:   PetscFree(stageUsed);
    1640:   PetscFree(localStageVisible);
    1641:   PetscFree(stageVisible);

    1643:   /* Information unrelated to this particular run */
    1644:   PetscFPrintf(comm, fd, "========================================================================================================================\n");
    1645:   PetscTime(&y);
    1646:   PetscTime(&x);
    1647:   PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y);
    1648:   PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y);
    1649:   PetscFPrintf(comm,fd,"Average time to get PetscTime(): %g\n", (y-x)/10.0);
    1650:   /* MPI information */
    1651:   if (size > 1) {
    1652:     MPI_Status  status;
    1653:     PetscMPIInt tag;
    1654:     MPI_Comm    newcomm;

    1656:     MPI_Barrier(comm);
    1657:     PetscTime(&x);
    1658:     MPI_Barrier(comm);
    1659:     MPI_Barrier(comm);
    1660:     MPI_Barrier(comm);
    1661:     MPI_Barrier(comm);
    1662:     MPI_Barrier(comm);
    1663:     PetscTime(&y);
    1664:     PetscFPrintf(comm, fd, "Average time for MPI_Barrier(): %g\n", (y-x)/5.0);
    1665:     PetscCommDuplicate(comm,&newcomm, &tag);
    1666:     MPI_Barrier(comm);
    1667:     if (rank) {
    1668:       MPI_Recv(0, 0, MPI_INT, rank-1,            tag, newcomm, &status);
    1669:       MPI_Send(0, 0, MPI_INT, (rank+1)%size, tag, newcomm);
    1670:     } else {
    1671:       PetscTime(&x);
    1672:       MPI_Send(0, 0, MPI_INT, 1,          tag, newcomm);
    1673:       MPI_Recv(0, 0, MPI_INT, size-1, tag, newcomm, &status);
    1674:       PetscTime(&y);
    1675:       PetscFPrintf(comm,fd,"Average time for zero size MPI_Send(): %g\n", (y-x)/size);
    1676:     }
    1677:     PetscCommDestroy(&newcomm);
    1678:   }
    1679:   PetscOptionsView(viewer);

    1681:   /* Machine and compile information */
    1682: #if defined(PETSC_USE_FORTRAN_KERNELS)
    1683:   PetscFPrintf(comm, fd, "Compiled with FORTRAN kernels\n");
    1684: #else
    1685:   PetscFPrintf(comm, fd, "Compiled without FORTRAN kernels\n");
    1686: #endif
    1687: #if defined(PETSC_USE_REAL_SINGLE)
    1688:   PetscFPrintf(comm, fd, "Compiled with single precision PetscScalar and PetscReal\n");
    1689: #elif defined(PETSC_USE_LONGDOUBLE)
    1690:   PetscFPrintf(comm, fd, "Compiled with long double precision PetscScalar and PetscReal\n");
    1691: #endif

    1693: #if defined(PETSC_USE_REAL_MAT_SINGLE)
    1694:   PetscFPrintf(comm, fd, "Compiled with single precision matrices\n");
    1695: #else
    1696:   PetscFPrintf(comm, fd, "Compiled with full precision matrices (default)\n");
    1697: #endif
    1698:   PetscFPrintf(comm, fd, "sizeof(short) %d sizeof(int) %d sizeof(long) %d sizeof(void*) %d sizeof(PetscScalar) %d sizeof(PetscInt) %d\n",
    1699:                       (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(void*),(int) sizeof(PetscScalar),(int) sizeof(PetscInt));

    1701:   PetscFPrintf(comm, fd, "Configure run at: %s\n",petscconfigureruntime);
    1702:   PetscFPrintf(comm, fd, "Configure options: %s",petscconfigureoptions);
    1703:   PetscFPrintf(comm, fd, "%s", petscmachineinfo);
    1704:   PetscFPrintf(comm, fd, "%s", petsccompilerinfo);
    1705:   PetscFPrintf(comm, fd, "%s", petsccompilerflagsinfo);
    1706:   PetscFPrintf(comm, fd, "%s", petsclinkerinfo);

    1708:   /* Cleanup */
    1709:   PetscFPrintf(comm, fd, "\n");
    1710:   PetscStageLogPush(stageLog, lastStage);
    1711:   return(0);
    1712: }

    1716: /*@C
    1717:   PetscLogPrintDetailed - Each process prints the times for its own events

    1719:   Collective over MPI_Comm

    1721:   Input Parameter:
    1722: + comm - The MPI communicator (only one processor prints output)
    1723: - file - [Optional] The output file name

    1725:   Options Database Keys:
    1726: . -log_summary_detailed - Prints summary of log information (for code compiled with PETSC_USE_LOG)

    1728:   Usage:
    1729: .vb
    1730:      PetscInitialize(...);
    1731:      PetscLogBegin();
    1732:      ... code ...
    1733:      PetscLogPrintDetailed(MPI_Comm,filename);
    1734:      PetscFinalize(...);
    1735: .ve

    1737:   Notes:
    1738:   By default the summary is printed to stdout.

    1740:   Level: beginner

    1742: .keywords: log, dump, print
    1743: .seealso: PetscLogBegin(), PetscLogDump(), PetscLogView()
    1744: @*/
    1745: PetscErrorCode  PetscLogPrintDetailed(MPI_Comm comm, const char filename[])
    1746: {
    1747:   FILE               *fd = PETSC_STDOUT;
    1748:   PetscStageLog      stageLog;
    1749:   PetscStageInfo     *stageInfo = NULL;
    1750:   PetscEventPerfInfo *eventInfo = NULL;
    1751:   const char         *name      = NULL;
    1752:   PetscLogDouble     TotalTime;
    1753:   PetscLogDouble     stageTime, flops, flopr, mess, messLen, red;
    1754:   PetscLogDouble     maxf, totf, maxt, tott, totm, totml, totr = 0.0;
    1755:   PetscMPIInt        maxCt;
    1756:   PetscBool          *stageUsed;
    1757:   PetscBool          *stageVisible;
    1758:   int                numStages, numEvents;
    1759:   int                stage;
    1760:   PetscLogEvent      event;
    1761:   PetscErrorCode     ierr;

    1764:   if (!PetscLogBegin_PrivateCalled) SETERRQ(comm, PETSC_ERR_ORDER, "No call to PetscLogBegin() before PetscLogPrintDetailed()");
    1765:   /* Pop off any stages the user forgot to remove */
    1766:   PetscLogGetStageLog(&stageLog);
    1767:   PetscStageLogGetCurrent(stageLog, &stage);
    1768:   while (stage >= 0) {
    1769:     PetscStageLogPop(stageLog);
    1770:     PetscStageLogGetCurrent(stageLog, &stage);
    1771:   }
    1772:   /* Get the total elapsed time */
    1773:   PetscTime(&TotalTime);  TotalTime -= petsc_BaseTime;
    1774:   /* Open the summary file */
    1775:   if (filename) {
    1776:     PetscFOpen(comm, filename, "w", &fd);
    1777:   }

    1779:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
    1780:   PetscFPrintf(comm, fd, "***             WIDEN YOUR WINDOW TO 120 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document            ***\n");
    1781:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");

    1784:   numStages = stageLog->numStages;
    1785:   PetscMalloc(numStages * sizeof(PetscBool), &stageUsed);
    1786:   PetscMalloc(numStages * sizeof(PetscBool), &stageVisible);
    1787:   if (numStages > 0) {
    1788:     stageInfo = stageLog->stageInfo;
    1789:     for (stage = 0; stage < numStages; stage++) {
    1790:       if (stage < stageLog->numStages) {
    1791:         stageUsed[stage]    = stageInfo[stage].used;
    1792:         stageVisible[stage] = stageInfo[stage].perfInfo.visible;
    1793:       } else {
    1794:         stageUsed[stage]    = PETSC_FALSE;
    1795:         stageVisible[stage] = PETSC_TRUE;
    1796:       }
    1797:     }
    1798:   }

    1800:   /* Report events */
    1801:   PetscFPrintf(comm, fd,"Event                Count      Time (sec)     Flops/sec                          \n");
    1802:   PetscFPrintf(comm, fd,"                                                            Mess   Avg len Reduct \n");
    1803:   PetscFPrintf(comm,fd,"-----------------------------------------------------------------------------------\n");
    1804:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
    1805:   for (stage = 0; stage < numStages; stage++) {
    1806:     if (!stageVisible[stage]) continue;
    1807:     if (stageUsed[stage]) {
    1808:       PetscSynchronizedFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
    1809:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1810:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1811:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1812:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1813:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1814:     }
    1815:     mess *= 0.5; messLen *= 0.5;

    1817:     /* Get total number of events in this stage --
    1818:     */
    1819:     if (stageUsed[stage]) {
    1820:       eventInfo = stageLog->stageInfo[stage].eventLog->eventInfo;
    1821:       numEvents = stageLog->stageInfo[stage].eventLog->numEvents;
    1822:     } else numEvents = 0;

    1824:     for (event = 0; event < numEvents; event++) {
    1825:       if (stageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents)) {
    1826:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) flopr = eventInfo[event].flops/eventInfo[event].time;
    1827:         else flopr = 0.0;

    1829:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
    1830:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1831:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
    1832:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1833:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1834:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
    1835:         totr  = eventInfo[event].numReductions;
    1836:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, PETSC_COMM_SELF);
    1837:         name  = stageLog->eventLog->eventInfo[event].name;
    1838:         totm *= 0.5; totml *= 0.5;
    1839:       }

    1841:       if (maxCt != 0) {
    1842:         if (totm != 0.0) totml /= totm;
    1843:         else totml = 0.0;
    1844:         PetscSynchronizedFPrintf(comm, fd,"%-16s %7d      %5.4e      %3.2e      %2.1e %2.1e %2.1e\n",name, maxCt,  maxt,  maxf, totm, totml, totr);
    1845:       }
    1846:     }
    1847:   }
    1848:   PetscSynchronizedFlush(comm);

    1850:   PetscFree(stageUsed);
    1851:   PetscFree(stageVisible);

    1853:   PetscFClose(comm, fd);
    1854:   return(0);
    1855: }

    1857: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
    1860: /*@C
    1861:    PetscGetFlops - Returns the number of flops used on this processor
    1862:    since the program began.

    1864:    Not Collective

    1866:    Output Parameter:
    1867:    flops - number of floating point operations

    1869:    Notes:
    1870:    A global counter logs all PETSc flop counts.  The user can use
    1871:    PetscLogFlops() to increment this counter to include flops for the
    1872:    application code.

    1874:    PETSc automatically logs library events if the code has been
    1875:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
    1876:    -log_summary, or -log_all are specified.  PetscLogFlops() is
    1877:    intended for logging user flops to supplement this PETSc
    1878:    information.

    1880:    Level: intermediate

    1882: .keywords: log, flops, floating point operations

    1884: .seealso: PetscTime(), PetscLogFlops()
    1885: @*/
    1886: PetscErrorCode  PetscGetFlops(PetscLogDouble *flops)
    1887: {
    1889:   *flops = petsc_TotalFlops;
    1890:   return(0);
    1891: }

    1895: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
    1896: {
    1898:   size_t         fullLength;
    1899:   va_list        Argp;

    1902:   if (!petsc_logObjects) return(0);
    1903:   va_start(Argp, format);
    1904:   PetscVSNPrintf(petsc_objects[obj->id].info, 64,format,&fullLength, Argp);
    1905:   va_end(Argp);
    1906:   return(0);
    1907: }

    1910: /*MC
    1911:    PetscLogFlops - Adds floating point operations to the global counter.

    1913:    Synopsis:
    1914:    #include "petsclog.h"
    1915:    PetscErrorCode PetscLogFlops(PetscLogDouble f)

    1917:    Not Collective

    1919:    Input Parameter:
    1920: .  f - flop counter

    1923:    Usage:
    1924: .vb
    1925:      PetscLogEvent USER_EVENT;
    1926:      PetscLogEventRegister("User event",0,&USER_EVENT);
    1927:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
    1928:         [code segment to monitor]
    1929:         PetscLogFlops(user_flops)
    1930:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
    1931: .ve

    1933:    Notes:
    1934:    A global counter logs all PETSc flop counts.  The user can use
    1935:    PetscLogFlops() to increment this counter to include flops for the
    1936:    application code.

    1938:    PETSc automatically logs library events if the code has been
    1939:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
    1940:    -log_summary, or -log_all are specified.  PetscLogFlops() is
    1941:    intended for logging user flops to supplement this PETSc
    1942:    information.

    1944:    Level: intermediate

    1946: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PetscGetFlops()

    1948: .keywords: log, flops, floating point operations
    1949: M*/

    1951: /*MC
    1952:    PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice)
    1953:     to get accurate timings

    1955:    Synopsis:
    1956:    #include "petsclog.h"
    1957:    void PetscPreLoadBegin(PetscBool  flag,char *name);

    1959:    Not Collective

    1961:    Input Parameter:
    1962: +   flag - PETSC_TRUE to run twice, PETSC_FALSE to run once, may be overridden
    1963:            with command line option -preload true or -preload false
    1964: -   name - name of first stage (lines of code timed separately with -log_summary) to
    1965:            be preloaded

    1967:    Usage:
    1968: .vb
    1969:      PetscPreLoadBegin(PETSC_TRUE,"first stage);
    1970:        lines of code
    1971:        PetscPreLoadStage("second stage");
    1972:        lines of code
    1973:      PetscPreLoadEnd();
    1974: .ve

    1976:    Notes: Only works in C/C++, not Fortran

    1978:      Flags available within the macro.
    1979: +    PetscPreLoadingUsed - true if we are or have done preloading
    1980: .    PetscPreLoadingOn - true if it is CURRENTLY doing preload
    1981: .    PetscPreLoadIt - 0 for the first computation (with preloading turned off it is only 0) 1 for the second
    1982: -    PetscPreLoadMax - number of times it will do the computation, only one when preloading is turned on
    1983:      The first two variables are available throughout the program, the second two only between the PetscPreLoadBegin()
    1984:      and PetscPreLoadEnd()

    1986:    Level: intermediate

    1988: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PetscPreLoadEnd(), PetscPreLoadStage()

    1990:    Concepts: preloading
    1991:    Concepts: timing^accurate
    1992:    Concepts: paging^eliminating effects of

    1995: M*/

    1997: /*MC
    1998:    PetscPreLoadEnd - End a segment of code that may be preloaded (run twice)
    1999:     to get accurate timings

    2001:    Synopsis:
    2002:    #include "petsclog.h"
    2003:    void PetscPreLoadEnd(void);

    2005:    Not Collective

    2007:    Usage:
    2008: .vb
    2009:      PetscPreLoadBegin(PETSC_TRUE,"first stage);
    2010:        lines of code
    2011:        PetscPreLoadStage("second stage");
    2012:        lines of code
    2013:      PetscPreLoadEnd();
    2014: .ve

    2016:    Notes: only works in C/C++ not fortran

    2018:    Level: intermediate

    2020: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PetscPreLoadBegin(), PetscPreLoadStage()

    2022: M*/

    2024: /*MC
    2025:    PetscPreLoadStage - Start a new segment of code to be timed separately.
    2026:     to get accurate timings

    2028:    Synopsis:
    2029:    #include "petsclog.h"
    2030:    void PetscPreLoadStage(char *name);

    2032:    Not Collective

    2034:    Usage:
    2035: .vb
    2036:      PetscPreLoadBegin(PETSC_TRUE,"first stage);
    2037:        lines of code
    2038:        PetscPreLoadStage("second stage");
    2039:        lines of code
    2040:      PetscPreLoadEnd();
    2041: .ve

    2043:    Notes: only works in C/C++ not fortran

    2045:    Level: intermediate

    2047: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PetscPreLoadBegin(), PetscPreLoadEnd()

    2049: M*/

    2053: /*@
    2054:    PetscLogViewPython - Saves logging information in a Python format.

    2056:    Collective on PetscViewer

    2058:    Input Paramter:
    2059: .   viewer - viewer to save Python data

    2061:   Level: intermediate

    2063: @*/
    2064: PetscErrorCode  PetscLogViewPython(PetscViewer viewer)
    2065: {
    2066:   FILE               *fd;
    2067:   PetscLogDouble     zero                    = 0.0;
    2068:   PetscStageLog      stageLog;
    2069:   PetscStageInfo     *stageInfo              = NULL;
    2070:   PetscEventPerfInfo *eventInfo              = NULL;
    2071:   const char         *name;
    2072:   char               stageName[2048];
    2073:   char               eventName[2048];
    2074:   PetscLogDouble     locTotalTime, TotalTime = 0, TotalFlops = 0;
    2075:   PetscLogDouble     numMessages             = 0, messageLength = 0, avgMessLen, numReductions = 0;
    2076:   PetscLogDouble     stageTime, flops, mem, mess, messLen, red;
    2077:   PetscLogDouble     fracTime, fracFlops, fracMessages, fracLength;
    2078:   PetscLogDouble     fracReductions;
    2079:   PetscLogDouble     tot,avg,x,y,*mydata;
    2080:   PetscMPIInt        maxCt;
    2081:   PetscMPIInt        size, rank, *mycount;
    2082:   PetscBool          *localStageUsed,    *stageUsed;
    2083:   PetscBool          *localStageVisible, *stageVisible;
    2084:   int                numStages, localNumEvents, numEvents;
    2085:   int                stage, lastStage;
    2086:   PetscLogEvent      event;
    2087:   PetscErrorCode     ierr;
    2088:   PetscInt           i;
    2089:   MPI_Comm           comm;

    2092:   PetscObjectGetComm((PetscObject)viewer,&comm);
    2093:   if (!PetscLogBegin_PrivateCalled) SETERRQ(comm, PETSC_ERR_ORDER, "No call to PetscLogBegin() before PetscLogViewPython()");
    2094:   MPI_Comm_size(comm, &size);
    2095:   MPI_Comm_rank(comm, &rank);
    2096:   PetscMalloc(size*sizeof(PetscLogDouble), &mydata);
    2097:   PetscMalloc(size*sizeof(PetscMPIInt), &mycount);
    2098:   PetscViewerASCIIGetPointer(viewer,&fd);

    2100:   /* Pop off any stages the user forgot to remove */
    2101:   lastStage = 0;
    2102:   PetscLogGetStageLog(&stageLog);
    2103:   PetscStageLogGetCurrent(stageLog, &stage);
    2104:   while (stage >= 0) {
    2105:     lastStage = stage;
    2106:     PetscStageLogPop(stageLog);
    2107:     PetscStageLogGetCurrent(stageLog, &stage);
    2108:   }
    2109:   /* Get the total elapsed time */
    2110:   PetscTime(&locTotalTime);  locTotalTime -= petsc_BaseTime;

    2112:   PetscFPrintf(comm, fd, "\n#------ PETSc Performance Summary ----------\n\n");
    2113:   PetscFPrintf(comm, fd, "Nproc = %d\n",size);

    2115:   /* Must preserve reduction count before we go on */
    2116:   red = (petsc_allreduce_ct + petsc_gather_ct + petsc_scatter_ct)/((PetscLogDouble) size);

    2118:   /* Calculate summary information */

    2120:   /*   Time */
    2121:   MPI_Gather(&locTotalTime,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2122:   if (!rank) {
    2123:     PetscFPrintf(comm, fd, "Time = [ ");
    2124:     tot  = 0.0;
    2125:     for (i=0; i<size; i++) {
    2126:       tot += mydata[i];
    2127:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2128:     }
    2129:     PetscFPrintf(comm, fd, "]\n");
    2130:     avg       = (tot)/((PetscLogDouble) size);
    2131:     TotalTime = tot;
    2132:   }

    2134:   /*   Objects */
    2135:   avg  = (PetscLogDouble) petsc_numObjects;
    2136:   MPI_Gather(&avg,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2137:   if (!rank) {
    2138:     PetscFPrintf(comm, fd, "Objects = [ ");
    2139:     for (i=0; i<size; i++) {
    2140:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2141:     }
    2142:     PetscFPrintf(comm, fd, "]\n");
    2143:   }

    2145:   /*   Flops */
    2146:   MPI_Gather(&petsc_TotalFlops,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2147:   if (!rank) {
    2148:     PetscFPrintf(comm, fd, "Flops = [ ");
    2149:     tot  = 0.0;
    2150:     for (i=0; i<size; i++) {
    2151:       tot += mydata[i];
    2152:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2153:     }
    2154:     PetscFPrintf(comm, fd, "]\n");
    2155:     TotalFlops = tot;
    2156:   }

    2158:   /*   Memory */
    2159:   PetscMallocGetMaximumUsage(&mem);
    2160:   MPI_Gather(&mem,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2161:   if (!rank) {
    2162:     PetscFPrintf(comm, fd, "Memory = [ ");
    2163:     for (i=0; i<size; i++) {
    2164:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2165:     }
    2166:     PetscFPrintf(comm, fd, "]\n");
    2167:   }

    2169:   /*   Messages */
    2170:   mess = 0.5*(petsc_irecv_ct + petsc_isend_ct + petsc_recv_ct + petsc_send_ct);
    2171:   MPI_Gather(&mess,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2172:   if (!rank) {
    2173:     PetscFPrintf(comm, fd, "MPIMessages = [ ");
    2174:     tot  = 0.0;
    2175:     for (i=0; i<size; i++) {
    2176:       tot += mydata[i];
    2177:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2178:     }
    2179:     PetscFPrintf(comm, fd, "]\n");
    2180:     numMessages = tot;
    2181:   }

    2183:   /*   Message Lengths */
    2184:   mess = 0.5*(petsc_irecv_len + petsc_isend_len + petsc_recv_len + petsc_send_len);
    2185:   MPI_Gather(&mess,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2186:   if (!rank) {
    2187:     PetscFPrintf(comm, fd, "MPIMessageLengths = [ ");
    2188:     tot  = 0.0;
    2189:     for (i=0; i<size; i++) {
    2190:       tot += mydata[i];
    2191:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2192:     }
    2193:     PetscFPrintf(comm, fd, "]\n");
    2194:     messageLength = tot;
    2195:   }

    2197:   /*   Reductions */
    2198:   MPI_Gather(&red,1,MPIU_PETSCLOGDOUBLE,mydata,1,MPIU_PETSCLOGDOUBLE,0,comm);
    2199:   if (!rank) {
    2200:     PetscFPrintf(comm, fd, "MPIReductions = [ ");
    2201:     tot  = 0.0;
    2202:     for (i=0; i<size; i++) {
    2203:       tot += mydata[i];
    2204:       PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2205:     }
    2206:     PetscFPrintf(comm, fd, "]\n");
    2207:     numReductions = tot;
    2208:   }

    2210:   /* Get total number of stages --
    2211:        Currently, a single processor can register more stages than another, but stages must all be registered in order.
    2212:        We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
    2213:        This seems best accomplished by assoicating a communicator with each stage.
    2214:   */
    2215:   MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm);
    2216:   PetscMalloc(numStages * sizeof(PetscBool), &localStageUsed);
    2217:   PetscMalloc(numStages * sizeof(PetscBool), &stageUsed);
    2218:   PetscMalloc(numStages * sizeof(PetscBool), &localStageVisible);
    2219:   PetscMalloc(numStages * sizeof(PetscBool), &stageVisible);
    2220:   if (numStages > 0) {
    2221:     stageInfo = stageLog->stageInfo;
    2222:     for (stage = 0; stage < numStages; stage++) {
    2223:       if (stage < stageLog->numStages) {
    2224:         localStageUsed[stage]    = stageInfo[stage].used;
    2225:         localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
    2226:       } else {
    2227:         localStageUsed[stage]    = PETSC_FALSE;
    2228:         localStageVisible[stage] = PETSC_TRUE;
    2229:       }
    2230:     }
    2231:     MPI_Allreduce(localStageUsed,    stageUsed,    numStages, MPIU_BOOL, MPI_LOR,  comm);
    2232:     MPI_Allreduce(localStageVisible, stageVisible, numStages, MPIU_BOOL, MPI_LAND, comm);
    2233:     for (stage = 0; stage < numStages; stage++) {
    2234:       if (stageUsed[stage]) {
    2235:         PetscFPrintf(comm, fd, "\n#Summary of Stages:   ----- Time ------  ----- Flops -----  --- Messages ---  -- Message Lengths --  -- Reductions --\n");
    2236:         PetscFPrintf(comm, fd, "#                       Avg     %%Total     Avg     %%Total   counts   %%Total     Avg         %%Total   counts   %%Total \n");
    2237:         break;
    2238:       }
    2239:     }
    2240:     for (stage = 0; stage < numStages; stage++) {
    2241:       if (!stageUsed[stage]) continue;
    2242:       if (localStageUsed[stage]) {
    2243:         MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2244:         MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2245:         MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2246:         MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2247:         MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2248:         name = stageInfo[stage].name;
    2249:       } else {
    2250:         MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2251:         MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2252:         MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2253:         MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2254:         MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2255:         name = "";
    2256:       }
    2257:       mess *= 0.5; messLen *= 0.5; red /= size;
    2258:       if (TotalTime     != 0.0) fracTime       = stageTime/TotalTime;    else fracTime       = 0.0;
    2259:       if (TotalFlops    != 0.0) fracFlops      = flops/TotalFlops;       else fracFlops      = 0.0;
    2260:       /* Talk to Barry if (stageTime     != 0.0) flops          = (size*flops)/stageTime; else flops          = 0.0; */
    2261:       if (numMessages   != 0.0) fracMessages   = mess/numMessages;       else fracMessages   = 0.0;
    2262:       if (numMessages   != 0.0) avgMessLen     = messLen/numMessages;    else avgMessLen     = 0.0;
    2263:       if (messageLength != 0.0) fracLength     = messLen/messageLength;  else fracLength     = 0.0;
    2264:       if (numReductions != 0.0) fracReductions = red/numReductions;      else fracReductions = 0.0;
    2265:       PetscFPrintf(comm, fd, "# ");
    2266:       PetscFPrintf(comm, fd, "%2d: %15s: %6.4e %5.1f%%  %6.4e %5.1f%%  %5.3e %5.1f%%  %5.3e      %5.1f%%  %5.3e %5.1f%% \n",
    2267:                           stage, name, stageTime/size, 100.0*fracTime, flops, 100.0*fracFlops,
    2268:                           mess, 100.0*fracMessages, avgMessLen, 100.0*fracLength, red, 100.0*fracReductions);
    2269:     }
    2270:   }

    2272:   /* Report events */
    2273:   PetscFPrintf(comm,fd,"\n# Event\n");
    2274:   PetscFPrintf(comm,fd,"# ------------------------------------------------------\n");
    2275:   PetscFPrintf(comm,fd,"class Stage(object):\n");
    2276:   PetscFPrintf(comm,fd,"    def __init__(self, name, time, flops, numMessages, messageLength, numReductions):\n");
    2277:   PetscFPrintf(comm,fd,"        # The time and flops represent totals across processes, whereas reductions are only counted once\n");
    2278:   PetscFPrintf(comm,fd,"        self.name          = name\n");
    2279:   PetscFPrintf(comm,fd,"        self.time          = time\n");
    2280:   PetscFPrintf(comm,fd,"        self.flops         = flops\n");
    2281:   PetscFPrintf(comm,fd,"        self.numMessages   = numMessages\n");
    2282:   PetscFPrintf(comm,fd,"        self.messageLength = messageLength\n");
    2283:   PetscFPrintf(comm,fd,"        self.numReductions = numReductions\n");
    2284:   PetscFPrintf(comm,fd,"        self.event         = {}\n");
    2285:   PetscFPrintf(comm,fd, "class Dummy(object):\n");
    2286:   PetscFPrintf(comm,fd, "    pass\n");
    2287:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
    2288:   for (stage = 0; stage < numStages; stage++) {
    2289:     if (!stageVisible[stage]) continue;
    2290:     if (localStageUsed[stage]) {
    2291:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2292:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2293:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2294:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2295:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2296:     } else {
    2297:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
    2298:       MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2299:       MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2300:       MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2301:       MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2302:       MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
    2303:     }
    2304:     mess *= 0.5; messLen *= 0.5; red /= size;

    2306:     /* Get total number of events in this stage --
    2307:        Currently, a single processor can register more events than another, but events must all be registered in order,
    2308:        just like stages. We can removed this requirement if necessary by having a global event numbering and indirection
    2309:        on the event ID. This seems best accomplished by assoicating a communicator with each stage.

    2311:        Problem: If the event did not happen on proc 1, its name will not be available.
    2312:        Problem: Event visibility is not implemented
    2313:     */

    2315:     {
    2316:       size_t len, c;

    2318:       PetscStrcpy(stageName, stageInfo[stage].name);
    2319:       PetscStrlen(stageName, &len);
    2320:       for (c = 0; c < len; ++c) {
    2321:         if (stageName[c] == ' ') stageName[c] = '_';
    2322:       }
    2323:     }
    2324:     if (!rank) {
    2325:       PetscFPrintf(comm, fd, "%s = Stage('%s', %g, %g, %g, %g, %g)\n", stageName, stageName, stageTime, flops, mess, messLen, red);
    2326:     }

    2328:     if (localStageUsed[stage]) {
    2329:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
    2330:       localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
    2331:     } else localNumEvents = 0;

    2333:     MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm);
    2334:     for (event = 0; event < numEvents; event++) {
    2335:       PetscBool      hasEvent = PETSC_TRUE;
    2336:       PetscMPIInt    tmpI;
    2337:       PetscLogDouble tmpR;

    2339:       if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents) && (eventInfo[event].depth == 0)) {
    2340:         size_t len, c;

    2342:         MPI_Allreduce(&eventInfo[event].count, &maxCt, 1, MPI_INT, MPI_MAX, comm);
    2343:         PetscStrcpy(eventName, stageLog->eventLog->eventInfo[event].name);
    2344:         PetscStrlen(eventName, &len);
    2345:         for (c = 0; c < len; ++c) {
    2346:           if (eventName[c] == ' ') eventName[c] = '_';
    2347:         }
    2348:       } else {
    2349:         MPI_Allreduce(&ierr, &maxCt, 1, MPI_INT, MPI_MAX, comm);
    2350:         eventName[0] = 0;
    2351:         hasEvent     = PETSC_FALSE;
    2352:       }

    2354:       if (maxCt != 0) {
    2355:         PetscFPrintf(comm, fd,"#\n");
    2356:         if (!rank) {
    2357:           PetscFPrintf(comm, fd, "%s = Dummy()\n",eventName);
    2358:           PetscFPrintf(comm, fd, "%s.event['%s'] = %s\n",stageName,eventName,eventName);
    2359:         }
    2360:         /* Count */
    2361:         if (hasEvent) tmpI = eventInfo[event].count;
    2362:         else          tmpI = 0;
    2363:         MPI_Gather(&tmpI,1, MPI_INT, mycount, 1, MPI_INT, 0, comm);
    2364:         PetscFPrintf(comm, fd, "%s.Count = [ ", eventName);
    2365:         if (!rank) {
    2366:           for (i=0; i<size; i++) {
    2367:             PetscFPrintf(comm, fd, "  %7d,",mycount[i]);
    2368:           }
    2369:           PetscFPrintf(comm, fd, "]\n");
    2370:         }
    2371:         /* Time */
    2372:         if (hasEvent) tmpR = eventInfo[event].time;
    2373:         else          tmpR = 0.0;
    2374:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2375:         if (!rank) {
    2376:           PetscFPrintf(comm, fd, "%s.Time  = [ ", eventName);
    2377:           for (i=0; i<size; i++) {
    2378:             PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2379:           }
    2380:           PetscFPrintf(comm, fd, "]\n");
    2381:         }
    2382:         if (hasEvent) tmpR = eventInfo[event].time2;
    2383:         else          tmpR = 0.0;
    2384:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2385:         if (!rank) {
    2386:           PetscFPrintf(comm, fd, "%s.Time2 = [ ", eventName);
    2387:           for (i=0; i<size; i++) {
    2388:             PetscFPrintf(comm, fd, "  %5.3e,", mydata[i]);
    2389:           }
    2390:           PetscFPrintf(comm, fd, "]\n");
    2391:         }
    2392:         /* Flops */
    2393:         if (hasEvent) tmpR = eventInfo[event].flops;
    2394:         else          tmpR = 0.0;
    2395:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2396:         if (!rank) {
    2397:           PetscFPrintf(comm, fd, "%s.Flops = [ ", eventName);
    2398:           for (i=0; i<size; i++) {
    2399:             PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2400:           }
    2401:           PetscFPrintf(comm, fd, "]\n");
    2402:         }
    2403:         if (hasEvent) tmpR = eventInfo[event].flops2;
    2404:         else          tmpR = 0.0;
    2405:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2406:         if (!rank) {
    2407:           PetscFPrintf(comm, fd, "%s.Flops2 = [ ", eventName);
    2408:           for (i=0; i<size; i++) {
    2409:             PetscFPrintf(comm, fd, "  %5.3e,", mydata[i]);
    2410:           }
    2411:           PetscFPrintf(comm, fd, "]\n");
    2412:         }
    2413:         /* Num Messages */
    2414:         if (hasEvent) tmpR = eventInfo[event].numMessages;
    2415:         else          tmpR = 0.0;
    2416:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2417:         PetscFPrintf(comm, fd, "%s.NumMessages = [ ", eventName);
    2418:         if (!rank) {
    2419:           for (i=0; i<size; i++) {
    2420:             PetscFPrintf(comm, fd, "  %7.1e,",mydata[i]);
    2421:           }
    2422:           PetscFPrintf(comm, fd, "]\n");
    2423:         }
    2424:         /* Message Length */
    2425:         if (hasEvent) tmpR = eventInfo[event].messageLength;
    2426:         else          tmpR = 0.0;
    2427:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2428:         if (!rank) {
    2429:           PetscFPrintf(comm, fd, "%s.MessageLength = [ ", eventName);
    2430:           for (i=0; i<size; i++) {
    2431:             PetscFPrintf(comm, fd, "  %5.3e,",mydata[i]);
    2432:           }
    2433:           PetscFPrintf(comm, fd, "]\n");
    2434:         }
    2435:         /* Num Reductions */
    2436:         if (hasEvent) tmpR = eventInfo[event].numReductions;
    2437:         else          tmpR = 0.0;
    2438:         MPI_Gather(&tmpR, 1, MPIU_PETSCLOGDOUBLE, mydata, 1, MPIU_PETSCLOGDOUBLE, 0, comm);
    2439:         PetscFPrintf(comm, fd, "%s.NumReductions = [ ", eventName);
    2440:         if (!rank) {
    2441:           for (i=0; i<size; i++) {
    2442:             PetscFPrintf(comm, fd, "  %7.1e,",mydata[i]);
    2443:           }
    2444:           PetscFPrintf(comm, fd, "]\n");
    2445:         }
    2446:       }
    2447:     }
    2448:   }

    2450:   /* Right now, only stages on the first processor are reported here, meaning only objects associated with
    2451:      the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
    2452:      stats for stages local to processor sets.
    2453:   */
    2454:   for (stage = 0; stage < numStages; stage++) {
    2455:     if (!localStageUsed[stage]) {
    2456:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
    2457:     }
    2458:   }

    2460:   PetscFree(localStageUsed);
    2461:   PetscFree(stageUsed);
    2462:   PetscFree(localStageVisible);
    2463:   PetscFree(stageVisible);
    2464:   PetscFree(mydata);
    2465:   PetscFree(mycount);

    2467:   /* Information unrelated to this particular run */
    2468:   PetscFPrintf(comm, fd, "# ========================================================================================================================\n");
    2469:   PetscTime(&y);
    2470:   PetscTime(&x);
    2471:   PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y);
    2472:   PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y); PetscTime(&y);
    2473:   PetscFPrintf(comm,fd,"AveragetimetogetPetscTime = %g\n", (y-x)/10.0);
    2474:   /* MPI information */
    2475:   if (size > 1) {
    2476:     MPI_Status  status;
    2477:     PetscMPIInt tag;
    2478:     MPI_Comm    newcomm;

    2480:     MPI_Barrier(comm);
    2481:     PetscTime(&x);
    2482:     MPI_Barrier(comm);
    2483:     MPI_Barrier(comm);
    2484:     MPI_Barrier(comm);
    2485:     MPI_Barrier(comm);
    2486:     MPI_Barrier(comm);
    2487:     PetscTime(&y);
    2488:     PetscFPrintf(comm, fd, "AveragetimeforMPI_Barrier = %g\n", (y-x)/5.0);
    2489:     PetscCommDuplicate(comm,&newcomm, &tag);
    2490:     MPI_Barrier(comm);
    2491:     if (rank) {
    2492:       MPI_Recv(0, 0, MPI_INT, rank-1,            tag, newcomm, &status);
    2493:       MPI_Send(0, 0, MPI_INT, (rank+1)%size, tag, newcomm);
    2494:     } else {
    2495:       PetscTime(&x);
    2496:       MPI_Send(0, 0, MPI_INT, 1,          tag, newcomm);
    2497:       MPI_Recv(0, 0, MPI_INT, size-1, tag, newcomm, &status);
    2498:       PetscTime(&y);
    2499:       PetscFPrintf(comm,fd,"AveragetimforzerosizeMPI_Send = %g\n", (y-x)/size);
    2500:     }
    2501:     PetscCommDestroy(&newcomm);
    2502:   }

    2504:   /* Cleanup */
    2505:   PetscFPrintf(comm, fd, "\n");
    2506:   PetscStageLogPush(stageLog, lastStage);
    2507:   return(0);
    2508: }

    2510: #else /* end of -DPETSC_USE_LOG section */

    2514: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
    2515: {
    2517:   return(0);
    2518: }

    2520: #endif /* PETSC_USE_LOG*/

    2523: PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
    2524: PetscClassId PETSC_OBJECT_CLASSID  = 0;

    2528: /*@C
    2529:   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.

    2531:   Not Collective

    2533:   Input Parameter:
    2534: . name   - The class name

    2536:   Output Parameter:
    2537: . oclass - The class id or classid

    2539:   Level: developer

    2541: .keywords: log, class, register

    2543: @*/
    2544: PetscErrorCode  PetscClassIdRegister(const char name[],PetscClassId *oclass)
    2545: {
    2546: #if defined(PETSC_USE_LOG)
    2547:   PetscStageLog  stageLog;
    2548:   PetscInt       stage;
    2550: #endif

    2553:   *oclass = ++PETSC_LARGEST_CLASSID;
    2554: #if defined(PETSC_USE_LOG)
    2555:   PetscLogGetStageLog(&stageLog);
    2556:   PetscClassRegLogRegister(stageLog->classLog, name, *oclass);
    2557:   for (stage = 0; stage < stageLog->numStages; stage++) {
    2558:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
    2559:   }
    2560: #endif
    2561:   return(0);
    2562: }

    2564: #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_MPE)
    2565: #include <mpe.h>

    2567: PetscBool PetscBeganMPE = PETSC_FALSE;

    2569: PETSC_INTERN PetscErrorCode PetscLogEventBeginMPE(PetscLogEvent,int,PetscObject,PetscObject,PetscObject,PetscObject);
    2570: PETSC_INTERN PetscErrorCode PetscLogEventEndMPE(PetscLogEvent,int,PetscObject,PetscObject,PetscObject,PetscObject);

    2574: /*@C
    2575:    PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files
    2576:    and slows the program down.

    2578:    Collective over PETSC_COMM_WORLD

    2580:    Options Database Keys:
    2581: . -log_mpe - Prints extensive log information (for code compiled with PETSC_USE_LOG)

    2583:    Notes:
    2584:    A related routine is PetscLogBegin() (with the options key -log_summary), which is
    2585:    intended for production runs since it logs only flop rates and object
    2586:    creation (and should not significantly slow the programs).

    2588:    Level: advanced

    2590:    Concepts: logging^MPE
    2591:    Concepts: logging^message passing

    2593: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogAllBegin(), PetscLogEventActivate(),
    2594:           PetscLogEventDeactivate()
    2595: @*/
    2596: PetscErrorCode  PetscLogMPEBegin(void)
    2597: {

    2601:   /* Do MPE initialization */
    2602:   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
    2603:     PetscInfo(0,"Initializing MPE.\n");
    2604:     MPE_Init_log();

    2606:     PetscBeganMPE = PETSC_TRUE;
    2607:   } else {
    2608:     PetscInfo(0,"MPE already initialized. Not attempting to reinitialize.\n");
    2609:   }
    2610:   PetscLogSet(PetscLogEventBeginMPE, PetscLogEventEndMPE);
    2611:   return(0);
    2612: }

    2616: /*@C
    2617:    PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.

    2619:    Collective over PETSC_COMM_WORLD

    2621:    Level: advanced

    2623: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogMPEBegin()
    2624: @*/
    2625: PetscErrorCode  PetscLogMPEDump(const char sname[])
    2626: {
    2627:   char           name[PETSC_MAX_PATH_LEN];

    2631:   if (PetscBeganMPE) {
    2632:     PetscInfo(0,"Finalizing MPE.\n");
    2633:     if (sname) {
    2634:       PetscStrcpy(name,sname);
    2635:     } else {
    2636:       PetscGetProgramName(name,PETSC_MAX_PATH_LEN);
    2637:     }
    2638:     MPE_Finish_log(name);
    2639:   } else {
    2640:     PetscInfo(0,"Not finalizing MPE (not started by PETSc).\n");
    2641:   }
    2642:   return(0);
    2643: }

    2645: #define PETSC_RGB_COLORS_MAX 39
    2646: static const char *PetscLogMPERGBColors[PETSC_RGB_COLORS_MAX] = {
    2647:   "OliveDrab:      ",
    2648:   "BlueViolet:     ",
    2649:   "CadetBlue:      ",
    2650:   "CornflowerBlue: ",
    2651:   "DarkGoldenrod:  ",
    2652:   "DarkGreen:      ",
    2653:   "DarkKhaki:      ",
    2654:   "DarkOliveGreen: ",
    2655:   "DarkOrange:     ",
    2656:   "DarkOrchid:     ",
    2657:   "DarkSeaGreen:   ",
    2658:   "DarkSlateGray:  ",
    2659:   "DarkTurquoise:  ",
    2660:   "DeepPink:       ",
    2661:   "DarkKhaki:      ",
    2662:   "DimGray:        ",
    2663:   "DodgerBlue:     ",
    2664:   "GreenYellow:    ",
    2665:   "HotPink:        ",
    2666:   "IndianRed:      ",
    2667:   "LavenderBlush:  ",
    2668:   "LawnGreen:      ",
    2669:   "LemonChiffon:   ",
    2670:   "LightCoral:     ",
    2671:   "LightCyan:      ",
    2672:   "LightPink:      ",
    2673:   "LightSalmon:    ",
    2674:   "LightSlateGray: ",
    2675:   "LightYellow:    ",
    2676:   "LimeGreen:      ",
    2677:   "MediumPurple:   ",
    2678:   "MediumSeaGreen: ",
    2679:   "MediumSlateBlue:",
    2680:   "MidnightBlue:   ",
    2681:   "MintCream:      ",
    2682:   "MistyRose:      ",
    2683:   "NavajoWhite:    ",
    2684:   "NavyBlue:       ",
    2685:   "OliveDrab:      "
    2686: };

    2690: /*@C
    2691:   PetscLogMPEGetRGBColor - This routine returns a rgb color useable with PetscLogEventRegister()

    2693:   Not collective. Maybe it should be?

    2695:   Output Parameter
    2696: . str - character string representing the color

    2698:   Level: developer

    2700: .keywords: log, mpe , color
    2701: .seealso: PetscLogEventRegister
    2702: @*/
    2703: PetscErrorCode  PetscLogMPEGetRGBColor(const char *str[])
    2704: {
    2705:   static int idx = 0;

    2708:   *str = PetscLogMPERGBColors[idx];
    2709:   idx  = (idx + 1)% PETSC_RGB_COLORS_MAX;
    2710:   return(0);
    2711: }

    2713: #endif /* PETSC_USE_LOG && PETSC_HAVE_MPE */