Actual source code: eventLog.c

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

  6: /* Variables for the tracing logger */

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

 19:   Not collective

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

 24:   Level: beginner

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

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

 45: /*@C
 46:   EventRegLogDestroy - This destroys a EventRegLog object.

 48:   Not collective

 50:   Input Paramter:
 51: . eventLog - The EventRegLog

 53:   Level: beginner

 55: .keywords: log, event, destroy
 56: .seealso: EventRegLogCreate()
 57: @*/
 58: PetscErrorCode EventRegLogDestroy(EventRegLog eventLog)
 59: {
 60:   int e;

 64:   for(e = 0; e < eventLog->numEvents; e++) {
 65:     PetscFree(eventLog->eventInfo[e].name);
 66:   }
 67:   PetscFree(eventLog->eventInfo);
 68:   PetscFree(eventLog);
 69:   return(0);
 70: }

 74: /*@C
 75:   EventPerfLogCreate - This creates a EventPerfLog object.

 77:   Not collective

 79:   Input Parameter:
 80: . eventLog - The EventPerfLog

 82:   Level: beginner

 84: .keywords: log, event, create
 85: .seealso: EventPerfLogDestroy(), StageLogCreate()
 86: @*/
 87: PetscErrorCode EventPerfLogCreate(EventPerfLog *eventLog)
 88: {
 89:   EventPerfLog l;

 93:   PetscNew(struct _EventPerfLog, &l);
 94:   l->numEvents   = 0;
 95:   l->maxEvents   = 100;
 96:   PetscMalloc(l->maxEvents * sizeof(EventPerfInfo), &l->eventInfo);
 97:   *eventLog = l;
 98:   return(0);
 99: }

103: /*@C
104:   EventPerfLogDestroy - This destroys a EventPerfLog object.

106:   Not collective

108:   Input Paramter:
109: . eventLog - The EventPerfLog

111:   Level: beginner

113: .keywords: log, event, destroy
114: .seealso: EventPerfLogCreate()
115: @*/
116: PetscErrorCode EventPerfLogDestroy(EventPerfLog eventLog)
117: {

121:   PetscFree(eventLog->eventInfo);
122:   PetscFree(eventLog);
123:   return(0);
124: }

126: /*------------------------------------------------ General Functions -------------------------------------------------*/
129: /*@C
130:   EventPerfInfoClear - This clears a EventPerfInfo object.

132:   Not collective

134:   Input Paramter:
135: . eventInfo - The EventPerfInfo

137:   Level: beginner

139: .keywords: log, event, destroy
140: .seealso: EventPerfLogCreate()
141: @*/
142: PetscErrorCode EventPerfInfoClear(EventPerfInfo *eventInfo)
143: {
145:   eventInfo->id            = -1;
146:   eventInfo->active        = PETSC_TRUE;
147:   eventInfo->visible       = PETSC_TRUE;
148:   eventInfo->depth         = 0;
149:   eventInfo->count         = 0;
150:   eventInfo->flops         = 0.0;
151:   eventInfo->time          = 0.0;
152:   eventInfo->numMessages   = 0.0;
153:   eventInfo->messageLength = 0.0;
154:   eventInfo->numReductions = 0.0;
155:   return(0);
156: }

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

163:   Not collective

165:   Input Paramter:
166: . eventInfo - The input EventPerfInfo

168:   Output Paramter:
169: . outInfo   - The output EventPerfInfo

171:   Level: beginner

173: .keywords: log, event, copy
174: .seealso: EventPerfInfoClear()
175: @*/
176: PetscErrorCode EventPerfInfoCopy(EventPerfInfo *eventInfo, EventPerfInfo *outInfo)
177: {
179:   outInfo->id      = eventInfo->id;
180:   outInfo->active  = eventInfo->active;
181:   outInfo->visible = eventInfo->visible;
182:   return(0);
183: }

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

190:   Not collective

192:   Input Paramters:
193: + eventLog - The EventPerfLog
194: - size     - The size

196:   Level: intermediate

198: .keywords: log, event, size, ensure
199: .seealso: EventPerfLogCreate()
200: @*/
201: PetscErrorCode EventPerfLogEnsureSize(EventPerfLog eventLog, int size)
202: {
203:   EventPerfInfo *eventInfo;

207:   while(size > eventLog->maxEvents) {
208:     PetscMalloc(eventLog->maxEvents*2 * sizeof(EventPerfInfo), &eventInfo);
209:     PetscMemcpy(eventInfo, eventLog->eventInfo, eventLog->maxEvents * sizeof(EventPerfInfo));
210:     PetscFree(eventLog->eventInfo);
211:     eventLog->eventInfo  = eventInfo;
212:     eventLog->maxEvents *= 2;
213:   }
214:   while(eventLog->numEvents < size) {
215:     EventPerfInfoClear(&eventLog->eventInfo[eventLog->numEvents++]);
216:   }
217:   return(0);
218: }

220: /*--------------------------------------------- Registration Functions ----------------------------------------------*/
223: /*@C
224:   EventRegLogRegister - Registers an event for logging operations in an application code.

226:   Not Collective

228:   Input Parameters:
229: + eventLog - The EventLog
230: . ename    - The name associated with the event
231: - cookie   - The cookie associated to the class for this event

233:   Output Parameter:
234: . event    - The event

236:   Example of Usage:
237: .vb
238:       int USER_EVENT;
239:       int user_event_flops;
240:       PetscLogEventRegister(&USER_EVENT,"User event name");
241:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
242:          [code segment to monitor]
243:          PetscLogFlops(user_event_flops);
244:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
245: .ve

247:   Notes: 
248:   PETSc automatically logs library events if the code has been
249:   compiled with -DPETSC_USE_LOG (which is the default) and -log,
250:   -log_summary, or -log_all are specified.  PetscLogEventRegister() is
251:   intended for logging user events to supplement this PETSc
252:   information. 

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

261:   Level: intermediate

263: .keywords: log, event, register
264: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventMPEActivate(), PetscLogEventMPEDeactivate(),
265:           EventLogActivate(), EventLogDeactivate()
266: @*/
267: PetscErrorCode EventRegLogRegister(EventRegLog eventLog, const char ename[], PetscCookie cookie, PetscEvent *event)
268: {
269:   EventRegInfo *eventInfo;
270:   char         *str;
271:   int           e;

277:   /* Should check cookie I think */
278:   e = eventLog->numEvents++;
279:   if (eventLog->numEvents > eventLog->maxEvents) {
280:     PetscMalloc(eventLog->maxEvents*2 * sizeof(EventRegInfo), &eventInfo);
281:     PetscMemcpy(eventInfo, eventLog->eventInfo, eventLog->maxEvents * sizeof(EventRegInfo));
282:     PetscFree(eventLog->eventInfo);
283:     eventLog->eventInfo  = eventInfo;
284:     eventLog->maxEvents *= 2;
285:   }
286:   PetscStrallocpy(ename, &str);
287:   eventLog->eventInfo[e].name   = str;
288:   eventLog->eventInfo[e].cookie = cookie;
289: #if defined(PETSC_HAVE_MPE)
290:   if (UseMPE) {
291:     const char  *color;
292:     PetscMPIInt rank;
293:     int         beginID, endID;

295:     beginID = MPE_Log_get_event_number();
296:     endID   = MPE_Log_get_event_number();
297:     eventLog->eventInfo[e].mpe_id_begin = beginID;
298:     eventLog->eventInfo[e].mpe_id_end   = endID;
299:     MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
300:     if (!rank) {
301:       PetscLogGetRGBColor(&color);
302:       MPE_Describe_state(beginID, endID, str, (char*)color);
303:     }
304:   }
305: #endif
306:   *event = e;
307:   return(0);
308: }

310: /*---------------------------------------------- Activation Functions -----------------------------------------------*/
313: /*@C
314:   EventPerfLogActivate - Indicates that a particular event should be logged.

316:   Not Collective

318:   Input Parameters:
319: + eventLog - The EventPerfLog
320: - event    - The event

322:    Usage:
323: .vb
324:       EventPerfLogDeactivate(log, VEC_SetValues);
325:         [code where you do not want to log VecSetValues()]
326:       EventPerfLogActivate(log, VEC_SetValues);
327:         [code where you do want to log VecSetValues()]
328: .ve 

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

334:   Level: advanced

336: .keywords: log, event, activate
337: .seealso: PetscLogEventMPEDeactivate(), PetscLogEventMPEActivate(), EventPerfLogDeactivate()
338: @*/
339: PetscErrorCode EventPerfLogActivate(EventPerfLog eventLog, PetscEvent event)
340: {
342:   eventLog->eventInfo[event].active = PETSC_TRUE;
343:   return(0);
344: }

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

351:   Not Collective

353:   Input Parameters:
354: + eventLog - The EventPerfLog
355: - event    - The event

357:    Usage:
358: .vb
359:       EventPerfLogDeactivate(log, VEC_SetValues);
360:         [code where you do not want to log VecSetValues()]
361:       EventPerfLogActivate(log, VEC_SetValues);
362:         [code where you do want to log VecSetValues()]
363: .ve 

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

369:   Level: advanced

371: .keywords: log, event, activate
372: .seealso: PetscLogEventMPEDeactivate(), PetscLogEventMPEActivate(), EventPerfLogActivate()
373: @*/
374: PetscErrorCode EventPerfLogDeactivate(EventPerfLog eventLog, PetscEvent event)
375: {
377:   eventLog->eventInfo[event].active = PETSC_FALSE;
378:   return(0);
379: }

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

386:   Not Collective

388:   Input Parameters:
389: + eventLog    - The EventPerfLog
390: . eventRegLog - The EventRegLog
391: - cookie      - The class id, for example MAT_COOKIE, SNES_COOKIE,

393:   Level: developer

395: .seealso: EventPerfLogDeactivateClass(), EventPerfLogActivate(), EventPerfLogDeactivate()
396: @*/
397: PetscErrorCode EventPerfLogActivateClass(EventPerfLog eventLog, EventRegLog eventRegLog, PetscCookie cookie)
398: {
399:   int e;

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

405:     if (c == cookie) eventLog->eventInfo[e].active = PETSC_TRUE;
406:   }
407:   return(0);
408: }

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

415:   Not Collective

417:   Input Parameters:
418: + eventLog    - The EventPerfLog
419: . eventRegLog - The EventRegLog
420: - cookie - The class id, for example MAT_COOKIE, SNES_COOKIE,

422:   Level: developer

424: .seealso: EventPerfLogDeactivateClass(), EventPerfLogDeactivate(), EventPerfLogActivate()
425: @*/
426: PetscErrorCode EventPerfLogDeactivateClass(EventPerfLog eventLog, EventRegLog eventRegLog, PetscCookie cookie)
427: {
428:   int e;

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

434:     if (c == cookie) eventLog->eventInfo[e].active = PETSC_FALSE;
435:   }
436:   return(0);
437: }

439: /*------------------------------------------------ Query Functions --------------------------------------------------*/
442: /*@C
443:   EventPerfLogSetVisible - This function determines whether an event is printed during PetscLogPrintSummary()

445:   Not Collective

447:   Input Parameters:
448: + eventLog  - The EventPerfLog
449: . event     - The event to log
450: - isVisible - The visibility flag, PETSC_TRUE for printing, otherwise PETSC_FALSE (default is PETSC_TRUE)

452:   Database Options:
453: . -log_summary - Activates log summary

455:   Level: intermediate

457: .keywords: log, visible, event
458: .seealso: EventPerfLogGetVisible(), EventRegLogRegister(), StageLogGetEventLog()
459: @*/
460: PetscErrorCode EventPerfLogSetVisible(EventPerfLog eventLog, PetscEvent event, PetscTruth isVisible)
461: {
463:   eventLog->eventInfo[event].visible = isVisible;
464:   return(0);
465: }

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

472:   Not Collective

474:   Input Parameters:
475: + eventLog  - The EventPerfLog
476: - event     - The event id to log

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

481:   Database Options:
482: . -log_summary - Activates log summary

484:   Level: intermediate

486: .keywords: log, visible, event
487: .seealso: EventPerfLogSetVisible(), EventRegLogRegister(), StageLogGetEventLog()
488: @*/
489: PetscErrorCode EventPerfLogGetVisible(EventPerfLog eventLog, PetscEvent event, PetscTruth *isVisible)
490: {
493:   *isVisible = eventLog->eventInfo[event].visible;
494:   return(0);
495: }

497: /*------------------------------------------------ Action Functions -------------------------------------------------*/
500: PetscErrorCode PetscLogEventBeginDefault(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
501: {
502:   StageLog     stageLog;
503:   EventPerfLog eventLog;
504:   int          stage;

508:   PetscLogGetStageLog(&stageLog);
509:   StageLogGetCurrent(stageLog, &stage);
510:   StageLogGetEventPerfLog(stageLog, stage, &eventLog);
511:   /* Check for double counting */
512:   eventLog->eventInfo[event].depth++;
513:   if (eventLog->eventInfo[event].depth > 1) return(0);
514:   /* Log performance info */
515:   eventLog->eventInfo[event].count++;
516:   PetscTimeSubtract(eventLog->eventInfo[event].time);
517:   eventLog->eventInfo[event].flops         -= _TotalFlops;
518:   eventLog->eventInfo[event].numMessages   -= irecv_ct  + isend_ct  + recv_ct  + send_ct;
519:   eventLog->eventInfo[event].messageLength -= irecv_len + isend_len + recv_len + send_len;
520:   eventLog->eventInfo[event].numReductions -= allreduce_ct;
521:   return(0);
522: }

526: PetscErrorCode PetscLogEventEndDefault(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
527: {
528:   StageLog     stageLog;
529:   EventPerfLog eventLog;
530:   int          stage;

534:   PetscLogGetStageLog(&stageLog);
535:   StageLogGetCurrent(stageLog, &stage);
536:   StageLogGetEventPerfLog(stageLog, stage, &eventLog);
537:   /* Check for double counting */
538:   eventLog->eventInfo[event].depth--;
539:   if (eventLog->eventInfo[event].depth > 0) {
540:     return(0);
541:   } else if (eventLog->eventInfo[event].depth < 0) {
542:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
543:   }
544:   /* Log performance info */
545:   PetscTimeAdd(eventLog->eventInfo[event].time);
546:   eventLog->eventInfo[event].flops         += _TotalFlops;
547:   eventLog->eventInfo[event].numMessages   += irecv_ct  + isend_ct  + recv_ct  + send_ct;
548:   eventLog->eventInfo[event].messageLength += irecv_len + isend_len + recv_len + send_len;
549:   eventLog->eventInfo[event].numReductions += allreduce_ct;
550:   return(0);
551: }

555: PetscErrorCode PetscLogEventBeginComplete(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
556: {
557:   StageLog       stageLog;
558:   EventRegLog    eventRegLog;
559:   EventPerfLog   eventPerfLog;
560:   Action        *tmpAction;
561:   PetscLogDouble start, end;
562:   PetscLogDouble curTime;
563:   int            stage;

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

611: PetscErrorCode PetscLogEventEndComplete(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
612: {
613:   StageLog       stageLog;
614:   EventRegLog    eventRegLog;
615:   EventPerfLog   eventPerfLog;
616:   Action        *tmpAction;
617:   PetscLogDouble start, end;
618:   PetscLogDouble curTime;
619:   int            stage;

623:   /* Dynamically enlarge logging structures */
624:   if (numActions >= maxActions) {
625:     PetscTime(start);
626:     PetscMalloc(maxActions*2 * sizeof(Action), &tmpAction);
627:     PetscMemcpy(tmpAction, actions, maxActions * sizeof(Action));
628:     PetscFree(actions);
629:     actions     = tmpAction;
630:     maxActions *= 2;
631:     PetscTime(end);
632:     BaseTime += (end - start);
633:   }
634:   /* Record the event */
635:   PetscLogGetStageLog(&stageLog);
636:   StageLogGetCurrent(stageLog, &stage);
637:   StageLogGetEventRegLog(stageLog, &eventRegLog);
638:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
639:   PetscTime(curTime);
640:   if (logActions == PETSC_TRUE) {
641:     actions[numActions].time   = curTime - BaseTime;
642:     actions[numActions].action = ACTIONEND;
643:     actions[numActions].event  = event;
644:     actions[numActions].cookie = eventRegLog->eventInfo[event].cookie;
645:     if (o1) actions[numActions].id1 = o1->id; else actions[numActions].id1 = -1;
646:     if (o2) actions[numActions].id2 = o2->id; else actions[numActions].id2 = -1;
647:     if (o3) actions[numActions].id3 = o3->id; else actions[numActions].id3 = -1;
648:     actions[numActions].flops    = _TotalFlops;
649:     PetscTrSpace(&actions[numActions].mem, PETSC_NULL, &actions[numActions].maxmem);
650:     numActions++;
651:   }
652:   /* Check for double counting */
653:   eventPerfLog->eventInfo[event].depth--;
654:   if (eventPerfLog->eventInfo[event].depth > 0) {
655:     return(0);
656:   } else if (eventPerfLog->eventInfo[event].depth < 0) {
657:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
658:   }
659:   /* Log the performance info */
660:   eventPerfLog->eventInfo[event].count++;
661:   eventPerfLog->eventInfo[event].time          += curTime;
662:   eventPerfLog->eventInfo[event].flops         += _TotalFlops;
663:   eventPerfLog->eventInfo[event].numMessages   += irecv_ct  + isend_ct  + recv_ct  + send_ct;
664:   eventPerfLog->eventInfo[event].messageLength += irecv_len + isend_len + recv_len + send_len;
665:   eventPerfLog->eventInfo[event].numReductions += allreduce_ct;
666:   return(0);
667: }

671: PetscErrorCode PetscLogEventBeginTrace(PetscEvent event, int t, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
672: {
673:   StageLog       stageLog;
674:   EventRegLog    eventRegLog;
675:   EventPerfLog   eventPerfLog;
676:   PetscLogDouble cur_time;
677:   PetscMPIInt    rank;
678:   int            stage;

682:   if (!tracetime) {PetscTime(tracetime);}

684:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
685:   PetscLogGetStageLog(&stageLog);
686:   StageLogGetCurrent(stageLog, &stage);
687:   StageLogGetEventRegLog(stageLog, &eventRegLog);
688:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
689:   /* Check for double counting */
690:   eventPerfLog->eventInfo[event].depth++;
691:   tracelevel++;
692:   if (eventPerfLog->eventInfo[event].depth > 1) return(0);
693:   /* Log performance info */
694:   PetscStrncpy(tracespace, traceblanks, 2*tracelevel);
695:   tracespace[2*tracelevel] = 0;
696:   PetscTime(cur_time);
697:   PetscFPrintf(PETSC_COMM_SELF,tracefile, "%s[%d] %g Event begin: %s\n", tracespace, rank, cur_time-tracetime, eventRegLog->eventInfo[event].name);
698:   fflush(tracefile);

700:   return(0);
701: }

705: PetscErrorCode PetscLogEventEndTrace(PetscEvent event,int t,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4)
706: {
707:   StageLog       stageLog;
708:   EventRegLog    eventRegLog;
709:   EventPerfLog   eventPerfLog;
710:   PetscLogDouble cur_time;
711:   int            stage;
712:   PetscMPIInt    rank;

716:   tracelevel--;
717:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
718:   PetscLogGetStageLog(&stageLog);
719:   StageLogGetCurrent(stageLog, &stage);
720:   StageLogGetEventRegLog(stageLog, &eventRegLog);
721:   StageLogGetEventPerfLog(stageLog, stage, &eventPerfLog);
722:   /* Check for double counting */
723:   eventPerfLog->eventInfo[event].depth--;
724:   if (eventPerfLog->eventInfo[event].depth > 0) {
725:     return(0);
726:   } else if (eventPerfLog->eventInfo[event].depth < 0 || tracelevel < 0) {
727:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Logging event had unbalanced begin/end pairs");
728:   }
729:   /* Log performance info */
730:   PetscStrncpy(tracespace, traceblanks, 2*tracelevel);
731:   tracespace[2*tracelevel] = 0;
732:   PetscTime(cur_time);
733:   PetscFPrintf(PETSC_COMM_SELF,tracefile, "%s[%d] %g Event end: %s\n", tracespace, rank, cur_time-tracetime, eventRegLog->eventInfo[event].name);
734:   fflush(tracefile);
735:   return(0);
736: }