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 <petscsys.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 at %s() line %d in %s\n",function,line,file);
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 at %s() line %d in %s\n",function,line,file);
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() line %d in %s\n",lasthead->id,(PetscLogDouble)lasthead->size,a,lasthead->functionname,lasthead->lineno,lasthead->filename);
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 at %s() line %d in %s\n",function,line,file);
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() line %d in %s\n",head->functionname,head->lineno,head->filename);
142: return PETSC_ERR_MEMC;
143: }
144: }
145: if (head->prev && head->prev != lasthead) {
146: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
147: (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
148: (*PetscErrorPrintf)("Previous memory originally allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
149: (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
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;
177: /* Do not try to handle empty blocks */
178: if (!a) { *result = NULL; return(0); }
180: PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
182: nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
183: PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);
185: head = (TRSPACE*)inew;
186: inew += sizeof(TrSPACE);
188: if (TRhead) TRhead->prev = head;
189: head->next = TRhead;
190: TRhead = head;
191: head->prev = NULL;
192: head->size = nsize;
193: head->rsize = a;
194: head->id = TRid++;
195: head->lineno = lineno;
197: head->filename = filename;
198: head->functionname = function;
199: head->classid = CLASSID_VALUE;
200: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
202: TRallocated += TRrequestedSize ? head->rsize : head->size;
203: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
204: if (PetscLogMemory) {
205: PetscInt i;
206: for (i=0; i<NumTRMaxMems; i++) {
207: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
208: }
209: }
210: TRfrags++;
212: #if defined(PETSC_USE_DEBUG)
213: if (PetscStackActive()) {
214: PetscStackCopy(petscstack,&head->stack);
216: head->stack.line[head->stack.currentsize-2] = lineno;
217: } else {
218: head->stack.currentsize = 0;
219: }
220: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
221: if (!clear && TRdebugIinitializenan) {
222: size_t i, n = a/sizeof(PetscReal);
223: PetscReal *s = (PetscReal*) inew;
224: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
225: #if defined(PETSC_USE_REAL_SINGLE)
226: int nas = 0x7F800002;
227: #else
228: PetscInt64 nas = 0x7FF0000000000002;
229: #endif
230: for (i=0; i<n; i++) {
231: memcpy(s+i,&nas,sizeof(PetscReal));
232: }
233: }
234: #endif
235: #endif
237: /*
238: Allow logging of all mallocs made.
239: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
240: */
241: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
242: if (!PetscLogMalloc) {
243: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
244: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
246: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
247: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
249: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
250: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
251: }
252: PetscLogMallocLength[PetscLogMalloc] = nsize;
253: PetscLogMallocFile[PetscLogMalloc] = filename;
254: PetscLogMallocFunction[PetscLogMalloc++] = function;
255: }
256: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
257: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");
258: }
259: *result = (void*)inew;
260: return(0);
261: }
263: /*
264: PetscTrFreeDefault - Free with tracing.
266: Input Parameters:
267: . a - pointer to a block allocated with PetscTrMalloc
268: . lineno - line number where used. Use __LINE__ for this
269: . filename - file name where used. Use __FILE__ for this
270: */
271: PetscErrorCode PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
272: {
273: char *a = (char*)aa;
274: TRSPACE *head;
275: char *ahead;
276: size_t asize;
278: PetscClassId *nend;
281: /* Do not try to handle empty blocks */
282: if (!a) return(0);
284: PetscMallocValidate(lineno,function,filename);
286: ahead = a;
287: a = a - sizeof(TrSPACE);
288: head = (TRSPACE*)a;
290: if (head->classid != CLASSID_VALUE) {
291: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
292: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
293: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
294: }
295: nend = (PetscClassId*)(ahead + head->size);
296: if (*nend != CLASSID_VALUE) {
297: if (*nend == ALREADY_FREED) {
298: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
299: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
300: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
301: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
302: } else {
303: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
304: }
305: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
306: } else {
307: /* Damaged tail */
308: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
309: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
310: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
311: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
312: }
313: }
314: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
315: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");
316: }
317: /* Mark the location freed */
318: *nend = ALREADY_FREED;
319: /* Save location where freed. If we suspect the line number, mark as allocated location */
320: if (lineno > 0 && lineno < 50000) {
321: head->lineno = lineno;
322: head->filename = filename;
323: head->functionname = function;
324: } else {
325: head->lineno = -head->lineno;
326: }
327: asize = TRrequestedSize ? head->rsize : head->size;
328: if (TRallocated < asize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
329: TRallocated -= asize;
330: TRfrags--;
331: if (head->prev) head->prev->next = head->next;
332: else TRhead = head->next;
334: if (head->next) head->next->prev = head->prev;
335: PetscFreeAlign(a,lineno,function,filename);
336: return(0);
337: }
339: /*
340: PetscTrReallocDefault - Realloc with tracing.
342: Input Parameters:
343: + len - number of bytes to allocate
344: . lineno - line number where used. Use __LINE__ for this
345: . filename - file name where used. Use __FILE__ for this
346: - result - original memory
348: Output Parameter:
349: . result - double aligned pointer to requested storage, or null if not available.
351: Level: developer
353: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
354: */
355: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
356: {
357: char *a = (char *) *result;
358: TRSPACE *head;
359: char *ahead, *inew;
360: PetscClassId *nend;
361: size_t nsize;
365: /* Realloc requests zero space so just free the current space */
366: if (!len) {
367: PetscTrFreeDefault(*result,lineno,function,filename);
368: *result = NULL;
369: return(0);
370: }
371: /* If the orginal space was NULL just use the regular malloc() */
372: if (!*result) {
373: PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
374: return(0);
375: }
377: PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
379: ahead = a;
380: a = a - sizeof(TrSPACE);
381: head = (TRSPACE *) a;
382: inew = a;
384: if (head->classid != CLASSID_VALUE) {
385: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
386: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
387: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
388: }
389: nend = (PetscClassId *)(ahead + head->size);
390: if (*nend != CLASSID_VALUE) {
391: if (*nend == ALREADY_FREED) {
392: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
393: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
394: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
395: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
396: } else {
397: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
398: }
399: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
400: } else {
401: /* Damaged tail */
402: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
403: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
404: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
405: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
406: }
407: }
409: /* remove original reference to the memory allocated from the PETSc debugging heap */
410: TRallocated -= TRrequestedSize ? head->rsize : head->size;
411: TRfrags--;
412: if (head->prev) head->prev->next = head->next;
413: else TRhead = head->next;
414: if (head->next) head->next->prev = head->prev;
416: nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
417: PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);
419: head = (TRSPACE*)inew;
420: inew += sizeof(TrSPACE);
422: if (TRhead) TRhead->prev = head;
423: head->next = TRhead;
424: TRhead = head;
425: head->prev = NULL;
426: head->size = nsize;
427: head->rsize = len;
428: head->id = TRid++;
429: head->lineno = lineno;
431: head->filename = filename;
432: head->functionname = function;
433: head->classid = CLASSID_VALUE;
434: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
436: TRallocated += TRrequestedSize ? head->rsize : head->size;
437: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
438: if (PetscLogMemory) {
439: PetscInt i;
440: for (i=0; i<NumTRMaxMems; i++) {
441: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
442: }
443: }
444: TRfrags++;
446: #if defined(PETSC_USE_DEBUG)
447: if (PetscStackActive()) {
448: PetscStackCopy(petscstack,&head->stack);
450: head->stack.line[head->stack.currentsize-2] = lineno;
451: } else {
452: head->stack.currentsize = 0;
453: }
454: #endif
456: /*
457: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
458: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
459: */
460: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
461: if (!PetscLogMalloc) {
462: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
463: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
465: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
466: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
468: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
469: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
470: }
471: PetscLogMallocLength[PetscLogMalloc] = nsize;
472: PetscLogMallocFile[PetscLogMalloc] = filename;
473: PetscLogMallocFunction[PetscLogMalloc++] = function;
474: }
475: *result = (void*)inew;
476: return(0);
477: }
479: /*@C
480: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
482: Collective on PetscViewer
484: Input Parameter:
485: + viewer - the viewer that defines the communicator
486: - message - string printed before values
488: Options Database:
489: + -malloc_debug - have PETSc track how much memory it has allocated
490: - -memory_view - during PetscFinalize() have this routine called
492: Level: intermediate
494: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
495: @*/
496: PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[])
497: {
498: PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
499: PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
501: MPI_Comm comm;
504: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
505: PetscMallocGetCurrentUsage(&allocated);
506: PetscMallocGetMaximumUsage(&allocatedmax);
507: PetscMemoryGetCurrentUsage(&resident);
508: PetscMemoryGetMaximumUsage(&residentmax);
509: if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
510: PetscObjectGetComm((PetscObject)viewer,&comm);
511: PetscViewerASCIIPrintf(viewer,message);
512: if (resident && residentmax && allocated) {
513: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
514: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
515: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
516: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
517: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
518: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
519: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
520: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
521: MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
522: MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
523: MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
524: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);
525: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
526: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
527: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
528: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
529: } else if (resident && residentmax) {
530: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
531: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
532: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
533: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
534: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
535: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
536: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
537: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
538: } else if (resident && allocated) {
539: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
540: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
541: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
542: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
543: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
544: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
545: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
546: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
547: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
548: } else if (allocated) {
549: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
550: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
551: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
552: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
553: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
554: PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");
555: } else {
556: PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
557: }
558: PetscViewerFlush(viewer);
559: return(0);
560: }
562: /*@
563: PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
565: Not Collective
567: Output Parameters:
568: . space - number of bytes currently allocated
570: Level: intermediate
572: .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
573: PetscMemoryGetMaximumUsage()
574: @*/
575: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
576: {
578: *space = (PetscLogDouble) TRallocated;
579: return(0);
580: }
582: /*@
583: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
584: during this run.
586: Not Collective
588: Output Parameters:
589: . space - maximum number of bytes ever allocated at one time
591: Level: intermediate
593: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
594: PetscMallocPushMaximumUsage()
595: @*/
596: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
597: {
599: *space = (PetscLogDouble) TRMaxMem;
600: return(0);
601: }
603: /*@
604: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
606: Not Collective
608: Input Parameter:
609: . event - an event id; this is just for error checking
611: Level: developer
613: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
614: PetscMallocPopMaximumUsage()
615: @*/
616: PetscErrorCode PetscMallocPushMaximumUsage(int event)
617: {
619: if (++NumTRMaxMems > MAXTRMAXMEMS) return(0);
620: TRMaxMems[NumTRMaxMems-1] = TRallocated;
621: TRMaxMemsEvents[NumTRMaxMems-1] = event;
622: return(0);
623: }
625: /*@
626: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
628: Not Collective
630: Input Parameter:
631: . event - an event id; this is just for error checking
633: Output Parameter:
634: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
636: Level: developer
638: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
639: PetscMallocPushMaximumUsage()
640: @*/
641: PetscErrorCode PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
642: {
644: *mu = 0;
645: if (NumTRMaxMems-- > MAXTRMAXMEMS) return(0);
646: if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
647: *mu = TRMaxMems[NumTRMaxMems];
648: return(0);
649: }
651: #if defined(PETSC_USE_DEBUG)
652: /*@C
653: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
655: Collective on PETSC_COMM_WORLD
657: Input Parameter:
658: . ptr - the memory location
660: Output Parameter:
661: . stack - the stack indicating where the program allocated this memory
663: Level: intermediate
665: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView()
666: @*/
667: PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack)
668: {
669: TRSPACE *head;
672: head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
673: *stack = &head->stack;
674: return(0);
675: }
676: #else
677: PetscErrorCode PetscMallocGetStack(void *ptr,void **stack)
678: {
680: *stack = NULL;
681: return(0);
682: }
683: #endif
685: /*@C
686: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
687: printed is: size of space (in bytes), address of space, id of space,
688: file in which space was allocated, and line number at which it was
689: allocated.
691: Not Collective
693: Input Parameter:
694: . fp - file pointer. If fp is NULL, stdout is assumed.
696: Options Database Key:
697: . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
699: Level: intermediate
701: Fortran Note:
702: The calling sequence in Fortran is PetscMallocDump(integer ierr)
703: The fp defaults to stdout.
705: Notes:
706: Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
708: When called in PetscFinalize() dumps only the allocations that have not been properly freed
710: PetscMallocView() prints a list of all memory ever allocated
712: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
713: @*/
714: PetscErrorCode PetscMallocDump(FILE *fp)
715: {
716: TRSPACE *head;
717: size_t libAlloc = 0;
719: PetscMPIInt rank;
722: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
723: if (!fp) fp = PETSC_STDOUT;
724: head = TRhead;
725: while (head) {
726: libAlloc += TRrequestedSize ? head->rsize : head->size;
727: head = head->next;
728: }
729: if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
730: head = TRhead;
731: while (head) {
732: PetscBool isLib;
734: PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
735: if (!isLib) {
736: fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->lineno,head->filename);
737: #if defined(PETSC_USE_DEBUG)
738: PetscStackPrint(&head->stack,fp);
739: #endif
740: }
741: head = head->next;
742: }
743: return(0);
744: }
746: /*@
747: PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
749: Not Collective
751: Input Arguments:
752: . logmin - minimum allocation size to log, or PETSC_DEFAULT
754: Options Database Key:
755: + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
756: . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
757: - -log_view_memory - view the memory usage also with the -log_view option
759: Level: advanced
761: Notes: Must be called after PetscMallocSetDebug()
763: Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
765: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
766: @*/
767: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
768: {
772: PetscLogMalloc = 0;
773: PetscMemorySetGetMaximumUsage();
774: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
775: PetscLogMallocThreshold = (size_t)logmin;
776: return(0);
777: }
779: /*@
780: PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
782: Not Collective
784: Output Arguments
785: . logging - PETSC_TRUE if logging is active
787: Options Database Key:
788: . -malloc_view <optional filename> - Activates PetscMallocView()
790: Level: advanced
792: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
793: @*/
794: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
795: {
798: *logging = (PetscBool)(PetscLogMalloc >= 0);
799: return(0);
800: }
802: /*@
803: PetscMallocTraceSet - Trace all calls to PetscMalloc()
805: Not Collective
807: Input Arguments:
808: + viewer - The viewer to use for tracing, or NULL to use stdout
809: . active - Flag to activate or deactivate tracing
810: - logmin - The smallest memory size that will be logged
812: Note:
813: The viewer should not be collective.
815: Level: advanced
817: .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
818: @*/
819: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
820: {
824: if (!active) {PetscLogMallocTrace = -1; return(0);}
825: PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
826: PetscLogMallocTrace = 0;
827: PetscMemorySetGetMaximumUsage();
828: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
829: PetscLogMallocTraceThreshold = (size_t) logmin;
830: return(0);
831: }
833: /*@
834: PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
836: Not Collective
838: Output Argument:
839: . logging - PETSC_TRUE if logging is active
841: Options Database Key:
842: . -malloc_view <optional filename> - Activates PetscMallocView()
844: Level: advanced
846: .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
847: @*/
848: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
849: {
852: *logging = (PetscBool) (PetscLogMallocTrace >= 0);
853: return(0);
854: }
856: /*@C
857: PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
858: PetscMemoryGetMaximumUsage()
860: Not Collective
862: Input Parameter:
863: . fp - file pointer; or NULL
865: Options Database Key:
866: . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
868: Level: advanced
870: Fortran Note:
871: The calling sequence in Fortran is PetscMallocView(integer ierr)
872: The fp defaults to stdout.
874: Notes:
875: PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
877: PetscMemoryView() gives a brief summary of current memory usage
879: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
880: @*/
881: PetscErrorCode PetscMallocView(FILE *fp)
882: {
883: PetscInt i,j,n,*perm;
884: size_t *shortlength;
885: int *shortcount,err;
886: PetscMPIInt rank;
887: PetscBool match;
888: const char **shortfunction;
889: PetscLogDouble rss;
893: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
894: err = fflush(fp);
895: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
897: if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
899: if (!fp) fp = PETSC_STDOUT;
900: PetscMemoryGetMaximumUsage(&rss);
901: if (rss) {
902: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
903: } else {
904: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
905: }
906: shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
907: shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
908: shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
909: for (i=0,n=0; i<PetscLogMalloc; i++) {
910: for (j=0; j<n; j++) {
911: PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
912: if (match) {
913: shortlength[j] += PetscLogMallocLength[i];
914: shortcount[j]++;
915: goto foundit;
916: }
917: }
918: shortfunction[n] = PetscLogMallocFunction[i];
919: shortlength[n] = PetscLogMallocLength[i];
920: shortcount[n] = 1;
921: n++;
922: foundit:;
923: }
925: perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
926: for (i=0; i<n; i++) perm[i] = i;
927: PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);
929: (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
930: for (i=0; i<n; i++) {
931: (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
932: }
933: free(perm);
934: free(shortlength);
935: free(shortcount);
936: free((char**)shortfunction);
937: err = fflush(fp);
938: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
939: return(0);
940: }
942: /* ---------------------------------------------------------------------------- */
944: /*@
945: PetscMallocSetDebug - Set's PETSc memory debugging
947: Not Collective
949: Input Parameter:
950: + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
951: - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
953: Options Database:
954: + -malloc_debug <true or false> - turns on or off debugging
955: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
956: . -malloc_view_threshold t - log only allocations larger than t
957: . -malloc_dump <filename> - print a list of all memory that has not been freed
958: . -malloc no - (deprecated) same as -malloc_debug no
959: - -malloc_log - (deprecated) same as -malloc_view
961: Level: developer
963: Notes: This is called in PetscInitialize() and should not be called elsewhere
965: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
966: @*/
967: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
968: {
972: if (PetscTrMalloc == PetscTrMallocDefault) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call this routine more than once, it can only be called in PetscInitialize()");
973: PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);
975: TRallocated = 0;
976: TRfrags = 0;
977: TRhead = NULL;
978: TRid = 0;
979: TRdebugLevel = eachcall;
980: TRMaxMem = 0;
981: PetscLogMallocMax = 10000;
982: PetscLogMalloc = -1;
983: TRdebugIinitializenan = initializenan;
984: return(0);
985: }
987: /*@
988: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
990: Not Collective
992: Output Parameters:
993: + basic - doing basic debugging
994: . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
995: - initializenan - initializes memory with NaN
997: Level: intermediate
999: Notes:
1000: By default, the debug version always does some debugging unless you run with -malloc_debug no
1002: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
1003: @*/
1004: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
1005: {
1007: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
1008: if (eachcall) *eachcall = TRdebugLevel;
1009: if (initializenan) *initializenan = TRdebugIinitializenan;
1010: return(0);
1011: }
1013: /*@
1014: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1016: Not Collective
1018: Input Parameter:
1019: . flg - PETSC_TRUE to log the requested memory size
1021: Options Database:
1022: . -malloc_requested_size <bool> - Sets this flag
1024: Level: developer
1026: .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1027: @*/
1028: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1029: {
1031: TRrequestedSize = flg;
1032: return(0);
1033: }
1035: /*@
1036: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1038: Not Collective
1040: Output Parameter:
1041: . flg - PETSC_TRUE if we log the requested memory size
1043: Level: developer
1045: .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1046: @*/
1047: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1048: {
1050: *flg = TRrequestedSize;
1051: return(0);
1052: }