Actual source code: classlog.c


  2: /*
  3:      This defines part of the private API for logging performance information. It is intended to be used only by the
  4:    PETSc PetscLog...() interface and not elsewhere, nor by users. Hence the prototypes for these functions are NOT
  5:    in the public PETSc include files.

  7: */
  8: #include <petsc/private/logimpl.h>

 10: /*@C
 11:   PetscClassRegLogCreate - This creates a `PetscClassRegLog` object.

 13:   Not Collective

 15:   Input Parameter:
 16: . classLog - The `PetscClassRegLog`

 18:   Level: developer

 20:   Note:
 21:   This is a low level routine used by the logging functions in PETSc

 23: .seealso: `PetscClassRegLogDestroy()`, `PetscStageLogCreate()`
 24: @*/
 25: PetscErrorCode PetscClassRegLogCreate(PetscClassRegLog *classLog)
 26: {
 27:   PetscClassRegLog l;

 29:   PetscFunctionBegin;
 30:   PetscCall(PetscNew(&l));

 32:   l->numClasses = 0;
 33:   l->maxClasses = 100;

 35:   PetscCall(PetscMalloc1(l->maxClasses, &l->classInfo));

 37:   *classLog = l;
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }

 41: /*@C
 42:   PetscClassRegLogDestroy - This destroys a `PetscClassRegLog` object.

 44:   Not Collective

 46:   Input Parameter:
 47: . classLog - The `PetscClassRegLog`

 49:   Level: developer

 51:   Note:
 52:   This is a low level routine used by the logging functions in PETSc

 54: .seealso: `PetscClassRegLogCreate()`
 55: @*/
 56: PetscErrorCode PetscClassRegLogDestroy(PetscClassRegLog classLog)
 57: {
 58:   int c;

 60:   PetscFunctionBegin;
 61:   for (c = 0; c < classLog->numClasses; c++) PetscCall(PetscClassRegInfoDestroy(&classLog->classInfo[c]));
 62:   PetscCall(PetscFree(classLog->classInfo));
 63:   PetscCall(PetscFree(classLog));
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

 67: /*@C
 68:   PetscClassRegInfoDestroy - This destroys a `PetscClassRegInfo` object.

 70:   Not Collective

 72:   Input Parameter:
 73: . c - The PetscClassRegInfo

 75:   Level: developer

 77:   Note:
 78:   This is a low level routine used by the logging functions in PETSc

 80: .seealso: `PetscStageLogDestroy()`, `EventLogDestroy()`
 81: @*/
 82: PetscErrorCode PetscClassRegInfoDestroy(PetscClassRegInfo *c)
 83: {
 84:   PetscFunctionBegin;
 85:   PetscCall(PetscFree(c->name));
 86:   PetscFunctionReturn(PETSC_SUCCESS);
 87: }

 89: /*@C
 90:   PetscClassPerfLogCreate - This creates a `PetscClassPerfLog` object.

 92:   Not Collective

 94:   Input Parameter:
 95: . classLog - The `PetscClassPerfLog`

 97:   Level: developer

 99:   Note:
100:   This is a low level routine used by the logging functions in PETSc

102: .seealso: `PetscClassPerfLogDestroy()`, `PetscStageLogCreate()`
103: @*/
104: PetscErrorCode PetscClassPerfLogCreate(PetscClassPerfLog *classLog)
105: {
106:   PetscClassPerfLog l;

108:   PetscFunctionBegin;
109:   PetscCall(PetscNew(&l));

111:   l->numClasses = 0;
112:   l->maxClasses = 100;

114:   PetscCall(PetscMalloc1(l->maxClasses, &l->classInfo));

116:   *classLog = l;
117:   PetscFunctionReturn(PETSC_SUCCESS);
118: }

120: /*@C
121:   PetscClassPerfLogDestroy - This destroys a `PetscClassPerfLog` object.

123:   Not Collective

125:   Input Parameter:
126: . classLog - The `PetscClassPerfLog`

128:   Level: developer

130:   Note:
131:   This is a low level routine used by the logging functions in PETSc

133: .seealso: `PetscClassPerfLogCreate()`
134: @*/
135: PetscErrorCode PetscClassPerfLogDestroy(PetscClassPerfLog classLog)
136: {
137:   PetscFunctionBegin;
138:   PetscCall(PetscFree(classLog->classInfo));
139:   PetscCall(PetscFree(classLog));
140:   PetscFunctionReturn(PETSC_SUCCESS);
141: }

143: /*------------------------------------------------ General Functions -------------------------------------------------*/
144: /*@C
145:   PetscClassPerfInfoClear - This clears a `PetscClassPerfInfo` object.

147:   Not Collective

149:   Input Parameter:
150: . classInfo - The `PetscClassPerfInfo`

152:   Level: developer

154:   Note:
155:   This is a low level routine used by the logging functions in PETSc

157: .seealso: `PetscClassPerfLogCreate()`
158: @*/
159: PetscErrorCode PetscClassPerfInfoClear(PetscClassPerfInfo *classInfo)
160: {
161:   PetscFunctionBegin;
162:   classInfo->id           = -1;
163:   classInfo->creations    = 0;
164:   classInfo->destructions = 0;
165:   classInfo->mem          = 0.0;
166:   classInfo->descMem      = 0.0;
167:   PetscFunctionReturn(PETSC_SUCCESS);
168: }

170: /*@C
171:   PetscClassPerfLogEnsureSize - This ensures that a `PetscClassPerfLog` is at least of a certain size.

173:   Not Collective

175:   Input Parameters:
176: + classLog - The `PetscClassPerfLog`
177: - size     - The size

179:   Level: developer

181:   Note:
182:   This is a low level routine used by the logging functions in PETSc

184: .seealso: `PetscClassPerfLogCreate()`
185: @*/
186: PetscErrorCode PetscClassPerfLogEnsureSize(PetscClassPerfLog classLog, int size)
187: {
188:   PetscClassPerfInfo *classInfo;

190:   PetscFunctionBegin;
191:   while (size > classLog->maxClasses) {
192:     PetscCall(PetscMalloc1(classLog->maxClasses * 2, &classInfo));
193:     PetscCall(PetscArraycpy(classInfo, classLog->classInfo, classLog->maxClasses));
194:     PetscCall(PetscFree(classLog->classInfo));

196:     classLog->classInfo = classInfo;
197:     classLog->maxClasses *= 2;
198:   }
199:   while (classLog->numClasses < size) PetscCall(PetscClassPerfInfoClear(&classLog->classInfo[classLog->numClasses++]));
200:   PetscFunctionReturn(PETSC_SUCCESS);
201: }

203: /*--------------------------------------------- Registration Functions ----------------------------------------------*/
204: /*@C
205:   PetscClassRegLogRegister - Registers a class for logging operations in an application code.

207:   Not Collective

209:   Input Parameters:
210: + classLog - The `PetscClassRegLog`
211: - cname    - The name associated with the class

213:   Output Parameter:
214: .  classid   - The classid

216:   Level: developer

218:   Note:
219:   This is a low level routine used by the logging functions in PETSc

221: .seealso: `PetscClassIdRegister()`
222: @*/
223: PetscErrorCode PetscClassRegLogRegister(PetscClassRegLog classLog, const char cname[], PetscClassId classid)
224: {
225:   PetscClassRegInfo *classInfo;
226:   int                c;

228:   PetscFunctionBegin;
230:   c = classLog->numClasses++;
231:   if (classLog->numClasses > classLog->maxClasses) {
232:     PetscCall(PetscMalloc1(classLog->maxClasses * 2, &classInfo));
233:     PetscCall(PetscArraycpy(classInfo, classLog->classInfo, classLog->maxClasses));
234:     PetscCall(PetscFree(classLog->classInfo));

236:     classLog->classInfo = classInfo;
237:     classLog->maxClasses *= 2;
238:   }
239:   PetscCall(PetscStrallocpy(cname, &(classLog->classInfo[c].name)));
240:   classLog->classInfo[c].classid = classid;
241:   PetscFunctionReturn(PETSC_SUCCESS);
242: }

244: /*------------------------------------------------ Query Functions --------------------------------------------------*/
245: /*@C
246:   PetscClassRegLogGetClass - This function returns the class corresponding to a given classid.

248:   Not Collective

250:   Input Parameters:
251: + classLog - The `PetscClassRegLog`
252: - classid  - The cookie

254:   Output Parameter:
255: . oclass   - The class id

257:   Level: developer

259:   Note:
260:   This is a low level routine used by the logging functions in PETSc

262: .seealso: `PetscClassIdRegister()`, `PetscLogObjCreateDefault()`, `PetscLogObjDestroyDefault()`
263: @*/
264: PetscErrorCode PetscClassRegLogGetClass(PetscClassRegLog classLog, PetscClassId classid, int *oclass)
265: {
266:   int c;

268:   PetscFunctionBegin;
270:   for (c = 0; c < classLog->numClasses; c++) {
271:     /* Could do bisection here */
272:     if (classLog->classInfo[c].classid == classid) break;
273:   }
274:   PetscCheck(c < classLog->numClasses, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid object classid %d\nThis could happen if you compile with PETSC_HAVE_DYNAMIC_LIBRARIES, but link with static libraries.", classid);
275:   *oclass = c;
276:   PetscFunctionReturn(PETSC_SUCCESS);
277: }

279: /*----------------------------------------------- Logging Functions -------------------------------------------------*/
280: /* Default object create logger */
281: PetscErrorCode PetscLogObjCreateDefault(PetscObject obj)
282: {
283:   PetscStageLog     stageLog;
284:   PetscClassRegLog  classRegLog;
285:   PetscClassPerfLog classPerfLog;
286:   Action           *tmpAction;
287:   Object           *tmpObjects;
288:   PetscLogDouble    start, end;
289:   int               oclass = 0;
290:   int               stage;

292:   PetscFunctionBegin;
293:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
294:   /* Record stage info */
295:   PetscCall(PetscLogGetStageLog(&stageLog));
296:   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
297:   PetscCall(PetscStageLogGetClassRegLog(stageLog, &classRegLog));
298:   PetscCall(PetscStageLogGetClassPerfLog(stageLog, stage, &classPerfLog));
299:   PetscCall(PetscClassRegLogGetClass(classRegLog, obj->classid, &oclass));
300:   classPerfLog->classInfo[oclass].creations++;
301:   /* Dynamically enlarge logging structures */
302:   if (petsc_numActions >= petsc_maxActions) {
303:     PetscCall(PetscTime(&start));
304:     PetscCall(PetscMalloc1(petsc_maxActions * 2, &tmpAction));
305:     PetscCall(PetscArraycpy(tmpAction, petsc_actions, petsc_maxActions));
306:     PetscCall(PetscFree(petsc_actions));

308:     petsc_actions = tmpAction;
309:     petsc_maxActions *= 2;
310:     PetscCall(PetscTime(&end));
311:     petsc_BaseTime += (end - start);
312:   }

314:   petsc_numObjects = obj->id;
315:   /* Record the creation action */
316:   if (petsc_logActions) {
317:     PetscCall(PetscTime(&petsc_actions[petsc_numActions].time));
318:     petsc_actions[petsc_numActions].time -= petsc_BaseTime;
319:     petsc_actions[petsc_numActions].action  = CREATE;
320:     petsc_actions[petsc_numActions].classid = obj->classid;
321:     petsc_actions[petsc_numActions].id1     = petsc_numObjects;
322:     petsc_actions[petsc_numActions].id2     = -1;
323:     petsc_actions[petsc_numActions].id3     = -1;
324:     petsc_actions[petsc_numActions].flops   = petsc_TotalFlops;

326:     PetscCall(PetscMallocGetCurrentUsage(&petsc_actions[petsc_numActions].mem));
327:     PetscCall(PetscMallocGetMaximumUsage(&petsc_actions[petsc_numActions].maxmem));
328:     petsc_numActions++;
329:   }
330:   /* Record the object */
331:   if (petsc_logObjects) {
332:     petsc_objects[petsc_numObjects].parent = -1;
333:     petsc_objects[petsc_numObjects].obj    = obj;

335:     PetscCall(PetscMemzero(petsc_objects[petsc_numObjects].name, sizeof(petsc_objects[0].name)));
336:     PetscCall(PetscMemzero(petsc_objects[petsc_numObjects].info, sizeof(petsc_objects[0].info)));

338:     /* Dynamically enlarge logging structures */
339:     if (petsc_numObjects >= petsc_maxObjects) {
340:       PetscCall(PetscTime(&start));
341:       PetscCall(PetscMalloc1(petsc_maxObjects * 2, &tmpObjects));
342:       PetscCall(PetscArraycpy(tmpObjects, petsc_objects, petsc_maxObjects));
343:       PetscCall(PetscFree(petsc_objects));

345:       petsc_objects = tmpObjects;
346:       petsc_maxObjects *= 2;
347:       PetscCall(PetscTime(&end));
348:       petsc_BaseTime += (end - start);
349:     }
350:   }
351:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
352:   PetscFunctionReturn(PETSC_SUCCESS);
353: }

355: /* Default object destroy logger */
356: PetscErrorCode PetscLogObjDestroyDefault(PetscObject obj)
357: {
358:   PetscStageLog     stageLog;
359:   PetscClassRegLog  classRegLog;
360:   PetscClassPerfLog classPerfLog;
361:   Action           *tmpAction;
362:   PetscLogDouble    start, end;
363:   int               oclass = 0;
364:   int               stage;

366:   PetscFunctionBegin;
367:   /* Record stage info */
368:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
369:   PetscCall(PetscLogGetStageLog(&stageLog));
370:   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
371:   if (stage != -1) {
372:     /* That can happen if the log summary is output before some things are destroyed */
373:     PetscCall(PetscStageLogGetClassRegLog(stageLog, &classRegLog));
374:     PetscCall(PetscStageLogGetClassPerfLog(stageLog, stage, &classPerfLog));
375:     PetscCall(PetscClassRegLogGetClass(classRegLog, obj->classid, &oclass));
376:     classPerfLog->classInfo[oclass].destructions++;
377:   }
378:   /* Cannot Credit all ancestors with your memory because they may have already been destroyed*/
379:   petsc_numObjectsDestroyed++;
380:   /* Dynamically enlarge logging structures */
381:   if (petsc_numActions >= petsc_maxActions) {
382:     PetscCall(PetscTime(&start));
383:     PetscCall(PetscMalloc1(petsc_maxActions * 2, &tmpAction));
384:     PetscCall(PetscArraycpy(tmpAction, petsc_actions, petsc_maxActions));
385:     PetscCall(PetscFree(petsc_actions));

387:     petsc_actions = tmpAction;
388:     petsc_maxActions *= 2;
389:     PetscCall(PetscTime(&end));
390:     petsc_BaseTime += (end - start);
391:   }
392:   /* Record the destruction action */
393:   if (petsc_logActions) {
394:     PetscCall(PetscTime(&petsc_actions[petsc_numActions].time));
395:     petsc_actions[petsc_numActions].time -= petsc_BaseTime;
396:     petsc_actions[petsc_numActions].action  = DESTROY;
397:     petsc_actions[petsc_numActions].classid = obj->classid;
398:     petsc_actions[petsc_numActions].id1     = obj->id;
399:     petsc_actions[petsc_numActions].id2     = -1;
400:     petsc_actions[petsc_numActions].id3     = -1;
401:     petsc_actions[petsc_numActions].flops   = petsc_TotalFlops;

403:     PetscCall(PetscMallocGetCurrentUsage(&petsc_actions[petsc_numActions].mem));
404:     PetscCall(PetscMallocGetMaximumUsage(&petsc_actions[petsc_numActions].maxmem));
405:     petsc_numActions++;
406:   }
407:   if (petsc_logObjects) {
408:     if (obj->name) PetscCall(PetscStrncpy(petsc_objects[obj->id].name, obj->name, 64));
409:     petsc_objects[obj->id].obj = NULL;
410:   }
411:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }