Actual source code: plog.c

  1: #define PETSC_DLL
  2: /*
  3:       PETSc code to log object creation and destruction and PETSc events.
  4: */
 5:  #include petsc.h
 6:  #include petsctime.h
  7: #if defined(PETSC_HAVE_MPE)
  8: #include "mpe.h"
  9: #endif
 10: #include <stdarg.h>
 11: #include <sys/types.h>
 12:  #include petscsys.h
 13: #if defined(PETSC_HAVE_STDLIB_H)
 14: #include <stdlib.h>
 15: #endif
 16: #if defined(PETSC_HAVE_MALLOC_H)
 17: #include <malloc.h>
 18: #endif
 19: #include "petscfix.h"
 20:  #include plog.h

 22: PetscEvent  PETSC_LARGEST_EVENT  = PETSC_EVENT;

 24: #if defined(PETSC_USE_LOG)
 25: #include "petscmachineinfo.h"
 26: #include "petscconfiginfo.h"

 28: /* used in the MPI_XXX() count macros in petsclog.h */
 29: int  PETSC_DUMMY_SIZE = 0;
 30: int  PETSC_DUMMY_COUNT = 0;

 32: /* Action and object logging variables */
 33: Action    *actions    = PETSC_NULL;
 34: Object    *objects    = PETSC_NULL;
 35: PetscTruth logActions = PETSC_FALSE;
 36: PetscTruth logObjects = PETSC_FALSE;
 37: int        numActions = 0, maxActions = 100;
 38: int        numObjects = 0, maxObjects = 100;
 39: int        numObjectsDestroyed = 0;

 41: /* Global counters */
 42: PetscLogDouble  BaseTime        = 0.0;
 43: PetscLogDouble  _TotalFlops     = 0.0; /* The number of flops */
 44: PetscLogDouble  send_ct         = 0.0; /* The number of sends */
 45: PetscLogDouble  recv_ct         = 0.0; /* The number of receives */
 46: PetscLogDouble  send_len        = 0.0; /* The total length of all sent messages */
 47: PetscLogDouble  recv_len        = 0.0; /* The total length of all received messages */
 48: PetscLogDouble  isend_ct        = 0.0; /* The number of immediate sends */
 49: PetscLogDouble  irecv_ct        = 0.0; /* The number of immediate receives */
 50: PetscLogDouble  isend_len       = 0.0; /* The total length of all immediate send messages */
 51: PetscLogDouble  irecv_len       = 0.0; /* The total length of all immediate receive messages */
 52: PetscLogDouble  wait_ct         = 0.0; /* The number of waits */
 53: PetscLogDouble  wait_any_ct     = 0.0; /* The number of anywaits */
 54: PetscLogDouble  wait_all_ct     = 0.0; /* The number of waitalls */
 55: PetscLogDouble  sum_of_waits_ct = 0.0; /* The total number of waits */
 56: PetscLogDouble  allreduce_ct    = 0.0; /* The number of reductions */

 58: /* Logging functions */
 59: PetscErrorCode  (*_PetscLogPHC)(PetscObject) = PETSC_NULL;
 60: PetscErrorCode  (*_PetscLogPHD)(PetscObject) = PETSC_NULL;
 61: PetscErrorCode  (*_PetscLogPLB)(PetscEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = PETSC_NULL;
 62: PetscErrorCode  (*_PetscLogPLE)(PetscEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = PETSC_NULL;

 64: /* Tracing event logging variables */
 65: FILE          *tracefile       = PETSC_NULL;
 66: int            tracelevel      = 0;
 67: const char    *traceblanks     = "                                                                                                    ";
 68: char           tracespace[128] = " ";
 69: PetscLogDouble tracetime       = 0.0;

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

 77:   Not Collective

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

 83:   Level: developer

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

 94:   PetscFree(actions);
 95:   actions = PETSC_NULL;
 96:   PetscFree(objects);
 97:   objects =  PETSC_NULL;
 98:   PetscLogSet(PETSC_NULL, PETSC_NULL);

100:   /* Resetting phase */
101:   PetscLogGetStageLog(&stageLog);
102:   StageLogDestroy(stageLog);
103:   _TotalFlops         = 0.0;
104:   numActions          = 0;
105:   numObjects          = 0;
106:   numObjectsDestroyed = 0;
107:   return(0);
108: }

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

115:   Not Collective

117:   Input Parameters:
118: + b - The function called at beginning of event
119: - e - The function called at end of event

121:   Level: developer

123: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogAllBegin(), PetscLogTraceBegin()
124: @*/
125: PetscErrorCode  PetscLogSet(PetscErrorCode (*b)(PetscEvent, int, PetscObject, PetscObject, PetscObject, PetscObject),
126:             PetscErrorCode (*e)(PetscEvent, int, PetscObject, PetscObject, PetscObject, PetscObject))
127: {
129:   _PetscLogPLB = b;
130:   _PetscLogPLE = e;
131:   return(0);
132: }

134: /*------------------------------------------- Initialization Functions ----------------------------------------------*/
137: PetscErrorCode  PetscLogBegin_Private(void)
138: {
139:   static PetscTruth initialized = PETSC_FALSE;
140:   int               stage;
141:   PetscTruth        opt;
142:   PetscErrorCode    ierr;

145:   if (initialized) return(0);
146:   initialized = PETSC_TRUE;
147:   PetscOptionsHasName(PETSC_NULL, "-log_exclude_actions", &opt);
148:   if (opt) {
149:     logActions = PETSC_FALSE;
150:   }
151:   PetscOptionsHasName(PETSC_NULL, "-log_exclude_objects", &opt);
152:   if (opt) {
153:     logObjects = PETSC_FALSE;
154:   }
155:   if (logActions) {
156:     PetscMalloc(maxActions * sizeof(Action), &actions);
157:   }
158:   if (logObjects) {
159:     PetscMalloc(maxObjects * sizeof(Object), &objects);
160:   }
161:   _PetscLogPHC = PetscLogObjCreateDefault;
162:   _PetscLogPHD = PetscLogObjDestroyDefault;
163:   /* Setup default logging structures */
164:   StageLogCreate(&_stageLog);
165:   StageLogRegister(_stageLog, "Main Stage", &stage);
166:   /* All processors sync here for more consistent logging */
167:   MPI_Barrier(PETSC_COMM_WORLD);
168:   PetscTime(BaseTime);
169:   PetscLogStagePush(stage);
170:   return(0);
171: }

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

180:   Collective over PETSC_COMM_WORLD

182:   Options Database Keys:
183: + -log_summary - Prints summary of flop and timing information to the 
184:                   screen (for code compiled with PETSC_USE_LOG)
185: - -log - Prints detailed log information (for code compiled with PETSC_USE_LOG)

187:   Usage:
188: .vb
189:       PetscInitialize(...);
190:       PetscLogBegin();
191:        ... code ...
192:       PetscLogPrintSummary(MPI_Comm,filename); or PetscLogDump(); 
193:       PetscFinalize();
194: .ve

196:   Notes:
197:   PetscLogPrintSummary(MPI_Comm,filename) or PetscLogDump() actually cause the printing of 
198:   the logging information.

200:   Level: advanced

202: .keywords: log, begin
203: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogPrintSummary(), PetscLogTraceBegin()
204: @*/
205: PetscErrorCode  PetscLogBegin(void)
206: {

211:   PetscLogBegin_Private();
212:   return(0);
213: }

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

221:   Collective on PETSC_COMM_WORLD

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

226:   Usage:
227: .vb
228:      PetscInitialize(...);
229:      PetscLogAllBegin();
230:      ... code ...
231:      PetscLogDump(filename);
232:      PetscFinalize();
233: .ve

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

240:   Level: advanced

242: .keywords: log, all, begin
243: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogTraceBegin()
244: @*/
245: PetscErrorCode  PetscLogAllBegin(void)
246: {

251:   PetscLogBegin_Private();
252:   return(0);
253: }

257: /*@
258:   PetscLogTraceBegin - Activates trace logging.  Every time a PETSc event
259:   begins or ends, the event name is printed.

261:   Collective on PETSC_COMM_WORLD

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

266:   Options Database Key:
267: . -log_trace [filename] - Activates PetscLogTraceBegin()

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

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

277:   Level: intermediate

279: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogPrintSummary(), PetscLogBegin()
280: @*/
281: PetscErrorCode  PetscLogTraceBegin(FILE *file)
282: {

286:   tracefile = file;
288:   PetscLogBegin_Private();
289:   return(0);
290: }

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

297:   Not Collective

299:   Input Parameter:
300: . flag - PETSC_TRUE if actions are to be logged

302:   Level: intermediate

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

307:   Options Database Keys:
308: . -log_exclude_actions - Turns off actions logging

310: .keywords: log, stage, register
311: .seealso: PetscLogStagePush(), PetscLogStagePop()
312: @*/
313: PetscErrorCode  PetscLogActions(PetscTruth flag)
314: {
316:   logActions = flag;
317:   return(0);
318: }

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

325:   Not Collective

327:   Input Parameter:
328: . flag - PETSC_TRUE if objects are to be logged

330:   Level: intermediate

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

335:   Options Database Keys:
336: . -log_exclude_objects - Turns off objects logging

338: .keywords: log, stage, register
339: .seealso: PetscLogStagePush(), PetscLogStagePop()
340: @*/
341: PetscErrorCode  PetscLogObjects(PetscTruth flag)
342: {
344:   logObjects = flag;
345:   return(0);
346: }

348: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
351: /*@C
352:   PetscLogStageRegister - Attaches a charactor string name to a logging stage.

354:   Not Collective

356:   Input Parameter:
357: . sname - The name to associate with that stage

359:   Output Parameter:
360: . stage - The stage number

362:   Level: intermediate

364: .keywords: log, stage, register
365: .seealso: PetscLogStagePush(), PetscLogStagePop()
366: @*/
367: PetscErrorCode  PetscLogStageRegister(int *stage, const char sname[])
368: {
369:   StageLog       stageLog;
370:   PetscEvent     event;

374:   PetscLogGetStageLog(&stageLog);
375:   StageLogRegister(stageLog, sname, stage);
376:   /* Copy events already changed in the main stage, this sucks */
377:   EventPerfLogEnsureSize(stageLog->stageInfo[*stage].eventLog, stageLog->eventLog->numEvents);
378:   for(event = 0; event < stageLog->eventLog->numEvents; event++) {
379:     EventPerfInfoCopy(&stageLog->stageInfo[0].eventLog->eventInfo[event],
380:                              &stageLog->stageInfo[*stage].eventLog->eventInfo[event]);
381:   }
382:   ClassPerfLogEnsureSize(stageLog->stageInfo[*stage].classLog, stageLog->classLog->numClasses);
383:   return(0);
384: }

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

391:   Not Collective

393:   Input Parameter:
394: . stage - The stage on which to log

396:   Usage:
397:   If the option -log_sumary is used to run the program containing the 
398:   following code, then 2 sets of summary data will be printed during
399:   PetscFinalize().
400: .vb
401:       PetscInitialize(int *argc,char ***args,0,0);
402:       [stage 0 of code]   
403:       PetscLogStagePush(1);
404:       [stage 1 of code]
405:       PetscLogStagePop();
406:       PetscBarrier(...);
407:       [more stage 0 of code]   
408:       PetscFinalize();
409: .ve
410:  
411:   Notes:
412:   Use PetscLogStageRegister() to register a stage.

414:   Level: intermediate

416: .keywords: log, push, stage
417: .seealso: PetscLogStagePop(), PetscLogStageRegister(), PetscBarrier()
418: @*/
419: PetscErrorCode  PetscLogStagePush(int stage)
420: {
421:   StageLog       stageLog;

425:   PetscLogGetStageLog(&stageLog);
426:   StageLogPush(stageLog, stage);
427:   return(0);
428: }

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

435:   Not Collective

437:   Usage:
438:   If the option -log_sumary is used to run the program containing the 
439:   following code, then 2 sets of summary data will be printed during
440:   PetscFinalize().
441: .vb
442:       PetscInitialize(int *argc,char ***args,0,0);
443:       [stage 0 of code]   
444:       PetscLogStagePush(1);
445:       [stage 1 of code]
446:       PetscLogStagePop();
447:       PetscBarrier(...);
448:       [more stage 0 of code]   
449:       PetscFinalize();
450: .ve

452:   Notes:  
453:   Use PetscLogStageRegister() to register a stage.

455:   Level: intermediate

457: .keywords: log, pop, stage
458: .seealso: PetscLogStagePush(), PetscLogStageRegister(), PetscBarrier()
459: @*/
460: PetscErrorCode  PetscLogStagePop(void)
461: {
462:   StageLog       stageLog;

466:   PetscLogGetStageLog(&stageLog);
467:   StageLogPop(stageLog);
468:   return(0);
469: }

473: /*@

476:   Not Collective 

478:   Input Parameters:
479: + stage    - The stage
480: - isActive - The activity flag, PETSC_TRUE for logging, else PETSC_FALSE (defaults to PETSC_TRUE)

482:   Level: intermediate

485: @*/
486: PetscErrorCode  PetscLogStageSetActive(int stage, PetscTruth isActive)
487: {
488:   StageLog       stageLog;

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

499: /*@

502:   Not Collective 

504:   Input Parameter:
505: . stage    - The stage

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

510:   Level: intermediate

513: @*/
514: PetscErrorCode  PetscLogStageGetActive(int stage, PetscTruth *isActive)
515: {
516:   StageLog       stageLog;

520:   PetscLogGetStageLog(&stageLog);
521:   StageLogGetActive(stageLog, stage, isActive);
522:   return(0);
523: }

527: /*@
528:   PetscLogStageSetVisible - Determines stage visibility in PetscLogPrintSummary()

530:   Not Collective 

532:   Input Parameters:
533: + stage     - The stage
534: - isVisible - The visibility flag, PETSC_TRUE to print, else PETSC_FALSE (defaults to PETSC_TRUE)

536:   Level: intermediate

538: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogPrintSummary()
539: @*/
540: PetscErrorCode  PetscLogStageSetVisible(int stage, PetscTruth isVisible)
541: {
542:   StageLog       stageLog;

546:   PetscLogGetStageLog(&stageLog);
547:   StageLogSetVisible(stageLog, stage, isVisible);
548:   return(0);
549: }

553: /*@
554:   PetscLogStageGetVisible - Returns stage visibility in PetscLogPrintSummary()

556:   Not Collective 

558:   Input Parameter:
559: . stage     - The stage

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

564:   Level: intermediate

566: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogPrintSummary()
567: @*/
568: PetscErrorCode  PetscLogStageGetVisible(int stage, PetscTruth *isVisible)
569: {
570:   StageLog       stageLog;

574:   PetscLogGetStageLog(&stageLog);
575:   StageLogGetVisible(stageLog, stage, isVisible);
576:   return(0);
577: }

581: /*@
582:   PetscLogStageGetId - Returns the stage id when given the stage name.

584:   Not Collective 

586:   Input Parameter:
587: . name  - The stage name

589:   Output Parameter:
590: . stage - The stage

592:   Level: intermediate

594: .seealso: PetscLogStagePush(), PetscLogStagePop(), PreLoadBegin(), PreLoadEnd(), PreLoadStage()
595: @*/
596: PetscErrorCode  PetscLogStageGetId(const char name[], int *stage)
597: {
598:   StageLog       stageLog;

602:   PetscLogGetStageLog(&stageLog);
603:   StageLogGetStage(stageLog, name, stage);
604:   return(0);
605: }

607: /*------------------------------------------------ Event Functions --------------------------------------------------*/
610: /*@C

613:   Not Collective

615:   Input Parameter:
616: + name   - The name associated with the event
617: - cookie - The cookie associated to the class for this event, obtain either with
618:            PetscLogClassRegister() or use a predefined one such as KSP_COOKIE, SNES_COOKIE
619:             
620:   Output Parameter:

623:   Example of Usage:
624: .vb
625:       PetscEvent USER_EVENT;
626:       PetscCookie cookie;
627:       int user_event_flops;
628:       PetscLogClassRegister(&cookie,"class name");
631:          [code segment to monitor]
632:          PetscLogFlops(user_event_flops);
634: .ve

636:   Notes: 
637:   PETSc automatically logs library events if the code has been
638:   compiled with -DPETSC_USE_LOG (which is the default) and -log,
640:   intended for logging user events to supplement this PETSc
641:   information. 

643:   PETSc can gather data for use with the utilities Upshot/Nupshot
644:   (part of the MPICH distribution).  If PETSc has been compiled
645:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
646:   MPICH), the user can employ another command line option, -log_mpe,
647:   to create a logfile, "mpe.log", which can be visualized
648:   Upshot/Nupshot. 

650:   The cookie is associated with each event so that classes of events
651:   can be disabled simultaneously, such as all matrix events. The user
652:   can either use an existing cookie, such as MAT_COOKIE, or create
653:   their own as shown in the example.

655:   Level: intermediate

657: .keywords: log, event, register
661: @*/
663: {
664:   StageLog       stageLog;
665:   int            stage;

669:   *event = PETSC_DECIDE;
670:   PetscLogGetStageLog(&stageLog);
671:   EventRegLogRegister(stageLog->eventLog, name, cookie, event);
672:   for(stage = 0; stage < stageLog->numStages; stage++) {
673:     EventPerfLogEnsureSize(stageLog->stageInfo[stage].eventLog, stageLog->eventLog->numEvents);
674:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
675:   }
676:   return(0);
677: }

681: /*@

684:   Not Collective

686:   Input Parameter:
687: . event - The event id

689:   Usage:
690: .vb
692:         [code where you do not want to log VecSetValues()]
694:         [code where you do want to log VecSetValues()]
695: .ve 

697:   Note:
698:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)

701:   Level: advanced

703: .keywords: log, event, activate
705: @*/
707: {
708:   StageLog       stageLog;
709:   int            stage;

713:   PetscLogGetStageLog(&stageLog);
714:   StageLogGetCurrent(stageLog, &stage);
715:   EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
716:   return(0);
717: }

721: /*@

724:   Not Collective

726:   Input Parameter:
727: . event - The event id

729:   Usage:
730: .vb
732:         [code where you do not want to log VecSetValues()]
734:         [code where you do want to log VecSetValues()]
735: .ve 

737:   Note: 
738:   The event may be either a pre-defined PETSc event (found in

741:   Level: advanced

743: .keywords: log, event, deactivate
745: @*/
747: {
748:   StageLog       stageLog;
749:   int            stage;

753:   PetscLogGetStageLog(&stageLog);
754:   StageLogGetCurrent(stageLog, &stage);
755:   EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
756:   return(0);
757: }

761: /*@

764:   Not Collective

766:   Input Parameters:
767: + event    - The event id
768: - isActive - The activity flag determining whether the event is logged

770:   Level: advanced

772: .keywords: log, event, activate
774: @*/
776: {
777:   StageLog       stageLog;
778:   int            stage;

782:   PetscLogGetStageLog(&stageLog);
783:   for(stage = 0; stage < stageLog->numStages; stage++) {
784:     if (isActive) {
785:       EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
786:     } else {
787:       EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
788:     }
789:   }
790:   return(0);
791: }

795: /*@

798:   Not Collective

800:   Input Parameter:
801: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.

803:   Level: developer

805: .keywords: log, event, activate, class
807: @*/
809: {
810:   StageLog       stageLog;
811:   int            stage;

815:   PetscLogGetStageLog(&stageLog);
816:   StageLogGetCurrent(stageLog, &stage);
817:   EventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
818:   return(0);
819: }

823: /*@

826:   Not Collective

828:   Input Parameter:
829: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.

831:   Level: developer

833: .keywords: log, event, deactivate, class
835: @*/
837: {
838:   StageLog       stageLog;
839:   int            stage;

843:   PetscLogGetStageLog(&stageLog);
844:   StageLogGetCurrent(stageLog, &stage);
845:   EventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
846:   return(0);
847: }

849: /*MC

852:    Input Parameters:
854: -  o1,o2,o3,o4 - objects associated with the event, or 0

856:    Synopsis:
858:                        PetscObject o4)

860:    Fortran Synopsis:

863:    Usage:
864: .vb
865:      int USER_EVENT;
866:      int user_event_flops;
869:         [code segment to monitor]
870:         PetscLogFlops(user_event_flops);
872: .ve

874:    Notes:
875:    You need to register each integer event with the command 
877:    -DPETSC_USE_LOG, which is the default.

879:    PETSc automatically logs library events if the code has been
880:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
882:    to supplement this PETSc information.

884:    Level: intermediate


888: .keywords: log, event, begin
889: M*/

891: /*MC

894:    Input Parameters:
896: -  o1,o2,o3,o4 - objects associated with the event, or 0

898:    Synopsis:
900:                      PetscObject o4)

902:    Fortran Synopsis:

905:    Usage:
906: .vb
907:      int USER_EVENT;
908:      int user_event_flops;
911:         [code segment to monitor]
912:         PetscLogFlops(user_event_flops);
914: .ve

916:    Notes:
917:    You should also register each additional integer event with the command 
919:    -DPETSC_USE_LOG, which is the default.

921:    PETSc automatically logs library events if the code has been
922:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
924:    to supplement this PETSc information.

926:    Level: intermediate


930: .keywords: log, event, end
931: M*/

933: /*MC

936:    Input Parameters:
938: .  o1,o2,o3,o4 - objects associated with the event, or 0
939: .  comm - communicator the barrier takes place over

941:    Synopsis:
943:                   PetscObject o4,MPI_Comm comm)

945:    Usage:
946: .vb
948:        MPI_Allreduce()
950: .ve

952:    Notes:
953:    This is for logging the amount of time spent in a barrier for an event
954:    that requires synchronization. 

956:    Additional Notes:
957:    Synchronization events always come in pairs; for example, VEC_NormBarrier and 
958:    VEC_NormComm = VEC_NormBarrier + 1

960:    Level: advanced


965: .keywords: log, event, begin, barrier
966: M*/

968: /*MC

971:    Input Parameters:
973: .  o1,o2,o3,o4 - objects associated with the event, or 0
974: .  comm - communicator the barrier takes place over

976:    Synopsis:
978:                   PetscObject o4,MPI_Comm comm)

980:     Usage:
981: .vb
983:        MPI_Allreduce()
985: .ve

987:    Notes:
988:    This is for logging the amount of time spent in a barrier for an event
989:    that requires synchronization. 

991:    Additional Notes:
992:    Synchronization events always come in pairs; for example, VEC_NormBarrier and 
993:    VEC_NormComm = VEC_NormBarrier + 1

995:    Level: advanced


1000: .keywords: log, event, begin, barrier
1001: M*/

1003: /*------------------------------------------------ Class Functions --------------------------------------------------*/
1006: /*@C
1007:   PetscLogClassRegister - Registers a class name for logging operations in an application code. 

1009:   Not Collective

1011:   Input Parameter:
1012: . name   - The class name
1013:             
1014:   Output Parameter:
1015: . oclass - The class id or cookie

1017:   Level: developer

1019: .keywords: log, class, register

1021: @*/
1022: PetscErrorCode  PetscLogClassRegister(PetscCookie *oclass, const char name[])
1023: {
1024:   StageLog       stageLog;
1025:   int            stage;

1029:   PetscLogGetStageLog(&stageLog);
1030:   ClassRegLogRegister(stageLog->classLog, name, oclass);
1031:   for(stage = 0; stage < stageLog->numStages; stage++) {
1032:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
1033:   }
1034:   return(0);
1035: }

1037: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1040: /*@C
1041:   PetscLogDump - Dumps logs of objects to a file. This file is intended to 
1042:   be read by petsc/bin/petscview.

1044:   Collective on PETSC_COMM_WORLD

1046:   Input Parameter:
1047: . name - an optional file name

1049:   Options Database Keys:
1050: + -log     - Prints basic log information (for code compiled with PETSC_USE_LOG)
1051: - -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)
1052:    
1053:   Usage:
1054: .vb
1055:      PetscInitialize(...);
1056:      PetscLogBegin(); or PetscLogAllBegin(); 
1057:      ... code ...
1058:      PetscLogDump(filename);
1059:      PetscFinalize();
1060: .ve

1062:   Notes:
1063:   The default file name is 
1064: $    Log.<rank>
1065:   where <rank> is the processor number. If no name is specified, 
1066:   this file will be used.

1068:   Level: advanced

1070: .keywords: log, dump
1071: .seealso: PetscLogBegin(), PetscLogAllBegin(), PetscLogPrintSummary()
1072: @*/
1073: PetscErrorCode  PetscLogDump(const char sname[])
1074: {
1075:   StageLog       stageLog;
1076:   EventPerfInfo *eventInfo;
1077:   FILE          *fd;
1078:   char           file[PETSC_MAX_PATH_LEN], fname[PETSC_MAX_PATH_LEN];
1079:   PetscLogDouble flops, _TotalTime;
1080:   PetscMPIInt    rank;
1081:   int            action, object, curStage;
1082:   PetscEvent     event;
1084: 
1086:   /* Calculate the total elapsed time */
1087:   PetscTime(_TotalTime);
1088:   _TotalTime -= BaseTime;
1089:   /* Open log file */
1090:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1091:   if (sname) {
1092:     sprintf(file, "%s.%d", sname, rank);
1093:   } else {
1094:     sprintf(file, "Log.%d", rank);
1095:   }
1096:   PetscFixFilename(file, fname);
1097:   PetscFOpen(PETSC_COMM_WORLD, fname, "w", &fd);
1098:   if ((!rank) && (!fd)) SETERRQ1(PETSC_ERR_FILE_OPEN, "Cannot open file: %s", fname);
1099:   /* Output totals */
1100:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Total Flops %14e %16.8e\n", _TotalFlops, _TotalTime);
1101:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Clock Resolution %g\n", 0.0);
1102:   /* Output actions */
1103:   if (logActions) {
1104:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Actions accomplished %d\n", numActions);
1105:     for(action = 0; action < numActions; action++) {
1106:       PetscFPrintf(PETSC_COMM_WORLD, fd, "%g %d %d %d %d %d %d %g %g %g\n",
1107:                           actions[action].time, actions[action].action, (int)actions[action].event, (int)actions[action].cookie, actions[action].id1,
1108:                           actions[action].id2, actions[action].id3, actions[action].flops, actions[action].mem, actions[action].maxmem);
1109:     }
1110:   }
1111:   /* Output objects */
1112:   if (logObjects) {
1113:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Objects created %d destroyed %d\n", numObjects, numObjectsDestroyed);
1114:     for(object = 0; object < numObjects; object++) {
1115:       PetscFPrintf(PETSC_COMM_WORLD, fd, "Parent ID: %d Memory: %d\n", objects[object].parent, (int) objects[object].mem);
1116:       if (!objects[object].name[0]) {
1117:         PetscFPrintf(PETSC_COMM_WORLD, fd,"No Name\n");
1118:       } else {
1119:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Name: %s\n", objects[object].name);
1120:       }
1121:       if (objects[object].info[0] != 0) {
1122:         PetscFPrintf(PETSC_COMM_WORLD, fd, "No Info\n");
1123:       } else {
1124:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Info: %s\n", objects[object].info);
1125:       }
1126:     }
1127:   }
1128:   /* Output events */
1129:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Event log:\n");
1130:   PetscLogGetStageLog(&stageLog);
1131:   StackTop(stageLog->stack, &curStage);
1132:   eventInfo = stageLog->stageInfo[curStage].eventLog->eventInfo;
1133:   for(event = 0; event < stageLog->stageInfo[curStage].eventLog->numEvents; event++) {
1134:     if (eventInfo[event].time != 0.0) {
1135:       flops = eventInfo[event].flops/eventInfo[event].time;
1136:     } else {
1137:       flops = 0.0;
1138:     }
1139:     PetscFPrintf(PETSC_COMM_WORLD, fd, "%d %16d %16g %16g %16g\n", event, eventInfo[event].count,
1140:                         eventInfo[event].flops, eventInfo[event].time, flops);
1141:   }
1142:   PetscFClose(PETSC_COMM_WORLD, fd);
1143:   return(0);
1144: }

1148: /*@C
1149:   PetscLogPrintSummary - Prints a summary of the logging.

1151:   Collective over MPI_Comm

1153:   Input Parameter:
1154: + comm - The MPI communicator (only one processor prints output)
1155: - file - [Optional] The output file name

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

1160:   Usage:
1161: .vb
1162:      PetscInitialize(...);
1163:      PetscLogBegin();
1164:      ... code ...
1165:      PetscLogPrintSummary(MPI_Comm,filename);
1166:      PetscFinalize(...);
1167: .ve

1169:   Notes:
1170:   By default the summary is printed to stdout.

1172:   Level: beginner
1173:    
1174: .keywords: log, dump, print
1175: .seealso: PetscLogBegin(), PetscLogDump()
1176: @*/
1177: PetscErrorCode  PetscLogPrintSummary(MPI_Comm comm, const char filename[])
1178: {
1179:   FILE          *fd   = stdout;
1180:   PetscScalar    zero = 0.0;
1181:   StageLog       stageLog;
1182:   StageInfo     *stageInfo = PETSC_NULL;
1183:   EventPerfInfo *eventInfo = PETSC_NULL;
1184:   ClassPerfInfo *classInfo;
1185:   char           arch[10], hostname[64], username[16], pname[PETSC_MAX_PATH_LEN], date[64];
1186:   const char    *name;
1187:   PetscLogDouble locTotalTime, TotalTime, TotalFlops;
1188:   PetscLogDouble numMessages, messageLength, avgMessLen, numReductions;
1189:   PetscLogDouble stageTime, flops, flopr, mem, mess, messLen, red;
1190:   PetscLogDouble fracTime, fracFlops, fracMessages, fracLength, fracReductions, fracMess, fracMessLen, fracRed;
1191:   PetscLogDouble fracStageTime, fracStageFlops, fracStageMess, fracStageMessLen, fracStageRed;
1192:   PetscLogDouble min, max, tot, ratio, avg, x, y;
1193:   PetscLogDouble minf, maxf, totf, ratf, mint, maxt, tott, ratt, ratCt, totm, totml, totr;
1194:   PetscMPIInt    minCt, maxCt;
1195:   PetscMPIInt    size, rank;
1196:   PetscTruth    *localStageUsed,    *stageUsed;
1197:   PetscTruth    *localStageVisible, *stageVisible;
1198:   int            numStages, localNumEvents, numEvents;
1199:   int            stage, lastStage, oclass;
1200:   PetscEvent     event;
1202:   char           version[256];

1205:   MPI_Comm_size(comm, &size);
1206:   MPI_Comm_rank(comm, &rank);
1207:   /* Pop off any stages the user forgot to remove */
1208:   lastStage = 0;
1209:   PetscLogGetStageLog(&stageLog);
1210:   StageLogGetCurrent(stageLog, &stage);
1211:   while (stage >= 0) {
1212:     lastStage = stage;
1213:     StageLogPop(stageLog);
1214:     StageLogGetCurrent(stageLog, &stage);
1215:   }
1216:   /* Get the total elapsed time */
1217:   PetscTime(locTotalTime);  locTotalTime -= BaseTime;
1218:   /* Open the summary file */
1219:   if (filename) {
1220:     PetscFOpen(comm, filename, "w", &fd);
1221:   }

1223:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1224:   PetscFPrintf(comm, fd, "***             WIDEN YOUR WINDOW TO 120 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document            ***\n");
1225:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1226:   PetscFPrintf(comm, fd, "\n---------------------------------------------- PETSc Performance Summary: ----------------------------------------------\n\n");
1227:   PetscGetArchType(arch, 10);
1228:   PetscGetHostName(hostname, 64);
1229:   PetscGetUserName(username, 16);
1230:   PetscGetProgramName(pname, PETSC_MAX_PATH_LEN);
1231:   PetscGetDate(date, 64);
1232:   PetscGetVersion(&version,256);
1233:   if (size == 1) {
1234:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processor, by %s %s\n", pname, arch, hostname, size, username, date);
1235:   } else {
1236:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processors, by %s %s\n", pname, arch, hostname, size, username, date);
1237:   }
1238:   PetscFPrintf(comm, fd, "Using %s\n", version);

1240:   /* Must preserve reduction count before we go on */
1241:   red  = allreduce_ct/((PetscLogDouble) size);

1243:   /* Calculate summary information */
1244:   PetscFPrintf(comm, fd, "\n                         Max       Max/Min        Avg      Total \n");
1245:   /*   Time */
1246:   MPI_Allreduce(&locTotalTime, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1247:   MPI_Allreduce(&locTotalTime, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1248:   MPI_Allreduce(&locTotalTime, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1249:   avg  = (tot)/((PetscLogDouble) size);
1250:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1251:   PetscFPrintf(comm, fd, "Time (sec):           %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
1252:   TotalTime = tot;
1253:   /*   Objects */
1254:   avg  = (PetscLogDouble) numObjects;
1255:   MPI_Allreduce(&avg,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1256:   MPI_Allreduce(&avg,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1257:   MPI_Allreduce(&avg,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1258:   avg  = (tot)/((PetscLogDouble) size);
1259:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1260:   PetscFPrintf(comm, fd, "Objects:              %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
1261:   /*   Flops */
1262:   MPI_Allreduce(&_TotalFlops,  &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1263:   MPI_Allreduce(&_TotalFlops,  &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1264:   MPI_Allreduce(&_TotalFlops,  &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1265:   avg  = (tot)/((PetscLogDouble) size);
1266:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1267:   PetscFPrintf(comm, fd, "Flops:                %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1268:   TotalFlops = tot;
1269:   /*   Flops/sec -- Must talk to Barry here */
1270:   if (locTotalTime != 0.0) flops = _TotalFlops/locTotalTime; else flops = 0.0;
1271:   MPI_Allreduce(&flops,        &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1272:   MPI_Allreduce(&flops,        &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1273:   MPI_Allreduce(&flops,        &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1274:   avg  = (tot)/((PetscLogDouble) size);
1275:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1276:   PetscFPrintf(comm, fd, "Flops/sec:            %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1277:   /*   Memory */
1278:   PetscMallocGetMaximumUsage(&mem);
1279:   if (mem > 0.0) {
1280:     MPI_Allreduce(&mem,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1281:     MPI_Allreduce(&mem,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1282:     MPI_Allreduce(&mem,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1283:     avg  = (tot)/((PetscLogDouble) size);
1284:     if (min != 0.0) ratio = max/min; else ratio = 0.0;
1285:     PetscFPrintf(comm, fd, "Memory:               %5.3e   %10.5f              %5.3e\n", max, ratio, tot);
1286:   }
1287:   /*   Messages */
1288:   mess = 0.5*(irecv_ct + isend_ct + recv_ct + send_ct);
1289:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1290:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1291:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1292:   avg  = (tot)/((PetscLogDouble) size);
1293:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1294:   PetscFPrintf(comm, fd, "MPI Messages:         %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1295:   numMessages = tot;
1296:   /*   Message Lengths */
1297:   mess = 0.5*(irecv_len + isend_len + recv_len + send_len);
1298:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1299:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1300:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1301:   if (numMessages != 0) avg = (tot)/(numMessages); else avg = 0.0;
1302:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1303:   PetscFPrintf(comm, fd, "MPI Message Lengths:  %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1304:   messageLength = tot;
1305:   /*   Reductions */
1306:   MPI_Allreduce(&red,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1307:   MPI_Allreduce(&red,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1308:   MPI_Allreduce(&red,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1309:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1310:   PetscFPrintf(comm, fd, "MPI Reductions:       %5.3e   %10.5f\n", max, ratio);
1311:   numReductions = tot;
1312:   PetscFPrintf(comm, fd, "\nFlop counting convention: 1 flop = 1 real number operation of type (multiply/divide/add/subtract)\n");
1313:   PetscFPrintf(comm, fd, "                            e.g., VecAXPY() for real vectors of length N --> 2N flops\n");
1314:   PetscFPrintf(comm, fd, "                            and VecAXPY() for complex vectors of length N --> 8N flops\n");

1316:   /* Get total number of stages --
1317:        Currently, a single processor can register more stages than another, but stages must all be registered in order.
1318:        We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
1319:        This seems best accomplished by assoicating a communicator with each stage.
1320:   */
1321:   MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm);
1322:   PetscMalloc(numStages * sizeof(PetscTruth), &localStageUsed);
1323:   PetscMalloc(numStages * sizeof(PetscTruth), &stageUsed);
1324:   PetscMalloc(numStages * sizeof(PetscTruth), &localStageVisible);
1325:   PetscMalloc(numStages * sizeof(PetscTruth), &stageVisible);
1326:   if (numStages > 0) {
1327:     stageInfo = stageLog->stageInfo;
1328:     for(stage = 0; stage < numStages; stage++) {
1329:       if (stage < stageLog->numStages) {
1330:         localStageUsed[stage]    = stageInfo[stage].used;
1331:         localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
1332:       } else {
1333:         localStageUsed[stage]    = PETSC_FALSE;
1334:         localStageVisible[stage] = PETSC_TRUE;
1335:       }
1336:     }
1337:     MPI_Allreduce(localStageUsed,    stageUsed,    numStages, MPI_INT, MPI_LOR,  comm);
1338:     MPI_Allreduce(localStageVisible, stageVisible, numStages, MPI_INT, MPI_LAND, comm);
1339:     for(stage = 0; stage < numStages; stage++) {
1340:       if (stageUsed[stage]) {
1341:         PetscFPrintf(comm, fd, "\nSummary of Stages:   ----- Time ------  ----- Flops -----  --- Messages ---  -- Message Lengths --  -- Reductions --\n");
1342:         PetscFPrintf(comm, fd, "                        Avg     %%Total     Avg     %%Total   counts   %%Total     Avg         %%Total   counts   %%Total \n");
1343:         break;
1344:       }
1345:     }
1346:     for(stage = 0; stage < numStages; stage++) {
1347:       if (!stageUsed[stage]) continue;
1348:       if (localStageUsed[stage]) {
1349:         MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1350:         MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1351:         MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1352:         MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1353:         MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1354:         name = stageInfo[stage].name;
1355:       } else {
1356:         MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1357:         MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1358:         MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1359:         MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1360:         MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1361:         name = "";
1362:       }
1363:       mess *= 0.5; messLen *= 0.5; red /= size;
1364:       if (TotalTime     != 0.0) fracTime       = stageTime/TotalTime;    else fracTime       = 0.0;
1365:       if (TotalFlops    != 0.0) fracFlops      = flops/TotalFlops;       else fracFlops      = 0.0;
1366:       /* Talk to Barry if (stageTime     != 0.0) flops          = (size*flops)/stageTime; else flops          = 0.0; */
1367:       if (numMessages   != 0.0) fracMessages   = mess/numMessages;       else fracMessages   = 0.0;
1368:       if (numMessages   != 0.0) avgMessLen     = messLen/numMessages;    else avgMessLen     = 0.0;
1369:       if (messageLength != 0.0) fracLength     = messLen/messageLength;  else fracLength     = 0.0;
1370:       if (numReductions != 0.0) fracReductions = red/numReductions;      else fracReductions = 0.0;
1371:       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",
1372:                           stage, name, stageTime/size, 100.0*fracTime, flops, 100.0*fracFlops,
1373:                           mess, 100.0*fracMessages, avgMessLen, 100.0*fracLength, red, 100.0*fracReductions);
1374:     }
1375:   }

1377:   PetscFPrintf(comm, fd,
1378:     "\n------------------------------------------------------------------------------------------------------------------------\n");
1379: 
1380:   PetscFPrintf(comm, fd, "See the 'Profiling' chapter of the users' manual for details on interpreting output.\n");
1381:   PetscFPrintf(comm, fd, "Phase summary info:\n");
1382:   PetscFPrintf(comm, fd, "   Count: number of times phase was executed\n");
1383:   PetscFPrintf(comm, fd, "   Time and Flops/sec: Max - maximum over all processors\n");
1384:   PetscFPrintf(comm, fd, "                       Ratio - ratio of maximum to minimum over all processors\n");
1385:   PetscFPrintf(comm, fd, "   Mess: number of messages sent\n");
1386:   PetscFPrintf(comm, fd, "   Avg. len: average message length\n");
1387:   PetscFPrintf(comm, fd, "   Reduct: number of global reductions\n");
1388:   PetscFPrintf(comm, fd, "   Global: entire computation\n");
1389:   PetscFPrintf(comm, fd, "   Stage: stages of a computation. Set stages with PetscLogStagePush() and PetscLogStagePop().\n");
1390:   PetscFPrintf(comm, fd, "      %%T - percent time in this phase         %%F - percent flops in this phase\n");
1391:   PetscFPrintf(comm, fd, "      %%M - percent messages in this phase     %%L - percent message lengths in this phase\n");
1392:   PetscFPrintf(comm, fd, "      %%R - percent reductions in this phase\n");
1393:   PetscFPrintf(comm, fd, "   Total Mflop/s: 10e-6 * (sum of flops over all processors)/(max time over all processors)\n");
1394:   PetscFPrintf(comm, fd,
1395:     "------------------------------------------------------------------------------------------------------------------------\n");
1396: 

1398: #if defined(PETSC_USE_DEBUG)
1399:   PetscFPrintf(comm, fd, "\n\n");
1400:   PetscFPrintf(comm, fd, "      ##########################################################\n");
1401:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1402:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
1403:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1404:   PetscFPrintf(comm, fd, "      #   This code was compiled with a debugging option,      #\n");
1405:   PetscFPrintf(comm, fd, "      #   To get timing results run config/configure.py        #\n");
1406:   PetscFPrintf(comm, fd, "      #   using --with-debugging=no, the performance will      #\n");
1407:   PetscFPrintf(comm, fd, "      #   be generally two or three times faster.              #\n");
1408:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1409:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
1410: #endif
1411: #if defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_FORTRAN_KERNELS)
1412:   PetscFPrintf(comm, fd, "\n\n");
1413:   PetscFPrintf(comm, fd, "      ##########################################################\n");
1414:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1415:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
1416:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1417:   PetscFPrintf(comm, fd, "      #   The code for various complex numbers numerical       #\n");
1418:   PetscFPrintf(comm, fd, "      #   kernels uses C++, which generally is not well        #\n");
1419:   PetscFPrintf(comm, fd, "      #   optimized.  For performance that is about 4-5 times  #\n");
1420:   PetscFPrintf(comm, fd, "      #   faster, specify --with-fortran-kernels=generic       #\n");
1421:   PetscFPrintf(comm, fd, "      #   when running config/configure.py.                    #\n");
1422:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1423:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
1424: #endif

1426:   if (!PetscPreLoadingUsed) {
1427:     PetscFPrintf(comm,fd,"\n\n");
1428:     PetscFPrintf(comm,fd,"      ##########################################################\n");
1429:     PetscFPrintf(comm,fd,"      #                                                        #\n");
1430:     PetscFPrintf(comm,fd,"      #                          WARNING!!!                    #\n");
1431:     PetscFPrintf(comm,fd,"      #                                                        #\n");
1432:     PetscFPrintf(comm,fd,"      #   This code was run without the PreLoadBegin()         #\n");
1433:     PetscFPrintf(comm,fd,"      #   macros. To get timing results we always recommend    #\n");
1434:     PetscFPrintf(comm,fd,"      #   preloading. otherwise timing numbers may be          #\n");
1435:     PetscFPrintf(comm,fd,"      #   meaningless.                                         #\n");
1436:     PetscFPrintf(comm,fd,"      ##########################################################\n\n\n");
1437:   }

1439:   /* Report events */
1440:   PetscFPrintf(comm, fd,
1441:     "Event                Count      Time (sec)     Flops/sec                         --- Global ---  --- Stage ---   Total\n");
1442: 
1443:   PetscFPrintf(comm, fd,
1444:     "                   Max Ratio  Max     Ratio   Max  Ratio  Mess   Avg len Reduct  %%T %%F %%M %%L %%R  %%T %%F %%M %%L %%R Mflop/s\n");
1445: 
1446:   PetscFPrintf(comm,fd,
1447:     "------------------------------------------------------------------------------------------------------------------------\n");

1449: 
1450:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
1451:   for(stage = 0; stage < numStages; stage++) {
1452:     if (!stageVisible[stage]) continue;
1453:     if (localStageUsed[stage]) {
1454:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1455:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1456:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1457:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1458:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1459:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1460:     } else {
1461:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1462:       MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1463:       MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1464:       MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1465:       MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1466:       MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1467:     }
1468:     mess *= 0.5; messLen *= 0.5; red /= size;

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

1475:        Problem: If the event did not happen on proc 1, its name will not be available.
1476:        Problem: Event visibility is not implemented
1477:     */
1478:     if (localStageUsed[stage]) {
1479:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
1480:       localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
1481:     } else {
1482:       localNumEvents = 0;
1483:     }
1484:     MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm);
1485:     for(event = 0; event < numEvents; event++) {
1486:       if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents)) {
1487:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) {
1488:           flopr = eventInfo[event].flops/eventInfo[event].time;
1489:         } else {
1490:           flopr = 0.0;
1491:         }
1492:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1493:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1494:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1495:         MPI_Allreduce(&eventInfo[event].time,          &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1496:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1497:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1498:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1499:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1500:         MPI_Allreduce(&eventInfo[event].numReductions, &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1501:         MPI_Allreduce(&eventInfo[event].count,         &minCt, 1, MPI_INT,             MPI_MIN, comm);
1502:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, comm);
1503:         name = stageLog->eventLog->eventInfo[event].name;
1504:       } else {
1505:         flopr = 0.0;
1506:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1507:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1508:         MPI_Allreduce(&zero,                           &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1509:         MPI_Allreduce(&zero,                           &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1510:         MPI_Allreduce(&zero,                           &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1511:         MPI_Allreduce(&zero,                           &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1512:         MPI_Allreduce(&zero,                           &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1513:         MPI_Allreduce(&zero,                           &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1514:         MPI_Allreduce(&zero,                           &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1515:         MPI_Allreduce(&ierr,                           &minCt, 1, MPI_INT,             MPI_MIN, comm);
1516:         MPI_Allreduce(&ierr,                           &maxCt, 1, MPI_INT,             MPI_MAX, comm);
1517:         name = "";
1518:       }
1519:       if (mint < 0.0) SETERRQ2(PETSC_ERR_PLIB,"Minimum time %g over all processors for %s is negative! Not possible!",mint,name);
1520:       if (minf < 0.0) SETERRQ2(PETSC_ERR_PLIB,"Minimum flops %g over all processors for %s is negative! Not possible!",minf,name);
1521:       totm *= 0.5; totml *= 0.5; totr /= size;
1522: 
1523:       if (maxCt != 0) {
1524:         if (minCt         != 0)   ratCt            = ((PetscLogDouble) maxCt)/minCt; else ratCt            = 0.0;
1525:         if (mint          != 0.0) ratt             = maxt/mint;                  else ratt             = 0.0;
1526:         if (minf          != 0.0) ratf             = maxf/minf;                  else ratf             = 0.0;
1527:         if (TotalTime     != 0.0) fracTime         = tott/TotalTime;             else fracTime         = 0.0;
1528:         if (TotalFlops    != 0.0) fracFlops        = totf/TotalFlops;            else fracFlops        = 0.0;
1529:         if (stageTime     != 0.0) fracStageTime    = tott/stageTime;             else fracStageTime    = 0.0;
1530:         if (flops         != 0.0) fracStageFlops   = totf/flops;                 else fracStageFlops   = 0.0;
1531:         if (numMessages   != 0.0) fracMess         = totm/numMessages;           else fracMess         = 0.0;
1532:         if (messageLength != 0.0) fracMessLen      = totml/messageLength;        else fracMessLen      = 0.0;
1533:         if (numReductions != 0.0) fracRed          = totr/numReductions;         else fracRed          = 0.0;
1534:         if (mess          != 0.0) fracStageMess    = totm/mess;                  else fracStageMess    = 0.0;
1535:         if (messLen       != 0.0) fracStageMessLen = totml/messLen;              else fracStageMessLen = 0.0;
1536:         if (red           != 0.0) fracStageRed     = totr/red;                   else fracStageRed     = 0.0;
1537:         if (totm          != 0.0) totml           /= totm;                       else totml            = 0.0;
1538:         if (maxt          != 0.0) flopr            = totf/maxt;                  else flopr            = 0.0;
1539:         PetscFPrintf(comm, fd,
1540:           "%-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",
1541:                             name, maxCt, ratCt, maxt, ratt, maxf, ratf, totm, totml, totr,
1542:                             100.0*fracTime, 100.0*fracFlops, 100.0*fracMess, 100.0*fracMessLen, 100.0*fracRed,
1543:                             100.0*fracStageTime, 100.0*fracStageFlops, 100.0*fracStageMess, 100.0*fracStageMessLen, 100.0*fracStageRed,
1544:                             flopr/1.0e6);
1545:       }
1546:     }
1547:   }

1549:   /* Memory usage and object creation */
1550:   PetscFPrintf(comm, fd,
1551:     "------------------------------------------------------------------------------------------------------------------------\n");
1552:   PetscFPrintf(comm, fd, "\n");
1553:   PetscFPrintf(comm, fd, "Memory usage is given in bytes:\n\n");

1555:   /* Right now, only stages on the first processor are reported here, meaning only objects associated with
1556:      the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
1557:      stats for stages local to processor sets.
1558:   */
1559:   /* We should figure out the longest object name here (now 20 characters) */
1560:   PetscFPrintf(comm, fd, "Object Type          Creations   Destructions   Memory  Descendants' Mem.\n");
1561:   for(stage = 0; stage < numStages; stage++) {
1562:     if (localStageUsed[stage]) {
1563:       classInfo = stageLog->stageInfo[stage].classLog->classInfo;
1564:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1565:       for(oclass = 0; oclass < stageLog->stageInfo[stage].classLog->numClasses; oclass++) {
1566:         if ((classInfo[oclass].creations > 0) || (classInfo[oclass].destructions > 0)) {
1567:           PetscFPrintf(comm, fd, "%20s %5d          %5d  %9d     %g\n", stageLog->classLog->classInfo[oclass].name,
1568:                               classInfo[oclass].creations, classInfo[oclass].destructions, (int) classInfo[oclass].mem,
1569:                               classInfo[oclass].descMem);
1570:         }
1571:       }
1572:     } else {
1573:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1574:     }
1575:   }

1577:   PetscFree(localStageUsed);
1578:   PetscFree(stageUsed);
1579:   PetscFree(localStageVisible);
1580:   PetscFree(stageVisible);

1582:   /* Information unrelated to this particular run */
1583:   PetscFPrintf(comm, fd,
1584:     "========================================================================================================================\n");
1585:   PetscTime(y);
1586:   PetscTime(x);
1587:   PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1588:   PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1589:   PetscFPrintf(comm,fd,"Average time to get PetscTime(): %g\n", (y-x)/10.0);
1590:   /* MPI information */
1591:   if (size > 1) {
1592:     MPI_Status  status;
1593:     PetscMPIInt tag;
1594:     MPI_Comm    newcomm;

1596:     MPI_Barrier(comm);
1597:     PetscTime(x);
1598:     MPI_Barrier(comm);
1599:     MPI_Barrier(comm);
1600:     MPI_Barrier(comm);
1601:     MPI_Barrier(comm);
1602:     MPI_Barrier(comm);
1603:     PetscTime(y);
1604:     PetscFPrintf(comm, fd, "Average time for MPI_Barrier(): %g\n", (y-x)/5.0);
1605:     PetscCommDuplicate(comm,&newcomm, &tag);
1606:     MPI_Barrier(comm);
1607:     if (rank) {
1608:       MPI_Recv(0, 0, MPI_INT, rank-1,            tag, newcomm, &status);
1609:       MPI_Send(0, 0, MPI_INT, (rank+1)%size, tag, newcomm);
1610:     } else {
1611:       PetscTime(x);
1612:       MPI_Send(0, 0, MPI_INT, 1,          tag, newcomm);
1613:       MPI_Recv(0, 0, MPI_INT, size-1, tag, newcomm, &status);
1614:       PetscTime(y);
1615:       PetscFPrintf(comm,fd,"Average time for zero size MPI_Send(): %g\n", (y-x)/size);
1616:     }
1617:     PetscCommDestroy(&newcomm);
1618:   }
1619:   if (!rank) {
1620:     PetscOptionsPrint(fd);
1621:   }
1622:   /* Machine and compile information */
1623: #if defined(PETSC_USE_FORTRAN_KERNELS)
1624:   PetscFPrintf(comm, fd, "Compiled with FORTRAN kernels\n");
1625: #else
1626:   PetscFPrintf(comm, fd, "Compiled without FORTRAN kernels\n");
1627: #endif
1628: #if defined(PETSC_USE_SINGLE)
1629:   PetscFPrintf(comm, fd, "Compiled with single precision PetscScalar and PetscReal\n");
1630: #elif defined(PETSC_USE_LONGDOUBLE)
1631:   PetscFPrintf(comm, fd, "Compiled with long double precision PetscScalar and PetscReal\n");
1632: #elif defined(PETSC_USE_INT)
1633:   PetscFPrintf(comm, fd, "Compiled with int PetscScalar and PetscReal\n");
1634: #endif

1636: #if defined(PETSC_USE_MAT_SINGLE)
1637:   PetscFPrintf(comm, fd, "Compiled with single precision matrices\n");
1638: #else
1639:   PetscFPrintf(comm, fd, "Compiled with full precision matrices (default)\n");
1640: #endif
1641:   PetscFPrintf(comm, fd, "sizeof(short) %d sizeof(int) %d sizeof(long) %d sizeof(void*) %d sizeof(PetscScalar) %d\n",
1642:                       (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(void*),(int) sizeof(PetscScalar));

1644:   PetscFPrintf(comm, fd, "Configure run at: %s\n",petscconfigureruntime);
1645:   PetscFPrintf(comm, fd, "Configure options: %s",petscconfigureoptions);
1646:   PetscFPrintf(comm, fd, "%s", petscmachineinfo);
1647:   PetscFPrintf(comm, fd, "%s", petsccompilerinfo);
1648:   PetscFPrintf(comm, fd, "%s", petsccompilerflagsinfo);
1649:   PetscFPrintf(comm, fd, "%s", petsclinkerinfo);

1651:   /* Cleanup */
1652:   PetscFPrintf(comm, fd, "\n");
1653:   PetscFClose(comm, fd);
1654:   StageLogPush(stageLog, lastStage);
1655:   return(0);
1656: }

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

1663:   Collective over MPI_Comm

1665:   Input Parameter:
1666: + comm - The MPI communicator (only one processor prints output)
1667: - file - [Optional] The output file name

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

1672:   Usage:
1673: .vb
1674:      PetscInitialize(...);
1675:      PetscLogBegin();
1676:      ... code ...
1677:      PetscLogPrintDetailed(MPI_Comm,filename);
1678:      PetscFinalize(...);
1679: .ve

1681:   Notes:
1682:   By default the summary is printed to stdout.

1684:   Level: beginner
1685:    
1686: .keywords: log, dump, print
1687: .seealso: PetscLogBegin(), PetscLogDump(), PetscLogPrintSummary()
1688: @*/
1689: PetscErrorCode  PetscLogPrintDetailed(MPI_Comm comm, const char filename[])
1690: {
1691:   FILE          *fd   = stdout;
1692:   StageLog       stageLog;
1693:   StageInfo     *stageInfo = PETSC_NULL;
1694:   EventPerfInfo *eventInfo = PETSC_NULL;
1695:   const char    *name = PETSC_NULL;
1696:   PetscLogDouble TotalTime;
1697:   PetscLogDouble stageTime, flops, flopr, mess, messLen, red;
1698:   PetscLogDouble maxf, totf, maxt, tott, totm, totml, totr = 0.0;
1699:   PetscMPIInt    maxCt;
1700:   PetscMPIInt    size, rank;
1701:   PetscTruth     *stageUsed;
1702:   PetscTruth     *stageVisible;
1703:   int            numStages, numEvents;
1704:   int            stage;
1705:   PetscEvent     event;

1709:   MPI_Comm_size(comm, &size);
1710:   MPI_Comm_rank(comm, &rank);
1711:   /* Pop off any stages the user forgot to remove */
1712:   PetscLogGetStageLog(&stageLog);
1713:   StageLogGetCurrent(stageLog, &stage);
1714:   while (stage >= 0) {
1715:     StageLogPop(stageLog);
1716:     StageLogGetCurrent(stageLog, &stage);
1717:   }
1718:   /* Get the total elapsed time */
1719:   PetscTime(TotalTime);  TotalTime -= BaseTime;
1720:   /* Open the summary file */
1721:   if (filename) {
1722:     PetscFOpen(comm, filename, "w", &fd);
1723:   }

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


1730:   numStages = stageLog->numStages;
1731:   PetscMalloc(numStages * sizeof(PetscTruth), &stageUsed);
1732:   PetscMalloc(numStages * sizeof(PetscTruth), &stageVisible);
1733:   if (numStages > 0) {
1734:     stageInfo = stageLog->stageInfo;
1735:     for(stage = 0; stage < numStages; stage++) {
1736:       if (stage < stageLog->numStages) {
1737:         stageUsed[stage]    = stageInfo[stage].used;
1738:         stageVisible[stage] = stageInfo[stage].perfInfo.visible;
1739:       } else {
1740:         stageUsed[stage]    = PETSC_FALSE;
1741:         stageVisible[stage] = PETSC_TRUE;
1742:       }
1743:     }
1744:   }

1746:   /* Report events */
1747:   PetscFPrintf(comm, fd,"Event                Count      Time (sec)     Flops/sec                          \n");
1748:   PetscFPrintf(comm, fd,"                                                            Mess   Avg len Reduct \n");
1749:   PetscFPrintf(comm,fd,"-----------------------------------------------------------------------------------\n");
1750:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
1751:   for(stage = 0; stage < numStages; stage++) {
1752:     if (!stageVisible[stage]) continue;
1753:     if (stageUsed[stage]) {
1754:       PetscSynchronizedFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1755:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1756:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1757:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1758:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1759:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1760:     }
1761:     mess *= 0.5; messLen *= 0.5;

1763:     /* Get total number of events in this stage --
1764:     */
1765:     if (stageUsed[stage]) {
1766:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
1767:       numEvents = stageLog->stageInfo[stage].eventLog->numEvents;
1768:     } else {
1769:       numEvents = 0;
1770:     }
1771:     for(event = 0; event < numEvents; event++) {
1772:       if (stageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents)) {
1773:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) {
1774:           flopr = eventInfo[event].flops/eventInfo[event].time;
1775:         } else {
1776:           flopr = 0.0;
1777:         }
1778:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
1779:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1780:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
1781:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1782:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1783:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1784:         totr = eventInfo[event].numReductions;
1785:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, PETSC_COMM_SELF);
1786:         name = stageLog->eventLog->eventInfo[event].name;
1787:         totm *= 0.5; totml *= 0.5;
1788:       }
1789: 
1790:       if (maxCt != 0) {
1791:         if (totm          != 0.0) totml           /= totm;                       else totml            = 0.0;
1792:         PetscSynchronizedFPrintf(comm, fd,"%-16s %7d      %5.4e      %3.2e      %2.1e %2.1e %2.1e\n",name, maxCt,  maxt,  maxf, totm, totml, totr);
1793:       }
1794:     }
1795:   }
1796:   PetscSynchronizedFlush(comm);

1798:   PetscFree(stageUsed);
1799:   PetscFree(stageVisible);

1801:   PetscFClose(comm, fd);
1802:   return(0);
1803: }

1805: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
1808: /*@C
1809:    PetscGetFlops - Returns the number of flops used on this processor 
1810:    since the program began. 

1812:    Not Collective

1814:    Output Parameter:
1815:    flops - number of floating point operations 

1817:    Notes:
1818:    A global counter logs all PETSc flop counts.  The user can use
1819:    PetscLogFlops() to increment this counter to include flops for the 
1820:    application code.  

1822:    PETSc automatically logs library events if the code has been
1823:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
1824:    -log_summary, or -log_all are specified.  PetscLogFlops() is
1825:    intended for logging user flops to supplement this PETSc
1826:    information.

1828:    Level: intermediate

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

1832: .seealso: PetscGetTime(), PetscLogFlops()
1833: @*/
1834: PetscErrorCode  PetscGetFlops(PetscLogDouble *flops)
1835: {
1837:   *flops = _TotalFlops;
1838:   return(0);
1839: }

1843: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
1844: {
1846:   va_list        Argp;

1849:   if (!logObjects) return(0);
1850:   va_start(Argp, format);
1851:   PetscVSNPrintf(objects[obj->id].info, 64,format, Argp);
1852:   va_end(Argp);
1853:   return(0);
1854: }

1858: /*@
1859:   PetscLogGetStageLog - This function returns the default stage logging object.

1861:   Not collective

1863:   Output Parameter:
1864: . stageLog - The default StageLog

1866:   Level: beginner

1868: .keywords: log, stage
1869: .seealso: StageLogCreate()
1870: @*/
1871: PetscErrorCode  PetscLogGetStageLog(StageLog *stageLog)
1872: {
1875:   *stageLog = _stageLog;
1876:   return(0);
1877: }

1879: /*MC
1880:    PetscLogFlops - Adds floating point operations to the global counter.

1882:    Input Parameter:
1883: .  f - flop counter

1885:    Synopsis:
1886:    void PetscLogFlops(int f)

1888:    Usage:
1889: .vb
1890:      int USER_EVENT;
1893:         [code segment to monitor]
1894:         PetscLogFlops(user_flops)
1896: .ve

1898:    Notes:
1899:    A global counter logs all PETSc flop counts.  The user can use
1900:    PetscLogFlops() to increment this counter to include flops for the 
1901:    application code.  

1903:    PETSc automatically logs library events if the code has been
1904:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
1905:    -log_summary, or -log_all are specified.  PetscLogFlops() is
1906:    intended for logging user flops to supplement this PETSc
1907:    information.

1909:    Level: intermediate


1913: .keywords: log, flops, floating point operations
1914: M*/

1916: /*MC
1917:    PreLoadBegin - Begin a segment of code that may be preloaded (run twice)
1918:     to get accurate timings

1920:    Input Parameter:
1921: +   flag - PETSC_TRUE to run twice, PETSC_FALSE to run once, may be overridden
1922:            with command line option -preload true or -preload false
1923: -   name - name of first stage (lines of code timed separately with -log_summary) to
1924:            be preloaded

1926:    Synopsis:
1927:    void PreLoadBegin(PetscTruth flag,char *name);

1929:    Usage:
1930: .vb
1931:      PreLoadBegin(PETSC_TRUE,"first stage);
1932:        lines of code
1933:        PreLoadStage("second stage");
1934:        lines of code
1935:      PreLoadEnd();
1936: .ve

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

1940:      Flags available within the macro. 
1941: +    PetscPreLoadingUsed - true if we are or have done preloading 
1942: .    PetscPreLoadingOn - true if it is CURRENTLY doing preload
1943: .    PreLoadIt - 0 for the first computation (with preloading turned off it is only 0) 1 for the second
1944: -    PreLoadMax - number of times it will do the computation, only one when preloading is turned on
1945:      The first two variables are available throughout the program, the second two only between the PreLoadBegin()
1946:      and PreLoadEnd()

1948:    Level: intermediate


1952:    Concepts: preloading
1953:    Concepts: timing^accurate
1954:    Concepts: paging^eliminating effects of


1957: M*/

1959: /*MC
1960:    PreLoadEnd - End a segment of code that may be preloaded (run twice)
1961:     to get accurate timings

1963:    Synopsis:
1964:    void PreLoadEnd(void);

1966:    Usage:
1967: .vb
1968:      PreLoadBegin(PETSC_TRUE,"first stage);
1969:        lines of code
1970:        PreLoadStage("second stage");
1971:        lines of code
1972:      PreLoadEnd();
1973: .ve

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

1977:    Level: intermediate


1981: M*/

1983: /*MC
1984:    PreLoadStage - Start a new segment of code to be timed separately.
1985:     to get accurate timings

1987:    Synopsis:
1988:    void PreLoadStage(char *name);

1990:    Usage:
1991: .vb
1992:      PreLoadBegin(PETSC_TRUE,"first stage);
1993:        lines of code
1994:        PreLoadStage("second stage");
1995:        lines of code
1996:      PreLoadEnd();
1997: .ve

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

2001:    Level: intermediate


2005: M*/

2007: /*----------------------------------------------- Stack Functions ---------------------------------------------------*/
2010: /*@C
2011:   StackDestroy - This function destroys a stack.

2013:   Not Collective

2015:   Input Parameter:
2016: . stack - The stack

2018:   Level: beginner

2020: .keywords: log, stack, destroy
2021: .seealso: StackCreate(), StackEmpty(), StackPush(), StackPop(), StackTop()
2022: @*/
2023: PetscErrorCode StackDestroy(IntStack stack)
2024: {

2028:   PetscFree(stack->stack);
2029:   PetscFree(stack);
2030:   return(0);
2031: }

2035: /*@C
2036:   StackEmpty - This function determines whether any items have been pushed.

2038:   Not Collective

2040:   Input Parameter:
2041: . stack - The stack

2043:   Output Parameter:
2044: . empty - PETSC_TRUE if the stack is empty

2046:   Level: intermediate

2048: .keywords: log, stack, empty
2049: .seealso: StackCreate(), StackDestroy(), StackPush(), StackPop(), StackTop()
2050: @*/
2051: PetscErrorCode StackEmpty(IntStack stack, PetscTruth *empty)
2052: {
2055:   if (stack->top == -1) {
2056:     *empty = PETSC_TRUE;
2057:   } else {
2058:     *empty = PETSC_FALSE;
2059:   }
2060:   return(0);
2061: }

2065: /*@C
2066:   StackTop - This function returns the top of the stack.

2068:   Not Collective

2070:   Input Parameter:
2071: . stack - The stack

2073:   Output Parameter:
2074: . top - The integer on top of the stack

2076:   Level: intermediate

2078: .keywords: log, stack, top
2079: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackPop()
2080: @*/
2081: PetscErrorCode StackTop(IntStack stack, int *top)
2082: {
2085:   *top = stack->stack[stack->top];
2086:   return(0);
2087: }

2091: /*@C
2092:   StackPush - This function pushes an integer on the stack.

2094:   Not Collective

2096:   Input Parameters:
2097: + stack - The stack
2098: - item  - The integer to push

2100:   Level: intermediate

2102: .keywords: log, stack, push
2103: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPop(), StackTop()
2104: @*/
2105: PetscErrorCode StackPush(IntStack stack, int item)
2106: {
2107:   int            *array;

2111:   stack->top++;
2112:   if (stack->top >= stack->max) {
2113:     PetscMalloc(stack->max*2 * sizeof(int), &array);
2114:     PetscMemcpy(array, stack->stack, stack->max * sizeof(int));
2115:     PetscFree(stack->stack);
2116:     stack->stack = array;
2117:     stack->max  *= 2;
2118:   }
2119:   stack->stack[stack->top] = item;
2120:   return(0);
2121: }

2125: /*@C
2126:   StackPop - This function pops an integer from the stack.

2128:   Not Collective

2130:   Input Parameter:
2131: . stack - The stack

2133:   Output Parameter:
2134: . item  - The integer popped

2136:   Level: intermediate

2138: .keywords: log, stack, pop
2139: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackTop()
2140: @*/
2141: PetscErrorCode StackPop(IntStack stack, int *item)
2142: {
2145:   if (stack->top == -1) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Stack is empty");
2146:   *item = stack->stack[stack->top--];
2147:   return(0);
2148: }

2152: /*@C
2153:   StackCreate - This function creates a stack.

2155:   Not Collective

2157:   Output Parameter:
2158: . stack - The stack

2160:   Level: beginner

2162: .keywords: log, stack, pop
2163: .seealso: StackDestroy(), StackEmpty(), StackPush(), StackPop(), StackTop()
2164: @*/
2165: PetscErrorCode StackCreate(IntStack *stack)
2166: {
2167:   IntStack       s;

2172:   PetscNew(struct _n_IntStack, &s);
2173:   s->top = -1;
2174:   s->max = 128;
2175:   PetscMalloc(s->max * sizeof(int), &s->stack);
2176:   PetscMemzero(s->stack, s->max * sizeof(int));
2177:   *stack = s;
2178:   return(0);
2179: }

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

2185: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
2186: {
2188:   return(0);
2189: }

2191: #endif /* PETSC_USE_LOG*/