Actual source code: eventLog.c

  1: /* $Id: eventLog.c,v 1.3 2000/08/16 05:14:09 knepley Exp $ */

 3:  #include petsc.h
 4:  #include src/sys/src/plog/ptime.h
 5:  #include plog.h

  7: /* Variables for the tracing logger */
  8: extern FILE          *tracefile;
  9: extern int            tracelevel;
 10: extern char          *traceblanks;
 11: extern char           tracespace[128];
 12: extern PetscLogDouble tracetime;

 14: /*----------------------------------------------- Creation Functions -------------------------------------------------*/
 15: /*@C
 16:   EventRegLogCreate - This creates a EventRegLog object.

 18:   Not collective

 20:   Input Parameter:
 21: . eventLog - The EventRegLog

 23:   Level: beginner

 25: .keywords: log, event, create
 26: .seealso: EventRegLogDestroy(), StageLogCreate()
 27: @*/
 28: int EventRegLogCreate(EventRegLog *eventLog) {
 29:   EventRegLog l;
 30:   int         ierr;

 33:   PetscNew(struct _EventRegLog, &l);
 34:   l->numEvents   = 0;
 35:   l->maxEvents   = 100;
 36:   PetscMalloc(l->maxEvents * sizeof(EventRegInfo), &l->eventInfo);
 37:   *eventLog = l;
 38:   return(0);
 39: }

 41: /*@C
 42:   EventRegLogDestroy - This destroys a EventRegLog object.

 44:   Not collective

 46:   Input Paramter:
 47: . eventLog - The EventRegLog

 49:   Level: beginner

 51: .keywords: log, event, destroy
 52: .seealso: EventRegLogCreate()
 53: @*/
 54: int EventRegLogDestroy(EventRegLog eventLog) {
 55:   int e;

 59:   for(e = 0; e < eventLog->numEvents; e++) {
 60:     PetscFree(eventLog->eventInfo[e].name);
 61:   }
 62:   PetscFree(eventLog->eventInfo);
 63:   PetscFree(eventLog);
 64:   return(0);
 65: }

 67: /*@C
 68:   EventPerfLogCreate - This creates a EventPerfLog object.

 70:   Not collective

 72:   Input Parameter:
 73: . eventLog - The EventPerfLog

 75:   Level: beginner

 77: .keywords: log, event, create
 78: .seealso: EventPerfLogDestroy(), StageLogCreate()
 79: @*/
 80: int EventPerfLogCreate(EventPerfLog *eventLog) {
 81:   EventPerfLog l;
 82:   int          ierr;

 85:   PetscNew(struct _EventPerfLog, &l);
 86:   l->numEvents   = 0;
 87:   l->maxEvents   = 100;
 88:   PetscMalloc(l->maxEvents * sizeof(EventPerfInfo), &l->eventInfo);
 89:   *eventLog = l;
 90:   return(0);
 91: }

 93: /*@C
 94:   EventPerfLogDestroy - This destroys a EventPerfLog object.

 96:   Not collective

 98:   Input Paramter:
 99: . eventLog - The EventPerfLog

101:   Level: beginner

103: .keywords: log, event, destroy
104: .seealso: EventPerfLogCreate()
105: @*/
106: int EventPerfLogDestroy(EventPerfLog eventLog) {

110:   PetscFree(eventLog->eventInfo);
111:   PetscFree(eventLog);
112:   return(0);
113: }

115: /*------------------------------------------------ General Functions -------------------------------------------------*/
116: /*@C
117:   EventPerfInfoClear - This clears a EventPerfInfo object.

119:   Not collective

121:   Input Paramter:
122: . eventInfo - The EventPerfInfo

124:   Level: beginner

126: .keywords: log, event, destroy
127: .seealso: EventPerfLogCreate()
128: @*/
129: int EventPerfInfoClear(EventPerfInfo *eventInfo) {
131:   eventInfo->id            = -1;
132:   eventInfo->active        = PETSC_TRUE;
133:   eventInfo->visible       = PETSC_TRUE;
134:   eventInfo->depth         = 0;
135:   eventInfo->count         = 0;
136:   eventInfo->flops         = 0.0;
137:   eventInfo->time          = 0.0;
138:   eventInfo->numMessages   = 0.0;
139:   eventInfo->messageLength = 0.0;
140:   eventInfo->numReductions = 0.0;
141:   return(0);
142: }

144: /*@C
145:   EventPerfInfoCopy - Copy the activity and visibility data in eventInfo to outInfo

147:   Not collective

149:   Input Paramter:
150: . eventInfo - The input EventPerfInfo

152:   Output Paramter:
153: . outInfo   - The output EventPerfInfo

155:   Level: beginner

157: .keywords: log, event, copy
158: .seealso: EventPerfInfoClear()
159: @*/
160: int EventPerfInfoCopy(EventPerfInfo *eventInfo, EventPerfInfo *outInfo) {
162:   outInfo->id      = eventInfo->id;
163:   outInfo->active  = eventInfo->active;
164:   outInfo->visible = eventInfo->visible;
165:   return(0);
166: }

168: /*@C
169:   EventPerfLogEnsureSize - This ensures that a EventPerfLog is at least of a certain size.

171:   Not collective

173:   Input Paramters:
174: + eventLog - The EventPerfLog
175: - size     - The size

177:   Level: intermediate

179: .keywords: log, event, size, ensure
180: .seealso: EventPerfLogCreate()
181: @*/
182: int EventPerfLogEnsureSize(EventPerfLog eventLog, int size) {
183:   EventPerfInfo *eventInfo;
184:   int            ierr;

187:   while(size > eventLog->maxEvents) {
188:     PetscMalloc(eventLog->maxEvents*2 * sizeof(EventPerfInfo), &eventInfo);
189:     PetscMemcpy(eventInfo, eventLog->eventInfo, eventLog->maxEvents * sizeof(EventPerfInfo));
190:     PetscFree(eventLog->eventInfo);
191:     eventLog->eventInfo  = eventInfo;
192:     eventLog->maxEvents *= 2;
193:   }
194:   while(eventLog->numEvents < size) {
195:     EventPerfInfoClear(&eventLog->eventInfo[eventLog->numEvents++]);
196:   }
197:   return(0);
198: }

200: /*--------------------------------------------- Registration Functions ----------------------------------------------*/
201: /*@C
202:   EventRegLogRegister - Registers an event for logging operations in an application code.

204:   Not Collective

206:   Input Parameters:
207: + eventLog - The EventLog
208: . ename    - The name associated with the event
209: - cookie   - The cookie associated to the class for this event

211:   Output Parameter:
212: . event    - The event

214:   Example of Usage:
215: .vb
216:       int USER_EVENT;
217:       int user_event_flops;
218:       PetscLogEventRegister(&USER_EVENT,"User event name");
219:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
220:          [code segment to monitor]
221:          PetscLogFlops(user_event_flops);
222:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
223: .ve

225:   Notes: 
226:   PETSc automatically logs library events if the code has been
227:   compiled with -DPETSC_USE_LOG (which is the default) and -log,
228:   -log_summary, or -log_all are specified.  PetscLogEventRegister() is
229:   intended for logging user events to supplement this PETSc
230:   information. 

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

239:   Level: intermediate

241: .keywords: log, event, register
242: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventMPEActivate(), PetscLogEventMPEDeactivate(),
243:           EventLogActivate(), EventLogDeactivate()
244: @*/
245: int EventRegLogRegister(EventRegLog eventLog, const char ename[], int cookie, PetscEvent *event) {
246:   EventRegInfo *eventInfo;
247:   char         *str;
248:   int           e;
249:   int           ierr;

254:   /* Should check cookie I think */
255:   e = eventLog->numEvents++;
256:   if (eventLog->numEvents > eventLog->maxEvents) {
257:     PetscMalloc(eventLog->maxEvents*2 * sizeof(EventRegInfo), &eventInfo);
258:     PetscMemcpy(eventInfo, eventLog->eventInfo, eventLog->maxEvents * sizeof(EventRegInfo));
259:     PetscFree(eventLog->eventInfo);
260:     eventLog->eventInfo  = eventInfo;
261:     eventLog->maxEvents *= 2;
262:   }
263:   PetscStrallocpy(ename, &str);
264:   eventLog->eventInfo[e].name   = str;
265:   eventLog->eventInfo[e].cookie = cookie;
266: #if defined(PETSC_HAVE_MPE)
267:   if (UseMPE) {
268:     char *color;
269:     int   rank, beginID, endID;

271:     beginID = MPE_Log_get_event_number();
272:     endID   = MPE_Log_get_event_number();
273:     eventLog->eventInfo[e].mpe_id_begin = beginID;
274:     eventLog->eventInfo[e].mpe_id_end   = endID;
275:     MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
276:     if (!rank) {
277:       PetscLogGetRGBColor(&color);
278:       MPE_Describe_state(beginID, endID, str, color);
279:     }
280:   }
281: #endif
282:   *event = e;
283:   return(0);
284: }

286: /*---------------------------------------------- Activation Functions -----------------------------------------------*/
287: /*@C
288:   EventPerfLogActivate - Indicates that a particular event should be logged.

290:   Not Collective

292:   Input Parameters:
293: + eventLog - The EventPerfLog
294: - event    - The event

296:    Usage:
297: .vb
298:       EventPerfLogDeactivate(log, VEC_SetValues);
299:         [code where you do not want to log VecSetValues()]
300:       EventPerfLogActivate(log, VEC_SetValues);
301:         [code where you do want to log VecSetValues()]
302: .ve 

304:   Note:
305:   The event may be either a pre-defined PETSc event (found in 
306:   include/petsclog.h) or an event number obtained with EventRegLogRegister().

308:   Level: advanced

310: .keywords: log, event, activate
311: .seealso: PetscLogEventMPEDeactivate(), PetscLogEventMPEActivate(), EventPerfLogDeactivate()
312: @*/
313: int EventPerfLogActivate(EventPerfLog eventLog, PetscEvent event) {
315:   eventLog->eventInfo[event].active = PETSC_TRUE;
316:   return(0);
317: }

319: /*@C
320:   EventPerfLogDeactivate - Indicates that a particular event should not be logged.

322:   Not Collective

324:   Input Parameters:
325: + eventLog - The EventPerfLog
326: - event    - The event

328:    Usage:
329: .vb
330:       EventPerfLogDeactivate(log, VEC_SetValues);
331:         [code where you do not want to log VecSetValues()]
332:       EventPerfLogActivate(log, VEC_SetValues);
333:         [code where you do want to log VecSetValues()]
334: .ve 

336:   Note:
337:   The event may be either a pre-defined PETSc event (found in 
338:   include/petsclog.h) or an event number obtained with EventRegLogRegister().

340:   Level: advanced

342: .keywords: log, event, activate
343: .seealso: PetscLogEventMPEDeactivate(), PetscLogEventMPEActivate(), EventPerfLogActivate()
344: @*/
345: int EventPerfLogDeactivate(EventPerfLog eventLog, PetscEvent event) {
347:   eventLog->eventInfo[event].active = PETSC_FALSE;
348:   return(0);
349: }

351: /*@C
352:   EventPerfLogActivateClass - Activates event logging for a PETSc object class.

354:   Not Collective

356:   Input Parameters:
357: + eventLog    - The EventPerfLog
358: . eventRegLog - The EventRegLog
359: - cookie      - The class id, for example MAT_COOKIE, SNES_COOKIE,

361:   Level: developer

363: .seealso: EventPerfLogDeactivateClass(), EventPerfLogActivate(), EventPerfLogDeactivate()
364: @*/
365: int EventPerfLogActivateClass(EventPerfLog eventLog, EventRegLog eventRegLog, int cookie) {
366:   int e;

369:   for(e = 0; e < eventLog->numEvents; e++) {
370:     int c = eventRegLog->eventInfo[e].cookie;

372:     if (c == cookie) eventLog->eventInfo[e].active = PETSC_TRUE;
373:   }
374:   return(0);
375: }

377: /*@C
378:   EventPerfLogDeactivateClass - Deactivates event logging for a PETSc object class.

380:   Not Collective

382:   Input Parameters:
383: + eventLog    - The EventPerfLog
384: . eventRegLog - The EventRegLog
385: - cookie - The class id, for example MAT_COOKIE, SNES_COOKIE,

387:   Level: developer

389: .seealso: EventPerfLogDeactivateClass(), EventPerfLogDeactivate(), EventPerfLogActivate()
390: @*/
391: int EventPerfLogDeactivateClass(EventPerfLog eventLog, EventRegLog eventRegLog, int cookie) {
392:   int e;

395:   for(e = 0; e < eventLog->numEvents; e++) {
396:     int c = eventRegLog->eventInfo[e].cookie;

398:     if (c == cookie) eventLog->eventInfo[e].active = PETSC_FALSE;
399:   }
400:   return(0);
401: }

403: /*------------------------------------------------ Query Functions --------------------------------------------------*/
404: /*@C
405:   EventPerfLogSetVisible - This function determines whether an event is printed during PetscLogPrintSummary()

407:   Not Collective

409:   Input Parameters:
410: + eventLog  - The EventPerfLog
411: . event     - The event to log
412: - isVisible - The visibility flag, PETSC_TRUE for printing, otherwise PETSC_FALSE (default is PETSC_TRUE)

414:   Database Options:
415: . -log_summary - Activates log summary

417:   Level: intermediate

419: .keywords: log, visible, event
420: .seealso: EventPerfLogGetVisible(), EventRegLogRegister(), StageLogGetEventLog()
421: @*/
422: int EventPerfLogSetVisible(EventPerfLog eventLog, PetscEvent event, PetscTruth isVisible) {
424:   eventLog->eventInfo[event].visible = isVisible;
425:   return(0);
426: }

428: /*@C
429:   EventPerfLogGetVisible - This function returns whether an event is printed during PetscLogPrintSummary()

431:   Not Collective

433:   Input Parameters:
434: + eventLog  - The EventPerfLog
435: - event     - The event id to log

437:   Output Parameter:
438: . isVisible - The visibility flag, PETSC_TRUE for printing, otherwise PETSC_FALSE (default is PETSC_TRUE)

440:   Database Options:
441: . -log_summary - Activates log summary

443:   Level: intermediate

445: .keywords: log, visible, event
446: .seealso: EventPerfLogSetVisible(), EventRegLogRegister(), StageLogGetEventLog()
447: @*/
448: int EventPerfLogGetVisible(EventPerfLog eventLog, PetscEvent event, PetscTruth *isVisible) {
451:   *isVisible = eventLog->eventInfo[event].visible;
452:   return(0);
453: }

455: /*------------------------------------------------ Action Functions -------------------------------------------------*/
456: int PetscLogEventBeginDefault(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) {
457:   StageLog     stageLog;
458:   EventPerfLog eventLog;
459:   int          stage;
460:   int          ierr;

463:   PetscLogGetStageLog(&stageLog);
464:   StageLogGetCurrent(stageLog, &stage);
465:   StageLogGetEventPerfLog(stageLog, stage, &eventLog);
466:   /* Check for double counting */
467:   eventLog->eventInfo[event].depth++;
468:   if (eventLog->eventInfo[event].depth > 1) return(0);
469:   /* Log performance info */
470:   eventLog->eventInfo[event].count++;
471:   PetscTimeSubtract(eventLog->eventInfo[event].time);
472:   eventLog->eventInfo[event].flops         -= _TotalFlops;
473:   eventLog->eventInfo[event].numMessages   -= irecv_ct  + isend_ct  + recv_ct  + send_ct;
474:   eventLog->eventInfo[event].messageLength -= irecv_len + isend_len + recv_len + send_len;
475:   eventLog->eventInfo[event].numReductions -= allreduce_ct;
476:   return(0);
477: }

479: int PetscLogEventEndDefault(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) {
480:   StageLog     stageLog;
481:   EventPerfLog eventLog;
482:   int          stage;
483:   int          ierr;

486:   PetscLogGetStageLog(&stageLog);
487:   StageLogGetCurrent(stageLog, &stage);
488:   StageLogGetEventPerfLog(stageLog, stage, &eventLog);
489:   /* Check for double counting */
490:   eventLog->eventInfo[event].depth--;
491:   if (eventLog->eventInfo[event].depth > 0) {
492:     return(0);
493:   } else if (eventLog->eventInfo[event].depth < 0) {
494:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
495:   }
496:   /* Log performance info */
497:   PetscTimeAdd(eventLog->eventInfo[event].time);
498:   eventLog->eventInfo[event].flops         += _TotalFlops;
499:   eventLog->eventInfo[event].numMessages   += irecv_ct  + isend_ct  + recv_ct  + send_ct;
500:   eventLog->eventInfo[event].messageLength += irecv_len + isend_len + recv_len + send_len;
501:   eventLog->eventInfo[event].numReductions += allreduce_ct;
502:   return(0);
503: }

505: int PetscLogEventBeginComplete(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) {
506:   StageLog       stageLog;
507:   EventRegLog    eventRegLog;
508:   EventPerfLog   eventPerfLog;
509:   Action        *tmpAction;
510:   PetscLogDouble start, end;
511:   PetscLogDouble curTime;
512:   int            stage;
513:   int            ierr;

516:   /* Dynamically enlarge logging structures */
517:   if (numActions >= maxActions) {
518:     PetscTime(start);
519:     PetscMalloc(maxActions*2 * sizeof(Action), &tmpAction);
520:     PetscMemcpy(tmpAction, actions, maxActions * sizeof(Action));
521:     PetscFree(actions);
522:     actions     = tmpAction;
523:     maxActions *= 2;
524:     PetscTime(end);
525:     BaseTime += (end - start);
526:   }
527:   /* Record the event */
528:   PetscLogGetStageLog(&stageLog);
529:   StageLogGetCurrent(stageLog, &stage);
530:   StageLogGetEventRegLog(stageLog, &eventRegLog);
531:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
532:   PetscTime(curTime);
533:   if (logActions == PETSC_TRUE) {
534:     actions[numActions].time   = curTime - BaseTime;
535:     actions[numActions].action = ACTIONBEGIN;
536:     actions[numActions].event  = event;
537:     actions[numActions].cookie = eventRegLog->eventInfo[event].cookie;
538:     if (o1) actions[numActions].id1 = o1->id; else actions[numActions].id1 = -1;
539:     if (o2) actions[numActions].id2 = o2->id; else actions[numActions].id2 = -1;
540:     if (o3) actions[numActions].id3 = o3->id; else actions[numActions].id3 = -1;
541:     actions[numActions].flops    = _TotalFlops;
542:     PetscTrSpace(&actions[numActions].mem, PETSC_NULL, &actions[numActions].maxmem);
543:     numActions++;
544:   }
545:   /* Check for double counting */
546:   eventPerfLog->eventInfo[event].depth++;
547:   if (eventPerfLog->eventInfo[event].depth > 1) return(0);
548:   /* Log the performance info */
549:   eventPerfLog->eventInfo[event].count++;
550:   eventPerfLog->eventInfo[event].time          -= curTime;
551:   eventPerfLog->eventInfo[event].flops         -= _TotalFlops;
552:   eventPerfLog->eventInfo[event].numMessages   -= irecv_ct  + isend_ct  + recv_ct  + send_ct;
553:   eventPerfLog->eventInfo[event].messageLength -= irecv_len + isend_len + recv_len + send_len;
554:   eventPerfLog->eventInfo[event].numReductions -= allreduce_ct;
555:   return(0);
556: }

558: int PetscLogEventEndComplete(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) {
559:   StageLog       stageLog;
560:   EventRegLog    eventRegLog;
561:   EventPerfLog   eventPerfLog;
562:   Action        *tmpAction;
563:   PetscLogDouble start, end;
564:   PetscLogDouble curTime;
565:   int            stage;
566:   int            ierr;

569:   /* Dynamically enlarge logging structures */
570:   if (numActions >= maxActions) {
571:     PetscTime(start);
572:     PetscMalloc(maxActions*2 * sizeof(Action), &tmpAction);
573:     PetscMemcpy(tmpAction, actions, maxActions * sizeof(Action));
574:     PetscFree(actions);
575:     actions     = tmpAction;
576:     maxActions *= 2;
577:     PetscTime(end);
578:     BaseTime += (end - start);
579:   }
580:   /* Record the event */
581:   PetscLogGetStageLog(&stageLog);
582:   StageLogGetCurrent(stageLog, &stage);
583:   StageLogGetEventRegLog(stageLog, &eventRegLog);
584:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
585:   PetscTime(curTime);
586:   if (logActions == PETSC_TRUE) {
587:     actions[numActions].time   = curTime - BaseTime;
588:     actions[numActions].action = ACTIONEND;
589:     actions[numActions].event  = event;
590:     actions[numActions].cookie = eventRegLog->eventInfo[event].cookie;
591:     if (o1) actions[numActions].id1 = o1->id; else actions[numActions].id1 = -1;
592:     if (o2) actions[numActions].id2 = o2->id; else actions[numActions].id2 = -1;
593:     if (o3) actions[numActions].id3 = o3->id; else actions[numActions].id3 = -1;
594:     actions[numActions].flops    = _TotalFlops;
595:     PetscTrSpace(&actions[numActions].mem, PETSC_NULL, &actions[numActions].maxmem);
596:     numActions++;
597:   }
598:   /* Check for double counting */
599:   eventPerfLog->eventInfo[event].depth--;
600:   if (eventPerfLog->eventInfo[event].depth > 0) {
601:     return(0);
602:   } else if (eventPerfLog->eventInfo[event].depth < 0) {
603:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
604:   }
605:   /* Log the performance info */
606:   eventPerfLog->eventInfo[event].count++;
607:   eventPerfLog->eventInfo[event].time          += curTime;
608:   eventPerfLog->eventInfo[event].flops         += _TotalFlops;
609:   eventPerfLog->eventInfo[event].numMessages   += irecv_ct  + isend_ct  + recv_ct  + send_ct;
610:   eventPerfLog->eventInfo[event].messageLength += irecv_len + isend_len + recv_len + send_len;
611:   eventPerfLog->eventInfo[event].numReductions += allreduce_ct;
612:   return(0);
613: }

615: int PetscLogEventBeginTrace(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4) {
616:   StageLog       stageLog;
617:   EventRegLog    eventRegLog;
618:   EventPerfLog   eventPerfLog;
619:   PetscLogDouble cur_time;
620:   int            rank, stage;
621:   int            ierr;

624:   if (tracetime == 0.0) {PetscTime(tracetime);}

626:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
627:   PetscLogGetStageLog(&stageLog);
628:   StageLogGetCurrent(stageLog, &stage);
629:   StageLogGetEventRegLog(stageLog, &eventRegLog);
630:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
631:   /* Check for double counting */
632:   eventPerfLog->eventInfo[event].depth++;
633:   if (eventPerfLog->eventInfo[event].depth > 1) return(0);
634:   /* Log performance info */
635:   PetscStrncpy(tracespace, traceblanks, 2*tracelevel);
636:   tracespace[2*tracelevel] = 0;
637:   PetscTime(cur_time);
638:   fprintf(tracefile, "%s[%d] %g Event begin: %sn", tracespace, rank, cur_time-tracetime, eventRegLog->eventInfo[event].name);
639:   fflush(tracefile);
640:   tracelevel++;

642:   return(0);
643: }

645: int PetscLogEventEndTrace(PetscEvent event,int t,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4) {
646:   StageLog       stageLog;
647:   EventRegLog    eventRegLog;
648:   EventPerfLog   eventPerfLog;
649:   PetscLogDouble cur_time;
650:   int            rank, stage;
651:   int            ierr;

654:   tracelevel--;
655:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
656:   PetscLogGetStageLog(&stageLog);
657:   StageLogGetCurrent(stageLog, &stage);
658:   StageLogGetEventRegLog(stageLog, &eventRegLog);
659:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
660:   /* Check for double counting */
661:   eventPerfLog->eventInfo[event].depth--;
662:   if (eventPerfLog->eventInfo[event].depth > 0) {
663:     return(0);
664:   } else if (eventPerfLog->eventInfo[event].depth < 0) {
665:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
666:   }
667:   /* Log performance info */
668:   PetscStrncpy(tracespace, traceblanks, 2*tracelevel);
669:   tracespace[2*tracelevel] = 0;
670:   PetscTime(cur_time);
671:   fprintf(tracefile, "%s[%d] %g Event end: %sn", tracespace, rank, cur_time-tracetime, eventRegLog->eventInfo[event].name);
672:   fflush(tracefile);
673:   return(0);
674: }