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: #include "petscmachineinfo.h"
8: #include "petscconfiginfo.h"
9: #if defined(PETSC_HAVE_MPE)
10: #include "mpe.h"
11: #endif
12: #include <stdarg.h>
13: #include <sys/types.h>
14: #include petscsys.h
15: #if defined(PETSC_HAVE_STDLIB_H)
16: #include <stdlib.h>
17: #endif
18: #if defined(PETSC_HAVE_MALLOC_H)
19: #include <malloc.h>
20: #endif
21: #include "petscfix.h"
22: #include plog.h
24: PetscEvent PETSC_LARGEST_EVENT = PETSC_EVENT;
26: #if defined(PETSC_USE_LOG)
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
618:
619: Output Parameter:
622: Example of Usage:
623: .vb
624: int USER_EVENT;
625: int user_event_flops;
628: [code segment to monitor]
629: PetscLogFlops(user_event_flops);
631: .ve
633: Notes:
634: PETSc automatically logs library events if the code has been
635: compiled with -DPETSC_USE_LOG (which is the default) and -log,
637: intended for logging user events to supplement this PETSc
638: information.
640: PETSc can gather data for use with the utilities Upshot/Nupshot
641: (part of the MPICH distribution). If PETSc has been compiled
642: with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
643: MPICH), the user can employ another command line option, -log_mpe,
644: to create a logfile, "mpe.log", which can be visualized
645: Upshot/Nupshot.
647: Level: intermediate
649: .keywords: log, event, register
653: @*/
655: {
656: StageLog stageLog;
657: int stage;
661: *event = PETSC_DECIDE;
662: PetscLogGetStageLog(&stageLog);
663: EventRegLogRegister(stageLog->eventLog, name, cookie, event);
664: for(stage = 0; stage < stageLog->numStages; stage++) {
665: EventPerfLogEnsureSize(stageLog->stageInfo[stage].eventLog, stageLog->eventLog->numEvents);
666: ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
667: }
668: return(0);
669: }
673: /*@
676: Not Collective
678: Input Parameter:
679: . event - The event id
681: Usage:
682: .vb
684: [code where you do not want to log VecSetValues()]
686: [code where you do want to log VecSetValues()]
687: .ve
689: Note:
690: The event may be either a pre-defined PETSc event (found in include/petsclog.h)
693: Level: advanced
695: .keywords: log, event, activate
697: @*/
699: {
700: StageLog stageLog;
701: int stage;
705: PetscLogGetStageLog(&stageLog);
706: StageLogGetCurrent(stageLog, &stage);
707: EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
708: return(0);
709: }
713: /*@
716: Not Collective
718: Input Parameter:
719: . event - The event id
721: Usage:
722: .vb
724: [code where you do not want to log VecSetValues()]
726: [code where you do want to log VecSetValues()]
727: .ve
729: Note:
730: The event may be either a pre-defined PETSc event (found in
733: Level: advanced
735: .keywords: log, event, deactivate
737: @*/
739: {
740: StageLog stageLog;
741: int stage;
745: PetscLogGetStageLog(&stageLog);
746: StageLogGetCurrent(stageLog, &stage);
747: EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
748: return(0);
749: }
753: /*@
756: Not Collective
758: Input Parameters:
759: + event - The event id
760: - isActive - The activity flag determining whether the event is logged
762: Level: advanced
764: .keywords: log, event, activate
766: @*/
768: {
769: StageLog stageLog;
770: int stage;
774: PetscLogGetStageLog(&stageLog);
775: for(stage = 0; stage < stageLog->numStages; stage++) {
776: if (isActive) {
777: EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
778: } else {
779: EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
780: }
781: }
782: return(0);
783: }
787: /*@
790: Not Collective
792: Input Parameter:
793: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.
795: Level: developer
797: .keywords: log, event, activate, class
799: @*/
801: {
802: StageLog stageLog;
803: int stage;
807: PetscLogGetStageLog(&stageLog);
808: StageLogGetCurrent(stageLog, &stage);
809: EventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
810: return(0);
811: }
815: /*@
818: Not Collective
820: Input Parameter:
821: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.
823: Level: developer
825: .keywords: log, event, deactivate, class
827: @*/
829: {
830: StageLog stageLog;
831: int stage;
835: PetscLogGetStageLog(&stageLog);
836: StageLogGetCurrent(stageLog, &stage);
837: EventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
838: return(0);
839: }
841: /*MC
844: Input Parameters:
846: - o1,o2,o3,o4 - objects associated with the event, or 0
848: Synopsis:
850: PetscObject o4)
852: Fortran Synopsis:
855: Usage:
856: .vb
857: int USER_EVENT;
858: int user_event_flops;
861: [code segment to monitor]
862: PetscLogFlops(user_event_flops);
864: .ve
866: Notes:
867: You need to register each integer event with the command
869: -DPETSC_USE_LOG, which is the default.
871: PETSc automatically logs library events if the code has been
872: compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
874: to supplement this PETSc information.
876: Level: intermediate
880: .keywords: log, event, begin
881: M*/
883: /*MC
886: Input Parameters:
888: - o1,o2,o3,o4 - objects associated with the event, or 0
890: Synopsis:
892: PetscObject o4)
894: Fortran Synopsis:
897: Usage:
898: .vb
899: int USER_EVENT;
900: int user_event_flops;
903: [code segment to monitor]
904: PetscLogFlops(user_event_flops);
906: .ve
908: Notes:
909: You should also register each additional integer event with the command
911: -DPETSC_USE_LOG, which is the default.
913: PETSc automatically logs library events if the code has been
914: compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
916: to supplement this PETSc information.
918: Level: intermediate
922: .keywords: log, event, end
923: M*/
925: /*MC
928: Input Parameters:
930: . o1,o2,o3,o4 - objects associated with the event, or 0
931: . comm - communicator the barrier takes place over
933: Synopsis:
935: PetscObject o4,MPI_Comm comm)
937: Usage:
938: .vb
940: MPI_Allreduce()
942: .ve
944: Notes:
945: This is for logging the amount of time spent in a barrier for an event
946: that requires synchronization.
948: Additional Notes:
949: Synchronization events always come in pairs; for example, VEC_NormBarrier and
950: VEC_NormComm = VEC_NormBarrier + 1
952: Level: advanced
957: .keywords: log, event, begin, barrier
958: M*/
960: /*MC
963: Input Parameters:
965: . o1,o2,o3,o4 - objects associated with the event, or 0
966: . comm - communicator the barrier takes place over
968: Synopsis:
970: PetscObject o4,MPI_Comm comm)
972: Usage:
973: .vb
975: MPI_Allreduce()
977: .ve
979: Notes:
980: This is for logging the amount of time spent in a barrier for an event
981: that requires synchronization.
983: Additional Notes:
984: Synchronization events always come in pairs; for example, VEC_NormBarrier and
985: VEC_NormComm = VEC_NormBarrier + 1
987: Level: advanced
992: .keywords: log, event, begin, barrier
993: M*/
995: /*------------------------------------------------ Class Functions --------------------------------------------------*/
998: /*@C
999: PetscLogClassRegister - Registers a class name for logging operations in an application code.
1001: Not Collective
1003: Input Parameter:
1004: . name - The class name
1005:
1006: Output Parameter:
1007: . oclass - The class id or cookie
1009: Level: developer
1011: .keywords: log, class, register
1012: .seealso: ClassLogRegister()
1013: @*/
1014: PetscErrorCode PetscLogClassRegister(PetscCookie *oclass, const char name[])
1015: {
1016: StageLog stageLog;
1017: int stage;
1021: *oclass = PETSC_DECIDE;
1022: PetscLogGetStageLog(&stageLog);
1023: ClassRegLogRegister(stageLog->classLog, name, oclass);
1024: for(stage = 0; stage < stageLog->numStages; stage++) {
1025: ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
1026: }
1027: return(0);
1028: }
1030: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1033: /*@C
1034: PetscLogDump - Dumps logs of objects to a file. This file is intended to
1035: be read by petsc/bin/petscview.
1037: Collective on PETSC_COMM_WORLD
1039: Input Parameter:
1040: . name - an optional file name
1042: Options Database Keys:
1043: + -log - Prints basic log information (for code compiled with PETSC_USE_LOG)
1044: - -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)
1045:
1046: Usage:
1047: .vb
1048: PetscInitialize(...);
1049: PetscLogBegin(); or PetscLogAllBegin();
1050: ... code ...
1051: PetscLogDump(filename);
1052: PetscFinalize();
1053: .ve
1055: Notes:
1056: The default file name is
1057: $ Log.<rank>
1058: where <rank> is the processor number. If no name is specified,
1059: this file will be used.
1061: Level: advanced
1063: .keywords: log, dump
1064: .seealso: PetscLogBegin(), PetscLogAllBegin(), PetscLogPrintSummary()
1065: @*/
1066: PetscErrorCode PetscLogDump(const char sname[])
1067: {
1068: StageLog stageLog;
1069: EventPerfInfo *eventInfo;
1070: FILE *fd;
1071: char file[PETSC_MAX_PATH_LEN], fname[PETSC_MAX_PATH_LEN];
1072: PetscLogDouble flops, _TotalTime;
1073: PetscMPIInt rank;
1074: int action, object, curStage;
1075: PetscEvent event;
1077:
1079: /* Calculate the total elapsed time */
1080: PetscTime(_TotalTime);
1081: _TotalTime -= BaseTime;
1082: /* Open log file */
1083: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1084: if (sname) {
1085: sprintf(file, "%s.%d", sname, rank);
1086: } else {
1087: sprintf(file, "Log.%d", rank);
1088: }
1089: PetscFixFilename(file, fname);
1090: PetscFOpen(PETSC_COMM_WORLD, fname, "w", &fd);
1091: if ((!rank) && (!fd)) SETERRQ1(PETSC_ERR_FILE_OPEN, "Cannot open file: %s", fname);
1092: /* Output totals */
1093: PetscFPrintf(PETSC_COMM_WORLD, fd, "Total Flops %14e %16.8e\n", _TotalFlops, _TotalTime);
1094: PetscFPrintf(PETSC_COMM_WORLD, fd, "Clock Resolution %g\n", 0.0);
1095: /* Output actions */
1096: if (logActions) {
1097: PetscFPrintf(PETSC_COMM_WORLD, fd, "Actions accomplished %d\n", numActions);
1098: for(action = 0; action < numActions; action++) {
1099: PetscFPrintf(PETSC_COMM_WORLD, fd, "%g %d %d %d %d %d %d %g %g %g\n",
1100: actions[action].time, actions[action].action, (int)actions[action].event, (int)actions[action].cookie, actions[action].id1,
1101: actions[action].id2, actions[action].id3, actions[action].flops, actions[action].mem, actions[action].maxmem);
1102: }
1103: }
1104: /* Output objects */
1105: if (logObjects) {
1106: PetscFPrintf(PETSC_COMM_WORLD, fd, "Objects created %d destroyed %d\n", numObjects, numObjectsDestroyed);
1107: for(object = 0; object < numObjects; object++) {
1108: PetscFPrintf(PETSC_COMM_WORLD, fd, "Parent ID: %d Memory: %d\n", objects[object].parent, (int) objects[object].mem);
1109: if (!objects[object].name[0]) {
1110: PetscFPrintf(PETSC_COMM_WORLD, fd,"No Name\n");
1111: } else {
1112: PetscFPrintf(PETSC_COMM_WORLD, fd, "Name: %s\n", objects[object].name);
1113: }
1114: if (objects[object].info[0] != 0) {
1115: PetscFPrintf(PETSC_COMM_WORLD, fd, "No Info\n");
1116: } else {
1117: PetscFPrintf(PETSC_COMM_WORLD, fd, "Info: %s\n", objects[object].info);
1118: }
1119: }
1120: }
1121: /* Output events */
1122: PetscFPrintf(PETSC_COMM_WORLD, fd, "Event log:\n");
1123: PetscLogGetStageLog(&stageLog);
1124: StackTop(stageLog->stack, &curStage);
1125: eventInfo = stageLog->stageInfo[curStage].eventLog->eventInfo;
1126: for(event = 0; event < stageLog->stageInfo[curStage].eventLog->numEvents; event++) {
1127: if (eventInfo[event].time != 0.0) {
1128: flops = eventInfo[event].flops/eventInfo[event].time;
1129: } else {
1130: flops = 0.0;
1131: }
1132: PetscFPrintf(PETSC_COMM_WORLD, fd, "%d %16d %16g %16g %16g\n", event, eventInfo[event].count,
1133: eventInfo[event].flops, eventInfo[event].time, flops);
1134: }
1135: PetscFClose(PETSC_COMM_WORLD, fd);
1136: return(0);
1137: }
1141: /*@C
1142: PetscLogPrintSummary - Prints a summary of the logging.
1144: Collective over MPI_Comm
1146: Input Parameter:
1147: + comm - The MPI communicator (only one processor prints output)
1148: - file - [Optional] The output file name
1150: Options Database Keys:
1151: . -log_summary - Prints summary of log information (for code compiled with PETSC_USE_LOG)
1153: Usage:
1154: .vb
1155: PetscInitialize(...);
1156: PetscLogBegin();
1157: ... code ...
1158: PetscLogPrintSummary(MPI_Comm,filename);
1159: PetscFinalize(...);
1160: .ve
1162: Notes:
1163: By default the summary is printed to stdout.
1164: More extensive examination of the log information can be done with
1165: PetscLogDump(), which is activated by the option -log or -log_all, in
1166: combination with petsc/bin/petscview.
1168: Level: beginner
1169:
1170: .keywords: log, dump, print
1171: .seealso: PetscLogBegin(), PetscLogDump()
1172: @*/
1173: PetscErrorCode PetscLogPrintSummary(MPI_Comm comm, const char filename[])
1174: {
1175: FILE *fd = stdout;
1176: PetscScalar zero = 0.0;
1177: StageLog stageLog;
1178: StageInfo *stageInfo = PETSC_NULL;
1179: EventPerfInfo *eventInfo = PETSC_NULL;
1180: ClassPerfInfo *classInfo;
1181: char arch[10], hostname[64], username[16], pname[PETSC_MAX_PATH_LEN], date[64];
1182: const char *name;
1183: PetscLogDouble locTotalTime, TotalTime, TotalFlops;
1184: PetscLogDouble numMessages, messageLength, avgMessLen, numReductions;
1185: PetscLogDouble stageTime, flops, flopr, mem, mess, messLen, red;
1186: PetscLogDouble fracTime, fracFlops, fracMessages, fracLength, fracReductions, fracMess, fracMessLen, fracRed;
1187: PetscLogDouble fracStageTime, fracStageFlops, fracStageMess, fracStageMessLen, fracStageRed;
1188: PetscLogDouble min, max, tot, ratio, avg, x, y;
1189: PetscLogDouble minf, maxf, totf, ratf, mint, maxt, tott, ratt, ratCt, totm, totml, totr;
1190: PetscMPIInt minCt, maxCt;
1191: PetscMPIInt size, rank;
1192: PetscTruth *localStageUsed, *stageUsed;
1193: PetscTruth *localStageVisible, *stageVisible;
1194: int numStages, localNumEvents, numEvents;
1195: int stage, oclass;
1196: PetscEvent event;
1198: char version[256];
1201: MPI_Comm_size(comm, &size);
1202: MPI_Comm_rank(comm, &rank);
1203: /* Pop off any stages the user forgot to remove */
1204: PetscLogGetStageLog(&stageLog);
1205: StageLogGetCurrent(stageLog, &stage);
1206: while (stage >= 0) {
1207: StageLogPop(stageLog);
1208: StageLogGetCurrent(stageLog, &stage);
1209: }
1210: /* Get the total elapsed time */
1211: PetscTime(locTotalTime); locTotalTime -= BaseTime;
1212: /* Open the summary file */
1213: if (filename) {
1214: PetscFOpen(comm, filename, "w", &fd);
1215: }
1217: PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1218: PetscFPrintf(comm, fd, "*** WIDEN YOUR WINDOW TO 120 CHARACTERS. Use 'enscript -r -fCourier9' to print this document ***\n");
1219: PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1220: PetscFPrintf(comm, fd, "\n---------------------------------------------- PETSc Performance Summary: ----------------------------------------------\n\n");
1221: PetscGetArchType(arch, 10);
1222: PetscGetHostName(hostname, 64);
1223: PetscGetUserName(username, 16);
1224: PetscGetProgramName(pname, PETSC_MAX_PATH_LEN);
1225: PetscGetDate(date, 64);
1226: PetscGetVersion(&version,256);
1227: if (size == 1) {
1228: PetscFPrintf(comm,fd,"%s on a %s named %s with %d processor, by %s %s\n", pname, arch, hostname, size, username, date);
1229: } else {
1230: PetscFPrintf(comm,fd,"%s on a %s named %s with %d processors, by %s %s\n", pname, arch, hostname, size, username, date);
1231: }
1232: PetscFPrintf(comm, fd, "Using %s\n", version);
1234: /* Must preserve reduction count before we go on */
1235: red = allreduce_ct/((PetscLogDouble) size);
1237: /* Calculate summary information */
1238: PetscFPrintf(comm, fd, "\n Max Max/Min Avg Total \n");
1239: /* Time */
1240: MPI_Allreduce(&locTotalTime, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1241: MPI_Allreduce(&locTotalTime, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1242: MPI_Allreduce(&locTotalTime, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1243: avg = (tot)/((PetscLogDouble) size);
1244: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1245: PetscFPrintf(comm, fd, "Time (sec): %5.3e %10.5f %5.3e\n", max, ratio, avg);
1246: TotalTime = tot;
1247: /* Objects */
1248: avg = (PetscLogDouble) numObjects;
1249: MPI_Allreduce(&avg, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1250: MPI_Allreduce(&avg, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1251: MPI_Allreduce(&avg, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1252: avg = (tot)/((PetscLogDouble) size);
1253: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1254: PetscFPrintf(comm, fd, "Objects: %5.3e %10.5f %5.3e\n", max, ratio, avg);
1255: /* Flops */
1256: MPI_Allreduce(&_TotalFlops, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1257: MPI_Allreduce(&_TotalFlops, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1258: MPI_Allreduce(&_TotalFlops, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1259: avg = (tot)/((PetscLogDouble) size);
1260: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1261: PetscFPrintf(comm, fd, "Flops: %5.3e %10.5f %5.3e %5.3e\n", max, ratio, avg, tot);
1262: TotalFlops = tot;
1263: /* Flops/sec -- Must talk to Barry here */
1264: if (locTotalTime != 0.0) flops = _TotalFlops/locTotalTime; else flops = 0.0;
1265: MPI_Allreduce(&flops, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1266: MPI_Allreduce(&flops, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1267: MPI_Allreduce(&flops, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1268: avg = (tot)/((PetscLogDouble) size);
1269: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1270: PetscFPrintf(comm, fd, "Flops/sec: %5.3e %10.5f %5.3e %5.3e\n", max, ratio, avg, tot);
1271: /* Memory */
1272: PetscMallocGetMaximumUsage(&mem);
1273: if (mem > 0.0) {
1274: MPI_Allreduce(&mem, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1275: MPI_Allreduce(&mem, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1276: MPI_Allreduce(&mem, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1277: avg = (tot)/((PetscLogDouble) size);
1278: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1279: PetscFPrintf(comm, fd, "Memory: %5.3e %10.5f %5.3e\n", max, ratio, tot);
1280: }
1281: /* Messages */
1282: mess = 0.5*(irecv_ct + isend_ct + recv_ct + send_ct);
1283: MPI_Allreduce(&mess, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1284: MPI_Allreduce(&mess, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1285: MPI_Allreduce(&mess, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1286: avg = (tot)/((PetscLogDouble) size);
1287: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1288: PetscFPrintf(comm, fd, "MPI Messages: %5.3e %10.5f %5.3e %5.3e\n", max, ratio, avg, tot);
1289: numMessages = tot;
1290: /* Message Lengths */
1291: mess = 0.5*(irecv_len + isend_len + recv_len + send_len);
1292: MPI_Allreduce(&mess, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1293: MPI_Allreduce(&mess, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1294: MPI_Allreduce(&mess, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1295: if (numMessages != 0) avg = (tot)/(numMessages); else avg = 0.0;
1296: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1297: PetscFPrintf(comm, fd, "MPI Message Lengths: %5.3e %10.5f %5.3e %5.3e\n", max, ratio, avg, tot);
1298: messageLength = tot;
1299: /* Reductions */
1300: MPI_Allreduce(&red, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1301: MPI_Allreduce(&red, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1302: MPI_Allreduce(&red, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1303: if (min != 0.0) ratio = max/min; else ratio = 0.0;
1304: PetscFPrintf(comm, fd, "MPI Reductions: %5.3e %10.5f\n", max, ratio);
1305: numReductions = tot;
1306: PetscFPrintf(comm, fd, "\nFlop counting convention: 1 flop = 1 real number operation of type (multiply/divide/add/subtract)\n");
1307: PetscFPrintf(comm, fd, " e.g., VecAXPY() for real vectors of length N --> 2N flops\n");
1308: PetscFPrintf(comm, fd, " and VecAXPY() for complex vectors of length N --> 8N flops\n");
1310: /* Get total number of stages --
1311: Currently, a single processor can register more stages than another, but stages must all be registered in order.
1312: We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
1313: This seems best accomplished by assoicating a communicator with each stage.
1314: */
1315: MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm);
1316: PetscMalloc(numStages * sizeof(PetscTruth), &localStageUsed);
1317: PetscMalloc(numStages * sizeof(PetscTruth), &stageUsed);
1318: PetscMalloc(numStages * sizeof(PetscTruth), &localStageVisible);
1319: PetscMalloc(numStages * sizeof(PetscTruth), &stageVisible);
1320: if (numStages > 0) {
1321: stageInfo = stageLog->stageInfo;
1322: for(stage = 0; stage < numStages; stage++) {
1323: if (stage < stageLog->numStages) {
1324: localStageUsed[stage] = stageInfo[stage].used;
1325: localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
1326: } else {
1327: localStageUsed[stage] = PETSC_FALSE;
1328: localStageVisible[stage] = PETSC_TRUE;
1329: }
1330: }
1331: MPI_Allreduce(localStageUsed, stageUsed, numStages, MPI_INT, MPI_LOR, comm);
1332: MPI_Allreduce(localStageVisible, stageVisible, numStages, MPI_INT, MPI_LAND, comm);
1333: for(stage = 0; stage < numStages; stage++) {
1334: if (stageUsed[stage]) {
1335: PetscFPrintf(comm, fd, "\nSummary of Stages: ----- Time ------ ----- Flops ----- --- Messages --- -- Message Lengths -- -- Reductions --\n");
1336: PetscFPrintf(comm, fd, " Avg %%Total Avg %%Total counts %%Total Avg %%Total counts %%Total \n");
1337: break;
1338: }
1339: }
1340: for(stage = 0; stage < numStages; stage++) {
1341: if (!stageUsed[stage]) continue;
1342: if (localStageUsed[stage]) {
1343: MPI_Allreduce(&stageInfo[stage].perfInfo.time, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1344: MPI_Allreduce(&stageInfo[stage].perfInfo.flops, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1345: MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1346: MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1347: MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1348: name = stageInfo[stage].name;
1349: } else {
1350: MPI_Allreduce(&zero, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1351: MPI_Allreduce(&zero, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1352: MPI_Allreduce(&zero, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1353: MPI_Allreduce(&zero, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1354: MPI_Allreduce(&zero, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1355: name = "";
1356: }
1357: mess *= 0.5; messLen *= 0.5; red /= size;
1358: if (TotalTime != 0.0) fracTime = stageTime/TotalTime; else fracTime = 0.0;
1359: if (TotalFlops != 0.0) fracFlops = flops/TotalFlops; else fracFlops = 0.0;
1360: /* Talk to Barry if (stageTime != 0.0) flops = (size*flops)/stageTime; else flops = 0.0; */
1361: if (numMessages != 0.0) fracMessages = mess/numMessages; else fracMessages = 0.0;
1362: if (numMessages != 0.0) avgMessLen = messLen/numMessages; else avgMessLen = 0.0;
1363: if (messageLength != 0.0) fracLength = messLen/messageLength; else fracLength = 0.0;
1364: if (numReductions != 0.0) fracReductions = red/numReductions; else fracReductions = 0.0;
1365: 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",
1366: stage, name, stageTime/size, 100.0*fracTime, flops, 100.0*fracFlops,
1367: mess, 100.0*fracMessages, avgMessLen, 100.0*fracLength, red, 100.0*fracReductions);
1368: }
1369: }
1371: PetscFPrintf(comm, fd,
1372: "\n------------------------------------------------------------------------------------------------------------------------\n");
1373:
1374: PetscFPrintf(comm, fd, "See the 'Profiling' chapter of the users' manual for details on interpreting output.\n");
1375: PetscFPrintf(comm, fd, "Phase summary info:\n");
1376: PetscFPrintf(comm, fd, " Count: number of times phase was executed\n");
1377: PetscFPrintf(comm, fd, " Time and Flops/sec: Max - maximum over all processors\n");
1378: PetscFPrintf(comm, fd, " Ratio - ratio of maximum to minimum over all processors\n");
1379: PetscFPrintf(comm, fd, " Mess: number of messages sent\n");
1380: PetscFPrintf(comm, fd, " Avg. len: average message length\n");
1381: PetscFPrintf(comm, fd, " Reduct: number of global reductions\n");
1382: PetscFPrintf(comm, fd, " Global: entire computation\n");
1383: PetscFPrintf(comm, fd, " Stage: stages of a computation. Set stages with PetscLogStagePush() and PetscLogStagePop().\n");
1384: PetscFPrintf(comm, fd, " %%T - percent time in this phase %%F - percent flops in this phase\n");
1385: PetscFPrintf(comm, fd, " %%M - percent messages in this phase %%L - percent message lengths in this phase\n");
1386: PetscFPrintf(comm, fd, " %%R - percent reductions in this phase\n");
1387: PetscFPrintf(comm, fd, " Total Mflop/s: 10e-6 * (sum of flops over all processors)/(max time over all processors)\n");
1388: PetscFPrintf(comm, fd,
1389: "------------------------------------------------------------------------------------------------------------------------\n");
1390:
1392: #if defined(PETSC_USE_DEBUG)
1393: PetscFPrintf(comm, fd, "\n\n");
1394: PetscFPrintf(comm, fd, " ##########################################################\n");
1395: PetscFPrintf(comm, fd, " # #\n");
1396: PetscFPrintf(comm, fd, " # WARNING!!! #\n");
1397: PetscFPrintf(comm, fd, " # #\n");
1398: PetscFPrintf(comm, fd, " # This code was compiled with a debugging option, #\n");
1399: PetscFPrintf(comm, fd, " # To get timing results run config/configure.py #\n");
1400: PetscFPrintf(comm, fd, " # using --with-debugging=no, the performance will #\n");
1401: PetscFPrintf(comm, fd, " # be generally two or three times faster. #\n");
1402: PetscFPrintf(comm, fd, " # #\n");
1403: PetscFPrintf(comm, fd, " ##########################################################\n\n\n");
1404: #endif
1405: #if defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_FORTRAN_KERNELS)
1406: PetscFPrintf(comm, fd, "\n\n");
1407: PetscFPrintf(comm, fd, " ##########################################################\n");
1408: PetscFPrintf(comm, fd, " # #\n");
1409: PetscFPrintf(comm, fd, " # WARNING!!! #\n");
1410: PetscFPrintf(comm, fd, " # #\n");
1411: PetscFPrintf(comm, fd, " # The code for various complex numbers numerical #\n");
1412: PetscFPrintf(comm, fd, " # kernels uses C++, which generally is not well #\n");
1413: PetscFPrintf(comm, fd, " # optimized. For performance that is about 4-5 times #\n");
1414: PetscFPrintf(comm, fd, " # faster, specify --with-fortran-kernels=generic #\n");
1415: PetscFPrintf(comm, fd, " # when running config/configure.py. #\n");
1416: PetscFPrintf(comm, fd, " # #\n");
1417: PetscFPrintf(comm, fd, " ##########################################################\n\n\n");
1418: #endif
1420: if (!PetscPreLoadingUsed) {
1421: PetscFPrintf(comm,fd,"\n\n");
1422: PetscFPrintf(comm,fd," ##########################################################\n");
1423: PetscFPrintf(comm,fd," # #\n");
1424: PetscFPrintf(comm,fd," # WARNING!!! #\n");
1425: PetscFPrintf(comm,fd," # #\n");
1426: PetscFPrintf(comm,fd," # This code was run without the PreLoadBegin() #\n");
1427: PetscFPrintf(comm,fd," # macros. To get timing results we always recommend #\n");
1428: PetscFPrintf(comm,fd," # preloading. otherwise timing numbers may be #\n");
1429: PetscFPrintf(comm,fd," # meaningless. #\n");
1430: PetscFPrintf(comm,fd," ##########################################################\n\n\n");
1431: }
1433: /* Report events */
1434: PetscFPrintf(comm, fd,
1435: "Event Count Time (sec) Flops/sec --- Global --- --- Stage --- Total\n");
1436:
1437: PetscFPrintf(comm, fd,
1438: " Max Ratio Max Ratio Max Ratio Mess Avg len Reduct %%T %%F %%M %%L %%R %%T %%F %%M %%L %%R Mflop/s\n");
1439:
1440: PetscFPrintf(comm,fd,
1441: "------------------------------------------------------------------------------------------------------------------------\n");
1443:
1444: /* Problem: The stage name will not show up unless the stage executed on proc 1 */
1445: for(stage = 0; stage < numStages; stage++) {
1446: if (!stageVisible[stage]) continue;
1447: if (localStageUsed[stage]) {
1448: PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1449: MPI_Allreduce(&stageInfo[stage].perfInfo.time, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1450: MPI_Allreduce(&stageInfo[stage].perfInfo.flops, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1451: MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1452: MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1453: MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1454: } else {
1455: PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1456: MPI_Allreduce(&zero, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1457: MPI_Allreduce(&zero, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1458: MPI_Allreduce(&zero, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1459: MPI_Allreduce(&zero, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1460: MPI_Allreduce(&zero, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1461: }
1462: mess *= 0.5; messLen *= 0.5; red /= size;
1464: /* Get total number of events in this stage --
1465: Currently, a single processor can register more events than another, but events must all be registered in order,
1466: just like stages. We can removed this requirement if necessary by having a global event numbering and indirection
1467: on the event ID. This seems best accomplished by assoicating a communicator with each stage.
1469: Problem: If the event did not happen on proc 1, its name will not be available.
1470: Problem: Event visibility is not implemented
1471: */
1472: if (localStageUsed[stage]) {
1473: eventInfo = stageLog->stageInfo[stage].eventLog->eventInfo;
1474: localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
1475: } else {
1476: localNumEvents = 0;
1477: }
1478: MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm);
1479: for(event = 0; event < numEvents; event++) {
1480: if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents)) {
1481: if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) {
1482: flopr = eventInfo[event].flops/eventInfo[event].time;
1483: } else {
1484: flopr = 0.0;
1485: }
1486: MPI_Allreduce(&flopr, &minf, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1487: MPI_Allreduce(&flopr, &maxf, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1488: MPI_Allreduce(&eventInfo[event].flops, &totf, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1489: MPI_Allreduce(&eventInfo[event].time, &mint, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1490: MPI_Allreduce(&eventInfo[event].time, &maxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1491: MPI_Allreduce(&eventInfo[event].time, &tott, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1492: MPI_Allreduce(&eventInfo[event].numMessages, &totm, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1493: MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1494: MPI_Allreduce(&eventInfo[event].numReductions, &totr, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1495: MPI_Allreduce(&eventInfo[event].count, &minCt, 1, MPI_INT, MPI_MIN, comm);
1496: MPI_Allreduce(&eventInfo[event].count, &maxCt, 1, MPI_INT, MPI_MAX, comm);
1497: name = stageLog->eventLog->eventInfo[event].name;
1498: } else {
1499: flopr = 0.0;
1500: MPI_Allreduce(&flopr, &minf, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1501: MPI_Allreduce(&flopr, &maxf, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1502: MPI_Allreduce(&zero, &totf, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1503: MPI_Allreduce(&zero, &mint, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1504: MPI_Allreduce(&zero, &maxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1505: MPI_Allreduce(&zero, &tott, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1506: MPI_Allreduce(&zero, &totm, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1507: MPI_Allreduce(&zero, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1508: MPI_Allreduce(&zero, &totr, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1509: MPI_Allreduce(&ierr, &minCt, 1, MPI_INT, MPI_MIN, comm);
1510: MPI_Allreduce(&ierr, &maxCt, 1, MPI_INT, MPI_MAX, comm);
1511: name = "";
1512: }
1513: if (mint < 0.0) SETERRQ2(PETSC_ERR_PLIB,"Minimum time %g over all processors for %s is negative! Not possible!",mint,name);
1514: if (minf < 0.0) SETERRQ2(PETSC_ERR_PLIB,"Minimum flops %g over all processors for %s is negative! Not possible!",minf,name);
1515: totm *= 0.5; totml *= 0.5; totr /= size;
1516:
1517: if (maxCt != 0) {
1518: if (minCt != 0) ratCt = ((PetscLogDouble) maxCt)/minCt; else ratCt = 0.0;
1519: if (mint != 0.0) ratt = maxt/mint; else ratt = 0.0;
1520: if (minf != 0.0) ratf = maxf/minf; else ratf = 0.0;
1521: if (TotalTime != 0.0) fracTime = tott/TotalTime; else fracTime = 0.0;
1522: if (TotalFlops != 0.0) fracFlops = totf/TotalFlops; else fracFlops = 0.0;
1523: if (stageTime != 0.0) fracStageTime = tott/stageTime; else fracStageTime = 0.0;
1524: if (flops != 0.0) fracStageFlops = totf/flops; else fracStageFlops = 0.0;
1525: if (numMessages != 0.0) fracMess = totm/numMessages; else fracMess = 0.0;
1526: if (messageLength != 0.0) fracMessLen = totml/messageLength; else fracMessLen = 0.0;
1527: if (numReductions != 0.0) fracRed = totr/numReductions; else fracRed = 0.0;
1528: if (mess != 0.0) fracStageMess = totm/mess; else fracStageMess = 0.0;
1529: if (messLen != 0.0) fracStageMessLen = totml/messLen; else fracStageMessLen = 0.0;
1530: if (red != 0.0) fracStageRed = totr/red; else fracStageRed = 0.0;
1531: if (totm != 0.0) totml /= totm; else totml = 0.0;
1532: if (maxt != 0.0) flopr = totf/maxt; else flopr = 0.0;
1533: PetscFPrintf(comm, fd,
1534: "%-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",
1535: name, maxCt, ratCt, maxt, ratt, maxf, ratf, totm, totml, totr,
1536: 100.0*fracTime, 100.0*fracFlops, 100.0*fracMess, 100.0*fracMessLen, 100.0*fracRed,
1537: 100.0*fracStageTime, 100.0*fracStageFlops, 100.0*fracStageMess, 100.0*fracStageMessLen, 100.0*fracStageRed,
1538: flopr/1.0e6);
1539: }
1540: }
1541: }
1543: /* Memory usage and object creation */
1544: PetscFPrintf(comm, fd,
1545: "------------------------------------------------------------------------------------------------------------------------\n");
1546: PetscFPrintf(comm, fd, "\n");
1547: PetscFPrintf(comm, fd, "Memory usage is given in bytes:\n\n");
1549: /* Right now, only stages on the first processor are reported here, meaning only objects associated with
1550: the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
1551: stats for stages local to processor sets.
1552: */
1553: /* We should figure out the longest object name here (now 20 characters) */
1554: PetscFPrintf(comm, fd, "Object Type Creations Destructions Memory Descendants' Mem.\n");
1555: for(stage = 0; stage < numStages; stage++) {
1556: if (localStageUsed[stage]) {
1557: classInfo = stageLog->stageInfo[stage].classLog->classInfo;
1558: PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1559: for(oclass = 0; oclass < stageLog->stageInfo[stage].classLog->numClasses; oclass++) {
1560: if ((classInfo[oclass].creations > 0) || (classInfo[oclass].destructions > 0)) {
1561: PetscFPrintf(comm, fd, "%20s %5d %5d %9d %g\n", stageLog->classLog->classInfo[oclass].name,
1562: classInfo[oclass].creations, classInfo[oclass].destructions, (int) classInfo[oclass].mem,
1563: classInfo[oclass].descMem);
1564: }
1565: }
1566: } else {
1567: PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1568: }
1569: }
1571: PetscFree(localStageUsed);
1572: PetscFree(stageUsed);
1573: PetscFree(localStageVisible);
1574: PetscFree(stageVisible);
1576: /* Information unrelated to this particular run */
1577: PetscFPrintf(comm, fd,
1578: "========================================================================================================================\n");
1579: PetscTime(y);
1580: PetscTime(x);
1581: PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1582: PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1583: PetscFPrintf(comm,fd,"Average time to get PetscTime(): %g\n", (y-x)/10.0);
1584: /* MPI information */
1585: if (size > 1) {
1586: MPI_Status status;
1587: PetscMPIInt tag;
1588: MPI_Comm newcomm;
1590: MPI_Barrier(comm);
1591: PetscTime(x);
1592: MPI_Barrier(comm);
1593: MPI_Barrier(comm);
1594: MPI_Barrier(comm);
1595: MPI_Barrier(comm);
1596: MPI_Barrier(comm);
1597: PetscTime(y);
1598: PetscFPrintf(comm, fd, "Average time for MPI_Barrier(): %g\n", (y-x)/5.0);
1599: PetscCommDuplicate(comm,&newcomm, &tag);
1600: MPI_Barrier(comm);
1601: if (rank) {
1602: MPI_Recv(0, 0, MPI_INT, rank-1, tag, newcomm, &status);
1603: MPI_Send(0, 0, MPI_INT, (rank+1)%size, tag, newcomm);
1604: } else {
1605: PetscTime(x);
1606: MPI_Send(0, 0, MPI_INT, 1, tag, newcomm);
1607: MPI_Recv(0, 0, MPI_INT, size-1, tag, newcomm, &status);
1608: PetscTime(y);
1609: PetscFPrintf(comm,fd,"Average time for zero size MPI_Send(): %g\n", (y-x)/size);
1610: }
1611: PetscCommDestroy(&newcomm);
1612: }
1613: if (!rank) {
1614: PetscOptionsPrint(fd);
1615: }
1616: /* Machine and compile information */
1617: #if defined(PETSC_USE_FORTRAN_KERNELS)
1618: PetscFPrintf(comm, fd, "Compiled with FORTRAN kernels\n");
1619: #else
1620: PetscFPrintf(comm, fd, "Compiled without FORTRAN kernels\n");
1621: #endif
1622: #if defined(PETSC_USE_SINGLE)
1623: PetscFPrintf(comm, fd, "Compiled with single precision PetscScalar and PetscReal\n");
1624: #elif defined(PETSC_USE_LONGDOUBLE)
1625: PetscFPrintf(comm, fd, "Compiled with long double precision PetscScalar and PetscReal\n");
1626: #elif defined(PETSC_USE_INT)
1627: PetscFPrintf(comm, fd, "Compiled with int PetscScalar and PetscReal\n");
1628: #endif
1630: #if defined(PETSC_USE_MAT_SINGLE)
1631: PetscFPrintf(comm, fd, "Compiled with single precision matrices\n");
1632: #else
1633: PetscFPrintf(comm, fd, "Compiled with full precision matrices (default)\n");
1634: #endif
1635: PetscFPrintf(comm, fd, "sizeof(short) %d sizeof(int) %d sizeof(long) %d sizeof(void*) %d sizeof(PetscScalar) %d\n",
1636: (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(void*),(int) sizeof(PetscScalar));
1638: PetscFPrintf(comm, fd, "Configure run at: %s\n",petscconfigureruntime);
1639: PetscFPrintf(comm, fd, "Configure options: %s",petscconfigureoptions);
1640: PetscFPrintf(comm, fd, "%s", petscmachineinfo);
1641: PetscFPrintf(comm, fd, "%s", petsccompilerinfo);
1642: PetscFPrintf(comm, fd, "%s", petsccompilerflagsinfo);
1643: PetscFPrintf(comm, fd, "%s", petsclinkerinfo);
1645: /* Cleanup */
1646: PetscFPrintf(comm, fd, "\n");
1647: PetscFClose(comm, fd);
1648: return(0);
1649: }
1651: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
1654: /*@C
1655: PetscGetFlops - Returns the number of flops used on this processor
1656: since the program began.
1658: Not Collective
1660: Output Parameter:
1661: flops - number of floating point operations
1663: Notes:
1664: A global counter logs all PETSc flop counts. The user can use
1665: PetscLogFlops() to increment this counter to include flops for the
1666: application code.
1668: PETSc automatically logs library events if the code has been
1669: compiled with -DPETSC_USE_LOG (which is the default), and -log,
1670: -log_summary, or -log_all are specified. PetscLogFlops() is
1671: intended for logging user flops to supplement this PETSc
1672: information.
1674: Level: intermediate
1676: .keywords: log, flops, floating point operations
1678: .seealso: PetscGetTime(), PetscLogFlops()
1679: @*/
1680: PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
1681: {
1683: *flops = _TotalFlops;
1684: return(0);
1685: }
1689: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
1690: {
1692: va_list Argp;
1695: if (!logObjects) return(0);
1696: va_start(Argp, format);
1697: PetscVSNPrintf(objects[obj->id].info, 64,format, Argp);
1698: va_end(Argp);
1699: return(0);
1700: }
1702: #else /* end of -DPETSC_USE_LOG section */
1706: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
1707: {
1709: return(0);
1710: }
1712: #endif /* PETSC_USE_LOG*/
1716: /*@
1717: PetscLogGetStageLog - This function returns the default stage logging object.
1719: Not collective
1721: Output Parameter:
1722: . stageLog - The default StageLog
1724: Level: beginner
1726: .keywords: log, stage
1727: .seealso: StageLogCreate()
1728: @*/
1729: PetscErrorCode PetscLogGetStageLog(StageLog *stageLog)
1730: {
1733: *stageLog = _stageLog;
1734: return(0);
1735: }
1737: /*MC
1738: PetscLogFlops - Adds floating point operations to the global counter.
1740: Input Parameter:
1741: . f - flop counter
1743: Synopsis:
1744: void PetscLogFlops(int f)
1746: Usage:
1747: .vb
1748: int USER_EVENT;
1751: [code segment to monitor]
1752: PetscLogFlops(user_flops)
1754: .ve
1756: Notes:
1757: A global counter logs all PETSc flop counts. The user can use
1758: PetscLogFlops() to increment this counter to include flops for the
1759: application code.
1761: PETSc automatically logs library events if the code has been
1762: compiled with -DPETSC_USE_LOG (which is the default), and -log,
1763: -log_summary, or -log_all are specified. PetscLogFlops() is
1764: intended for logging user flops to supplement this PETSc
1765: information.
1767: Level: intermediate
1771: .keywords: log, flops, floating point operations
1772: M*/
1774: /*MC
1775: PreLoadBegin - Begin a segment of code that may be preloaded (run twice)
1776: to get accurate timings
1778: Input Parameter:
1779: + flag - PETSC_TRUE to run twice, PETSC_FALSE to run once, may be overridden
1780: with command line option -preload true or -preload false
1781: - name - name of first stage (lines of code timed separately with -log_summary) to
1782: be preloaded
1784: Synopsis:
1785: void PreLoadBegin(PetscTruth flag,char *name);
1787: Usage:
1788: .vb
1789: PreLoadBegin(PETSC_TRUE,"first stage);
1790: lines of code
1791: PreLoadStage("second stage");
1792: lines of code
1793: PreLoadEnd();
1794: .ve
1796: Notes: Only works in C/C++, not Fortran
1798: Flags available within the macro.
1799: + PetscPreLoadingUsed - true if we are or have done preloading
1800: . PetscPreLoadingOn - true if it is CURRENTLY doing preload
1801: . PreLoadIt - 0 for the first computation (with preloading turned off it is only 0) 1 for the second
1802: - PreLoadMax - number of times it will do the computation, only one when preloading is turned on
1803: The first two variables are available throughout the program, the second two only between the PreLoadBegin()
1804: and PreLoadEnd()
1806: Level: intermediate
1810: Concepts: preloading
1811: Concepts: timing^accurate
1812: Concepts: paging^eliminating effects of
1815: M*/
1817: /*MC
1818: PreLoadEnd - End a segment of code that may be preloaded (run twice)
1819: to get accurate timings
1821: Synopsis:
1822: void PreLoadEnd(void);
1824: Usage:
1825: .vb
1826: PreLoadBegin(PETSC_TRUE,"first stage);
1827: lines of code
1828: PreLoadStage("second stage");
1829: lines of code
1830: PreLoadEnd();
1831: .ve
1833: Notes: only works in C/C++ not fortran
1835: Level: intermediate
1839: M*/
1841: /*MC
1842: PreLoadStage - Start a new segment of code to be timed separately.
1843: to get accurate timings
1845: Synopsis:
1846: void PreLoadStage(char *name);
1848: Usage:
1849: .vb
1850: PreLoadBegin(PETSC_TRUE,"first stage);
1851: lines of code
1852: PreLoadStage("second stage");
1853: lines of code
1854: PreLoadEnd();
1855: .ve
1857: Notes: only works in C/C++ not fortran
1859: Level: intermediate
1863: M*/
1865: /*----------------------------------------------- Stack Functions ---------------------------------------------------*/
1868: /*@C
1869: StackDestroy - This function destroys a stack.
1871: Not Collective
1873: Input Parameter:
1874: . stack - The stack
1876: Level: beginner
1878: .keywords: log, stack, destroy
1879: .seealso: StackCreate(), StackEmpty(), StackPush(), StackPop(), StackTop()
1880: @*/
1881: PetscErrorCode StackDestroy(IntStack stack)
1882: {
1886: PetscFree(stack->stack);
1887: PetscFree(stack);
1888: return(0);
1889: }
1893: /*@C
1894: StackEmpty - This function determines whether any items have been pushed.
1896: Not Collective
1898: Input Parameter:
1899: . stack - The stack
1901: Output Parameter:
1902: . empty - PETSC_TRUE if the stack is empty
1904: Level: intermediate
1906: .keywords: log, stack, empty
1907: .seealso: StackCreate(), StackDestroy(), StackPush(), StackPop(), StackTop()
1908: @*/
1909: PetscErrorCode StackEmpty(IntStack stack, PetscTruth *empty)
1910: {
1913: if (stack->top == -1) {
1914: *empty = PETSC_TRUE;
1915: } else {
1916: *empty = PETSC_FALSE;
1917: }
1918: return(0);
1919: }
1923: /*@C
1924: StackTop - This function returns the top of the stack.
1926: Not Collective
1928: Input Parameter:
1929: . stack - The stack
1931: Output Parameter:
1932: . top - The integer on top of the stack
1934: Level: intermediate
1936: .keywords: log, stack, top
1937: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackPop()
1938: @*/
1939: PetscErrorCode StackTop(IntStack stack, int *top)
1940: {
1943: *top = stack->stack[stack->top];
1944: return(0);
1945: }
1949: /*@C
1950: StackPush - This function pushes an integer on the stack.
1952: Not Collective
1954: Input Parameters:
1955: + stack - The stack
1956: - item - The integer to push
1958: Level: intermediate
1960: .keywords: log, stack, push
1961: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPop(), StackTop()
1962: @*/
1963: PetscErrorCode StackPush(IntStack stack, int item)
1964: {
1965: int *array;
1969: stack->top++;
1970: if (stack->top >= stack->max) {
1971: PetscMalloc(stack->max*2 * sizeof(int), &array);
1972: PetscMemcpy(array, stack->stack, stack->max * sizeof(int));
1973: PetscFree(stack->stack);
1974: stack->stack = array;
1975: stack->max *= 2;
1976: }
1977: stack->stack[stack->top] = item;
1978: return(0);
1979: }
1983: /*@C
1984: StackPop - This function pops an integer from the stack.
1986: Not Collective
1988: Input Parameter:
1989: . stack - The stack
1991: Output Parameter:
1992: . item - The integer popped
1994: Level: intermediate
1996: .keywords: log, stack, pop
1997: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackTop()
1998: @*/
1999: PetscErrorCode StackPop(IntStack stack, int *item)
2000: {
2003: if (stack->top == -1) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Stack is empty");
2004: *item = stack->stack[stack->top--];
2005: return(0);
2006: }
2010: /*@C
2011: StackCreate - This function creates a stack.
2013: Not Collective
2015: Output Parameter:
2016: . stack - The stack
2018: Level: beginner
2020: .keywords: log, stack, pop
2021: .seealso: StackDestroy(), StackEmpty(), StackPush(), StackPop(), StackTop()
2022: @*/
2023: PetscErrorCode StackCreate(IntStack *stack)
2024: {
2025: IntStack s;
2030: PetscNew(struct _n_IntStack, &s);
2031: s->top = -1;
2032: s->max = 128;
2033: PetscMalloc(s->max * sizeof(int), &s->stack);
2034: PetscMemzero(s->stack, s->max * sizeof(int));
2035: *stack = s;
2036: return(0);
2037: }