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: }