Actual source code: mtr.c
2: /*
3: Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4: */
5: #include <petsc/private/petscimpl.h>
6: #include <petscviewer.h>
7: #if defined(PETSC_HAVE_MALLOC_H)
8: #include <malloc.h>
9: #endif
11: /*
12: These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13: */
14: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,PetscBool,int,const char[],const char[],void**);
15: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
16: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
18: #define CLASSID_VALUE ((PetscClassId) 0xf0e0d0c9)
19: #define ALREADY_FREED ((PetscClassId) 0x0f0e0d9c)
21: /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22: typedef struct _trSPACE {
23: size_t size, rsize; /* Aligned size and requested size */
24: int id;
25: int lineno;
26: const char *filename;
27: const char *functionname;
28: PetscClassId classid;
29: #if defined(PETSC_USE_DEBUG)
30: PetscStack stack;
31: #endif
32: struct _trSPACE *next,*prev;
33: } TRSPACE;
35: /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
36: It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
37: */
38: #define HEADER_BYTES ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
40: /* This union is used to insure that the block passed to the user retains
41: a minimum alignment of PETSC_MEMALIGN.
42: */
43: typedef union {
44: TRSPACE sp;
45: char v[HEADER_BYTES];
46: } TrSPACE;
48: #define MAXTRMAXMEMS 50
49: static size_t TRallocated = 0;
50: static int TRfrags = 0;
51: static TRSPACE *TRhead = NULL;
52: static int TRid = 0;
53: static PetscBool TRdebugLevel = PETSC_FALSE;
54: static PetscBool TRdebugIinitializenan= PETSC_FALSE;
55: static PetscBool TRrequestedSize = PETSC_FALSE;
56: static size_t TRMaxMem = 0;
57: static int NumTRMaxMems = 0;
58: static size_t TRMaxMems[MAXTRMAXMEMS];
59: static int TRMaxMemsEvents[MAXTRMAXMEMS];
60: /*
61: Arrays to log information on mallocs for PetscMallocView()
62: */
63: static int PetscLogMallocMax = 10000;
64: static int PetscLogMalloc = -1;
65: static size_t PetscLogMallocThreshold = 0;
66: static size_t *PetscLogMallocLength;
67: static const char **PetscLogMallocFile,**PetscLogMallocFunction;
68: static int PetscLogMallocTrace = -1;
69: static size_t PetscLogMallocTraceThreshold = 0;
70: static PetscViewer PetscLogMallocTraceViewer = NULL;
72: /*@C
73: PetscMallocValidate - Test the memory for corruption. This can be called at any time between PetscInitialize() and PetscFinalize()
75: Input Parameters:
76: + line - line number where call originated.
77: . function - name of function calling
78: - file - file where function is
80: Return value:
81: The number of errors detected.
83: Options Database:.
84: + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
85: - -malloc_debug - turns this feature on anytime
87: Output Effect:
88: Error messages are written to stdout.
90: Level: advanced
92: Notes:
93: This is only run if PetscMallocSetDebug() has been called which is set by -malloc_test (if debugging is turned on) or -malloc_debug (any time)
95: You should generally use CHKMEMQ as a short cut for calling this routine.
97: The Fortran calling sequence is simply PetscMallocValidate(ierr)
99: No output is generated if there are no problems detected.
101: Developers Note:
102: Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run
104: .seealso: CHKMEMQ
106: @*/
107: PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[])
108: {
109: TRSPACE *head,*lasthead;
110: char *a;
111: PetscClassId *nend;
113: if (!TRdebugLevel) return 0;
114: head = TRhead; lasthead = NULL;
115: if (head && head->prev) {
116: (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
117: (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n",head,head->prev);
118: return PETSC_ERR_MEMC;
119: }
120: while (head) {
121: if (head->classid != CLASSID_VALUE) {
122: (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
123: (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
124: (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
125: if (lasthead) {
126: a = (char*)(((TrSPACE*)head) + 1);
127: (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n",lasthead->id,(PetscLogDouble)lasthead->size,a,lasthead->functionname,lasthead->filename,lasthead->lineno);
128: }
129: abort();
130: return PETSC_ERR_MEMC;
131: }
132: a = (char*)(((TrSPACE*)head) + 1);
133: nend = (PetscClassId*)(a + head->size);
134: if (*nend != CLASSID_VALUE) {
135: (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
136: if (*nend == ALREADY_FREED) {
137: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
138: return PETSC_ERR_MEMC;
139: } else {
140: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
141: (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
142: return PETSC_ERR_MEMC;
143: }
144: }
145: if (head->prev && head->prev != lasthead) {
146: (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
147: (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
148: (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n",lasthead->functionname,lasthead->filename,lasthead->lineno);
149: (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
150: return PETSC_ERR_MEMC;
151: }
152: lasthead = head;
153: head = head->next;
154: }
155: return 0;
156: }
158: /*
159: PetscTrMallocDefault - Malloc with tracing.
161: Input Parameters:
162: + a - number of bytes to allocate
163: . lineno - line number where used. Use __LINE__ for this
164: - filename - file name where used. Use __FILE__ for this
166: Returns:
167: double aligned pointer to requested storage, or null if not available.
168: */
169: PetscErrorCode PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
170: {
171: TRSPACE *head;
172: char *inew;
173: size_t nsize;
176: /* Do not try to handle empty blocks */
177: if (!a) { *result = NULL; return 0; }
179: PetscMallocValidate(lineno,function,filename); if (ierr) return ierr;
181: nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
182: PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);
184: head = (TRSPACE*)inew;
185: inew += sizeof(TrSPACE);
187: if (TRhead) TRhead->prev = head;
188: head->next = TRhead;
189: TRhead = head;
190: head->prev = NULL;
191: head->size = nsize;
192: head->rsize = a;
193: head->id = TRid++;
194: head->lineno = lineno;
196: head->filename = filename;
197: head->functionname = function;
198: head->classid = CLASSID_VALUE;
199: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
201: TRallocated += TRrequestedSize ? head->rsize : head->size;
202: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
203: if (PetscLogMemory) {
204: PetscInt i;
205: for (i=0; i<NumTRMaxMems; i++) {
206: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
207: }
208: }
209: TRfrags++;
211: #if defined(PETSC_USE_DEBUG)
212: PetscStackCopy(&petscstack,&head->stack);
213: head->stack.line[head->stack.currentsize-2] = lineno;
214: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
215: if (!clear && TRdebugIinitializenan) {
216: size_t i, n = a/sizeof(PetscReal);
217: PetscReal *s = (PetscReal*) inew;
218: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
219: #if defined(PETSC_USE_REAL_SINGLE)
220: int nas = 0x7F800002;
221: #else
222: PetscInt64 nas = 0x7FF0000000000002;
223: #endif
224: for (i=0; i<n; i++) {
225: memcpy(s+i,&nas,sizeof(PetscReal));
226: }
227: }
228: #endif
229: #endif
231: /*
232: Allow logging of all mallocs made.
233: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
234: */
235: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
236: if (!PetscLogMalloc) {
237: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
240: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
243: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
245: }
246: PetscLogMallocLength[PetscLogMalloc] = nsize;
247: PetscLogMallocFile[PetscLogMalloc] = filename;
248: PetscLogMallocFunction[PetscLogMalloc++] = function;
249: }
250: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
251: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");
252: }
253: *result = (void*)inew;
254: return 0;
255: }
257: /*
258: PetscTrFreeDefault - Free with tracing.
260: Input Parameters:
261: . a - pointer to a block allocated with PetscTrMalloc
262: . lineno - line number where used. Use __LINE__ for this
263: . filename - file name where used. Use __FILE__ for this
264: */
265: PetscErrorCode PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
266: {
267: char *a = (char*)aa;
268: TRSPACE *head;
269: char *ahead;
270: size_t asize;
271: PetscClassId *nend;
273: /* Do not try to handle empty blocks */
274: if (!a) return 0;
276: PetscMallocValidate(lineno,function,filename);
278: ahead = a;
279: a = a - sizeof(TrSPACE);
280: head = (TRSPACE*)a;
282: if (head->classid != CLASSID_VALUE) {
283: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
284: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
285: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
286: }
287: nend = (PetscClassId*)(ahead + head->size);
288: if (*nend != CLASSID_VALUE) {
289: if (*nend == ALREADY_FREED) {
290: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
291: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
292: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
293: (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
294: } else {
295: (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
296: }
297: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
298: } else {
299: /* Damaged tail */
300: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
301: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
302: (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
303: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
304: }
305: }
306: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
307: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");
308: }
309: /* Mark the location freed */
310: *nend = ALREADY_FREED;
311: /* Save location where freed. If we suspect the line number, mark as allocated location */
312: if (lineno > 0 && lineno < 50000) {
313: head->lineno = lineno;
314: head->filename = filename;
315: head->functionname = function;
316: } else {
317: head->lineno = -head->lineno;
318: }
319: asize = TRrequestedSize ? head->rsize : head->size;
321: TRallocated -= asize;
322: TRfrags--;
323: if (head->prev) head->prev->next = head->next;
324: else TRhead = head->next;
326: if (head->next) head->next->prev = head->prev;
327: PetscFreeAlign(a,lineno,function,filename);
328: return 0;
329: }
331: /*
332: PetscTrReallocDefault - Realloc with tracing.
334: Input Parameters:
335: + len - number of bytes to allocate
336: . lineno - line number where used. Use __LINE__ for this
337: . filename - file name where used. Use __FILE__ for this
338: - result - original memory
340: Output Parameter:
341: . result - double aligned pointer to requested storage, or null if not available.
343: Level: developer
345: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
346: */
347: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
348: {
349: char *a = (char *) *result;
350: TRSPACE *head;
351: char *ahead, *inew;
352: PetscClassId *nend;
353: size_t nsize;
356: /* Realloc requests zero space so just free the current space */
357: if (!len) {
358: PetscTrFreeDefault(*result,lineno,function,filename);
359: *result = NULL;
360: return 0;
361: }
362: /* If the orginal space was NULL just use the regular malloc() */
363: if (!*result) {
364: PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
365: return 0;
366: }
368: PetscMallocValidate(lineno,function,filename); if (ierr) return ierr;
370: ahead = a;
371: a = a - sizeof(TrSPACE);
372: head = (TRSPACE *) a;
373: inew = a;
375: if (head->classid != CLASSID_VALUE) {
376: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
377: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
378: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
379: }
380: nend = (PetscClassId *)(ahead + head->size);
381: if (*nend != CLASSID_VALUE) {
382: if (*nend == ALREADY_FREED) {
383: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
384: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
385: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
386: (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
387: } else {
388: (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
389: }
390: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
391: } else {
392: /* Damaged tail */
393: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
394: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
395: (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
396: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
397: }
398: }
400: /* remove original reference to the memory allocated from the PETSc debugging heap */
401: TRallocated -= TRrequestedSize ? head->rsize : head->size;
402: TRfrags--;
403: if (head->prev) head->prev->next = head->next;
404: else TRhead = head->next;
405: if (head->next) head->next->prev = head->prev;
407: nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
408: PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);
410: head = (TRSPACE*)inew;
411: inew += sizeof(TrSPACE);
413: if (TRhead) TRhead->prev = head;
414: head->next = TRhead;
415: TRhead = head;
416: head->prev = NULL;
417: head->size = nsize;
418: head->rsize = len;
419: head->id = TRid++;
420: head->lineno = lineno;
422: head->filename = filename;
423: head->functionname = function;
424: head->classid = CLASSID_VALUE;
425: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
427: TRallocated += TRrequestedSize ? head->rsize : head->size;
428: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
429: if (PetscLogMemory) {
430: PetscInt i;
431: for (i=0; i<NumTRMaxMems; i++) {
432: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
433: }
434: }
435: TRfrags++;
437: #if defined(PETSC_USE_DEBUG)
438: PetscStackCopy(&petscstack,&head->stack);
439: head->stack.line[head->stack.currentsize-2] = lineno;
440: #endif
442: /*
443: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
444: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
445: */
446: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
447: if (!PetscLogMalloc) {
448: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
451: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
454: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
456: }
457: PetscLogMallocLength[PetscLogMalloc] = nsize;
458: PetscLogMallocFile[PetscLogMalloc] = filename;
459: PetscLogMallocFunction[PetscLogMalloc++] = function;
460: }
461: *result = (void*)inew;
462: return 0;
463: }
465: /*@C
466: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
468: Collective on PetscViewer
470: Input Parameters:
471: + viewer - the viewer that defines the communicator
472: - message - string printed before values
474: Options Database:
475: + -malloc_debug - have PETSc track how much memory it has allocated
476: - -memory_view - during PetscFinalize() have this routine called
478: Level: intermediate
480: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
481: @*/
482: PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[])
483: {
484: PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
485: PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
486: MPI_Comm comm;
488: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
489: PetscMallocGetCurrentUsage(&allocated);
490: PetscMallocGetMaximumUsage(&allocatedmax);
491: PetscMemoryGetCurrentUsage(&resident);
492: PetscMemoryGetMaximumUsage(&residentmax);
493: if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
494: PetscObjectGetComm((PetscObject)viewer,&comm);
495: PetscViewerASCIIPrintf(viewer,"%s",message);
496: if (resident && residentmax && allocated) {
497: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
498: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
499: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
500: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
501: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
502: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
503: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
504: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
505: MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
506: MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
507: MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
508: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);
509: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
510: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
511: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
512: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
513: } else if (resident && residentmax) {
514: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
515: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
516: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
517: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
518: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
519: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
520: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
521: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
522: } else if (resident && allocated) {
523: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
524: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
525: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
526: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
527: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
528: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
529: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
530: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
531: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
532: } else if (allocated) {
533: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
534: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
535: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
536: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
537: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
538: PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");
539: } else {
540: PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
541: }
542: PetscViewerFlush(viewer);
543: return 0;
544: }
546: /*@
547: PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
549: Not Collective
551: Output Parameters:
552: . space - number of bytes currently allocated
554: Level: intermediate
556: .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
557: PetscMemoryGetMaximumUsage()
558: @*/
559: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
560: {
561: *space = (PetscLogDouble) TRallocated;
562: return 0;
563: }
565: /*@
566: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
567: during this run.
569: Not Collective
571: Output Parameters:
572: . space - maximum number of bytes ever allocated at one time
574: Level: intermediate
576: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
577: PetscMallocPushMaximumUsage()
578: @*/
579: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
580: {
581: *space = (PetscLogDouble) TRMaxMem;
582: return 0;
583: }
585: /*@
586: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
588: Not Collective
590: Input Parameter:
591: . event - an event id; this is just for error checking
593: Level: developer
595: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
596: PetscMallocPopMaximumUsage()
597: @*/
598: PetscErrorCode PetscMallocPushMaximumUsage(int event)
599: {
600: if (++NumTRMaxMems > MAXTRMAXMEMS) return 0;
601: TRMaxMems[NumTRMaxMems-1] = TRallocated;
602: TRMaxMemsEvents[NumTRMaxMems-1] = event;
603: return 0;
604: }
606: /*@
607: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
609: Not Collective
611: Input Parameter:
612: . event - an event id; this is just for error checking
614: Output Parameter:
615: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
617: Level: developer
619: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
620: PetscMallocPushMaximumUsage()
621: @*/
622: PetscErrorCode PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
623: {
624: *mu = 0;
625: if (NumTRMaxMems-- > MAXTRMAXMEMS) return 0;
627: *mu = TRMaxMems[NumTRMaxMems];
628: return 0;
629: }
631: #if defined(PETSC_USE_DEBUG)
632: /*@C
633: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
635: Collective on PETSC_COMM_WORLD
637: Input Parameter:
638: . ptr - the memory location
640: Output Parameter:
641: . stack - the stack indicating where the program allocated this memory
643: Level: intermediate
645: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView()
646: @*/
647: PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack)
648: {
649: TRSPACE *head;
651: head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
652: *stack = &head->stack;
653: return 0;
654: }
655: #else
656: PetscErrorCode PetscMallocGetStack(void *ptr,void **stack)
657: {
658: *stack = NULL;
659: return 0;
660: }
661: #endif
663: /*@C
664: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
665: printed is: size of space (in bytes), address of space, id of space,
666: file in which space was allocated, and line number at which it was
667: allocated.
669: Not Collective
671: Input Parameter:
672: . fp - file pointer. If fp is NULL, stdout is assumed.
674: Options Database Key:
675: . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
677: Level: intermediate
679: Fortran Note:
680: The calling sequence in Fortran is PetscMallocDump(integer ierr)
681: The fp defaults to stdout.
683: Notes:
684: Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
686: When called in PetscFinalize() dumps only the allocations that have not been properly freed
688: PetscMallocView() prints a list of all memory ever allocated
690: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
691: @*/
692: PetscErrorCode PetscMallocDump(FILE *fp)
693: {
694: TRSPACE *head;
695: size_t libAlloc = 0;
696: PetscMPIInt rank;
698: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
699: if (!fp) fp = PETSC_STDOUT;
700: head = TRhead;
701: while (head) {
702: libAlloc += TRrequestedSize ? head->rsize : head->size;
703: head = head->next;
704: }
705: if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
706: head = TRhead;
707: while (head) {
708: PetscBool isLib;
710: PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
711: if (!isLib) {
712: fprintf(fp,"[%2d] %.0f bytes %s() at %s:%d\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->filename,head->lineno);
713: #if defined(PETSC_USE_DEBUG)
714: PetscStackPrint(&head->stack,fp);
715: #endif
716: }
717: head = head->next;
718: }
719: return 0;
720: }
722: /*@
723: PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
725: Not Collective
727: Input Parameter:
728: . logmin - minimum allocation size to log, or PETSC_DEFAULT
730: Options Database Key:
731: + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
732: . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
733: - -log_view_memory - view the memory usage also with the -log_view option
735: Level: advanced
737: Notes: Must be called after PetscMallocSetDebug()
739: Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
741: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
742: @*/
743: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
744: {
745: PetscLogMalloc = 0;
746: PetscMemorySetGetMaximumUsage();
747: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
748: PetscLogMallocThreshold = (size_t)logmin;
749: return 0;
750: }
752: /*@
753: PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
755: Not Collective
757: Output Parameter
758: . logging - PETSC_TRUE if logging is active
760: Options Database Key:
761: . -malloc_view <optional filename> - Activates PetscMallocView()
763: Level: advanced
765: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
766: @*/
767: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
768: {
769: *logging = (PetscBool)(PetscLogMalloc >= 0);
770: return 0;
771: }
773: /*@
774: PetscMallocTraceSet - Trace all calls to PetscMalloc()
776: Not Collective
778: Input Parameters:
779: + viewer - The viewer to use for tracing, or NULL to use stdout
780: . active - Flag to activate or deactivate tracing
781: - logmin - The smallest memory size that will be logged
783: Note:
784: The viewer should not be collective.
786: Level: advanced
788: .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
789: @*/
790: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
791: {
792: if (!active) {PetscLogMallocTrace = -1; return 0;}
793: PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
794: PetscLogMallocTrace = 0;
795: PetscMemorySetGetMaximumUsage();
796: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
797: PetscLogMallocTraceThreshold = (size_t) logmin;
798: return 0;
799: }
801: /*@
802: PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
804: Not Collective
806: Output Parameter:
807: . logging - PETSC_TRUE if logging is active
809: Options Database Key:
810: . -malloc_view <optional filename> - Activates PetscMallocView()
812: Level: advanced
814: .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
815: @*/
816: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
817: {
818: *logging = (PetscBool) (PetscLogMallocTrace >= 0);
819: return 0;
820: }
822: /*@C
823: PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
824: PetscMemoryGetMaximumUsage()
826: Not Collective
828: Input Parameter:
829: . fp - file pointer; or NULL
831: Options Database Key:
832: . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
834: Level: advanced
836: Fortran Note:
837: The calling sequence in Fortran is PetscMallocView(integer ierr)
838: The fp defaults to stdout.
840: Notes:
841: PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
843: PetscMemoryView() gives a brief summary of current memory usage
845: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
846: @*/
847: PetscErrorCode PetscMallocView(FILE *fp)
848: {
849: PetscInt i,j,n,*perm;
850: size_t *shortlength;
851: int *shortcount,err;
852: PetscMPIInt rank;
853: PetscBool match;
854: const char **shortfunction;
855: PetscLogDouble rss;
857: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
858: err = fflush(fp);
863: if (!fp) fp = PETSC_STDOUT;
864: PetscMemoryGetMaximumUsage(&rss);
865: if (rss) {
866: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
867: } else {
868: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
869: }
873: for (i=0,n=0; i<PetscLogMalloc; i++) {
874: for (j=0; j<n; j++) {
875: PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
876: if (match) {
877: shortlength[j] += PetscLogMallocLength[i];
878: shortcount[j]++;
879: goto foundit;
880: }
881: }
882: shortfunction[n] = PetscLogMallocFunction[i];
883: shortlength[n] = PetscLogMallocLength[i];
884: shortcount[n] = 1;
885: n++;
886: foundit:;
887: }
890: for (i=0; i<n; i++) perm[i] = i;
891: PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);
893: (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
894: for (i=0; i<n; i++) {
895: (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
896: }
897: free(perm);
898: free(shortlength);
899: free(shortcount);
900: free((char**)shortfunction);
901: err = fflush(fp);
903: return 0;
904: }
906: /* ---------------------------------------------------------------------------- */
908: /*@
909: PetscMallocSetDebug - Set's PETSc memory debugging
911: Not Collective
913: Input Parameters:
914: + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
915: - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
917: Options Database:
918: + -malloc_debug <true or false> - turns on or off debugging
919: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
920: . -malloc_view_threshold t - log only allocations larger than t
921: . -malloc_dump <filename> - print a list of all memory that has not been freed
922: . -malloc no - (deprecated) same as -malloc_debug no
923: - -malloc_log - (deprecated) same as -malloc_view
925: Level: developer
927: Notes: This is called in PetscInitialize() and should not be called elsewhere
929: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
930: @*/
931: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
932: {
934: PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);
936: TRallocated = 0;
937: TRfrags = 0;
938: TRhead = NULL;
939: TRid = 0;
940: TRdebugLevel = eachcall;
941: TRMaxMem = 0;
942: PetscLogMallocMax = 10000;
943: PetscLogMalloc = -1;
944: TRdebugIinitializenan = initializenan;
945: return 0;
946: }
948: /*@
949: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
951: Not Collective
953: Output Parameters:
954: + basic - doing basic debugging
955: . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
956: - initializenan - initializes memory with NaN
958: Level: intermediate
960: Notes:
961: By default, the debug version always does some debugging unless you run with -malloc_debug no
963: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
964: @*/
965: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
966: {
967: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
968: if (eachcall) *eachcall = TRdebugLevel;
969: if (initializenan) *initializenan = TRdebugIinitializenan;
970: return 0;
971: }
973: /*@
974: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
976: Not Collective
978: Input Parameter:
979: . flg - PETSC_TRUE to log the requested memory size
981: Options Database:
982: . -malloc_requested_size <bool> - Sets this flag
984: Level: developer
986: .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
987: @*/
988: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
989: {
990: TRrequestedSize = flg;
991: return 0;
992: }
994: /*@
995: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
997: Not Collective
999: Output Parameter:
1000: . flg - PETSC_TRUE if we log the requested memory size
1002: Level: developer
1004: .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1005: @*/
1006: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1007: {
1008: *flg = TRrequestedSize;
1009: return 0;
1010: }