Actual source code: mtr.c
petsc-3.14.6 2021-03-30
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) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
126: return PETSC_ERR_MEMC;
127: }
128: a = (char*)(((TrSPACE*)head) + 1);
129: nend = (PetscClassId*)(a + head->size);
130: if (*nend != CLASSID_VALUE) {
131: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
132: if (*nend == ALREADY_FREED) {
133: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
134: return PETSC_ERR_MEMC;
135: } else {
136: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
137: (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
138: return PETSC_ERR_MEMC;
139: }
140: }
141: if (head->prev && head->prev != lasthead) {
142: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
143: (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
144: return PETSC_ERR_MEMC;
145: }
146: if (head->next && head != head->next->prev) {
147: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
148: (*PetscErrorPrintf)("Next memory header %p has invalid back pointer %p, should be %p\n",head->next,head->next->prev,head);
149: return PETSC_ERR_MEMC;
150: }
151: lasthead = head;
152: head = head->next;
153: }
154: return 0;
155: }
157: /*
158: PetscTrMallocDefault - Malloc with tracing.
160: Input Parameters:
161: + a - number of bytes to allocate
162: . lineno - line number where used. Use __LINE__ for this
163: - filename - file name where used. Use __FILE__ for this
165: Returns:
166: double aligned pointer to requested storage, or null if not available.
167: */
168: PetscErrorCode PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
169: {
170: TRSPACE *head;
171: char *inew;
172: 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) PetscFunctionReturn(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: if (PetscStackActive()) {
213: PetscStackCopy(petscstack,&head->stack);
215: head->stack.line[head->stack.currentsize-2] = lineno;
216: } else {
217: head->stack.currentsize = 0;
218: }
219: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
220: if (!clear && TRdebugIinitializenan) {
221: size_t i, n = a/sizeof(PetscReal);
222: PetscReal *s = (PetscReal*) inew;
223: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
224: #if defined(PETSC_USE_REAL_SINGLE)
225: int nas = 0x7F800002;
226: #else
227: PetscInt64 nas = 0x7FF0000000000002;
228: #endif
229: for (i=0; i<n; i++) {
230: memcpy(s+i,&nas,sizeof(PetscReal));
231: }
232: }
233: #endif
234: #endif
236: /*
237: Allow logging of all mallocs made.
238: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
239: */
240: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
241: if (!PetscLogMalloc) {
242: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
243: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
245: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
246: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
248: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
249: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
250: }
251: PetscLogMallocLength[PetscLogMalloc] = nsize;
252: PetscLogMallocFile[PetscLogMalloc] = filename;
253: PetscLogMallocFunction[PetscLogMalloc++] = function;
254: }
255: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
256: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");
257: }
258: *result = (void*)inew;
259: return(0);
260: }
262: /*
263: PetscTrFreeDefault - Free with tracing.
265: Input Parameters:
266: . a - pointer to a block allocated with PetscTrMalloc
267: . lineno - line number where used. Use __LINE__ for this
268: . filename - file name where used. Use __FILE__ for this
269: */
270: PetscErrorCode PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
271: {
272: char *a = (char*)aa;
273: TRSPACE *head;
274: char *ahead;
275: size_t asize;
277: PetscClassId *nend;
280: /* Do not try to handle empty blocks */
281: if (!a) return(0);
283: PetscMallocValidate(lineno,function,filename);
285: ahead = a;
286: a = a - sizeof(TrSPACE);
287: head = (TRSPACE*)a;
289: if (head->classid != CLASSID_VALUE) {
290: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
291: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
292: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
293: }
294: nend = (PetscClassId*)(ahead + head->size);
295: if (*nend != CLASSID_VALUE) {
296: if (*nend == ALREADY_FREED) {
297: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
298: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
299: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
300: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
301: } else {
302: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
303: }
304: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
305: } else {
306: /* Damaged tail */
307: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
308: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
309: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
310: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
311: }
312: }
313: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
314: PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");
315: }
316: /* Mark the location freed */
317: *nend = ALREADY_FREED;
318: /* Save location where freed. If we suspect the line number, mark as allocated location */
319: if (lineno > 0 && lineno < 50000) {
320: head->lineno = lineno;
321: head->filename = filename;
322: head->functionname = function;
323: } else {
324: head->lineno = -head->lineno;
325: }
326: asize = TRrequestedSize ? head->rsize : head->size;
327: if (TRallocated < asize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
328: TRallocated -= asize;
329: TRfrags--;
330: if (head->prev) head->prev->next = head->next;
331: else TRhead = head->next;
333: if (head->next) head->next->prev = head->prev;
334: PetscFreeAlign(a,lineno,function,filename);
335: return(0);
336: }
338: /*
339: PetscTrReallocDefault - Realloc with tracing.
341: Input Parameters:
342: + len - number of bytes to allocate
343: . lineno - line number where used. Use __LINE__ for this
344: . filename - file name where used. Use __FILE__ for this
345: - result - original memory
347: Output Parameter:
348: . result - double aligned pointer to requested storage, or null if not available.
350: Level: developer
352: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
353: */
354: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
355: {
356: char *a = (char *) *result;
357: TRSPACE *head;
358: char *ahead, *inew;
359: PetscClassId *nend;
360: size_t nsize;
364: /* Realloc requests zero space so just free the current space */
365: if (!len) {
366: PetscTrFreeDefault(*result,lineno,function,filename);
367: *result = NULL;
368: return(0);
369: }
370: /* If the orginal space was NULL just use the regular malloc() */
371: if (!*result) {
372: PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
373: return(0);
374: }
376: PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
378: ahead = a;
379: a = a - sizeof(TrSPACE);
380: head = (TRSPACE *) a;
381: inew = a;
383: if (head->classid != CLASSID_VALUE) {
384: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
385: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
386: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
387: }
388: nend = (PetscClassId *)(ahead + head->size);
389: if (*nend != CLASSID_VALUE) {
390: if (*nend == ALREADY_FREED) {
391: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
392: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
393: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
394: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
395: } else {
396: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
397: }
398: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
399: } else {
400: /* Damaged tail */
401: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
402: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
403: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
404: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
405: }
406: }
408: /* remove original reference to the memory allocated from the PETSc debugging heap */
409: TRallocated -= TRrequestedSize ? head->rsize : head->size;
410: TRfrags--;
411: if (head->prev) head->prev->next = head->next;
412: else TRhead = head->next;
413: if (head->next) head->next->prev = head->prev;
415: nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
416: PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);
418: head = (TRSPACE*)inew;
419: inew += sizeof(TrSPACE);
421: if (TRhead) TRhead->prev = head;
422: head->next = TRhead;
423: TRhead = head;
424: head->prev = NULL;
425: head->size = nsize;
426: head->rsize = len;
427: head->id = TRid;
428: head->lineno = lineno;
430: head->filename = filename;
431: head->functionname = function;
432: head->classid = CLASSID_VALUE;
433: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
435: TRallocated += TRrequestedSize ? head->rsize : head->size;
436: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
437: if (PetscLogMemory) {
438: PetscInt i;
439: for (i=0; i<NumTRMaxMems; i++) {
440: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
441: }
442: }
443: TRfrags++;
445: #if defined(PETSC_USE_DEBUG)
446: if (PetscStackActive()) {
447: PetscStackCopy(petscstack,&head->stack);
449: head->stack.line[head->stack.currentsize-2] = lineno;
450: } else {
451: head->stack.currentsize = 0;
452: }
453: #endif
455: /*
456: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
457: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
458: */
459: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
460: if (!PetscLogMalloc) {
461: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
462: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
464: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
465: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
467: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
468: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
469: }
470: PetscLogMallocLength[PetscLogMalloc] = nsize;
471: PetscLogMallocFile[PetscLogMalloc] = filename;
472: PetscLogMallocFunction[PetscLogMalloc++] = function;
473: }
474: *result = (void*)inew;
475: return(0);
476: }
478: /*@C
479: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
481: Collective on PetscViewer
483: Input Parameter:
484: + viewer - the viewer that defines the communicator
485: - message - string printed before values
487: Options Database:
488: + -malloc_debug - have PETSc track how much memory it has allocated
489: - -memory_view - during PetscFinalize() have this routine called
491: Level: intermediate
493: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
494: @*/
495: PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[])
496: {
497: PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
498: PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
500: MPI_Comm comm;
503: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
504: PetscMallocGetCurrentUsage(&allocated);
505: PetscMallocGetMaximumUsage(&allocatedmax);
506: PetscMemoryGetCurrentUsage(&resident);
507: PetscMemoryGetMaximumUsage(&residentmax);
508: if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
509: PetscObjectGetComm((PetscObject)viewer,&comm);
510: PetscViewerASCIIPrintf(viewer,message);
511: if (resident && residentmax && allocated) {
512: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
513: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
514: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
515: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
516: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
517: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
518: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
519: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
520: MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
521: MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
522: MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
523: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);
524: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
525: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
526: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
527: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
528: } else if (resident && residentmax) {
529: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
530: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
531: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
532: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
533: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
534: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
535: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
536: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
537: } else if (resident && allocated) {
538: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
539: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
540: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
541: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
542: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
543: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
544: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
545: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
546: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
547: } else if (allocated) {
548: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
549: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
550: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
551: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
552: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
553: PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");
554: } else {
555: PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
556: }
557: PetscViewerFlush(viewer);
558: return(0);
559: }
561: /*@
562: PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
564: Not Collective
566: Output Parameters:
567: . space - number of bytes currently allocated
569: Level: intermediate
571: .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
572: PetscMemoryGetMaximumUsage()
573: @*/
574: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
575: {
577: *space = (PetscLogDouble) TRallocated;
578: return(0);
579: }
581: /*@
582: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
583: during this run.
585: Not Collective
587: Output Parameters:
588: . space - maximum number of bytes ever allocated at one time
590: Level: intermediate
592: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
593: PetscMallocPushMaximumUsage()
594: @*/
595: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
596: {
598: *space = (PetscLogDouble) TRMaxMem;
599: return(0);
600: }
602: /*@
603: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
605: Not Collective
607: Input Parameter:
608: . event - an event id; this is just for error checking
610: Level: developer
612: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
613: PetscMallocPopMaximumUsage()
614: @*/
615: PetscErrorCode PetscMallocPushMaximumUsage(int event)
616: {
618: if (++NumTRMaxMems > MAXTRMAXMEMS) return(0);
619: TRMaxMems[NumTRMaxMems-1] = TRallocated;
620: TRMaxMemsEvents[NumTRMaxMems-1] = event;
621: return(0);
622: }
624: /*@
625: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
627: Not Collective
629: Input Parameter:
630: . event - an event id; this is just for error checking
632: Output Parameter:
633: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
635: Level: developer
637: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
638: PetscMallocPushMaximumUsage()
639: @*/
640: PetscErrorCode PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
641: {
643: *mu = 0;
644: if (NumTRMaxMems-- > MAXTRMAXMEMS) return(0);
645: if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
646: *mu = TRMaxMems[NumTRMaxMems];
647: return(0);
648: }
650: #if defined(PETSC_USE_DEBUG)
651: /*@C
652: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
654: Collective on PETSC_COMM_WORLD
656: Input Parameter:
657: . ptr - the memory location
659: Output Parameter:
660: . stack - the stack indicating where the program allocated this memory
662: Level: intermediate
664: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView()
665: @*/
666: PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack)
667: {
668: TRSPACE *head;
671: head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
672: *stack = &head->stack;
673: return(0);
674: }
675: #else
676: PetscErrorCode PetscMallocGetStack(void *ptr,void **stack)
677: {
679: *stack = NULL;
680: return(0);
681: }
682: #endif
684: /*@C
685: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
686: printed is: size of space (in bytes), address of space, id of space,
687: file in which space was allocated, and line number at which it was
688: allocated.
690: Not Collective
692: Input Parameter:
693: . fp - file pointer. If fp is NULL, stdout is assumed.
695: Options Database Key:
696: . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
698: Level: intermediate
700: Fortran Note:
701: The calling sequence in Fortran is PetscMallocDump(integer ierr)
702: The fp defaults to stdout.
704: Notes:
705: Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
707: When called in PetscFinalize() dumps only the allocations that have not been properly freed
709: PetscMallocView() prints a list of all memory ever allocated
711: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
712: @*/
713: PetscErrorCode PetscMallocDump(FILE *fp)
714: {
715: TRSPACE *head;
716: size_t libAlloc = 0;
718: PetscMPIInt rank;
721: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
722: if (!fp) fp = PETSC_STDOUT;
723: head = TRhead;
724: while (head) {
725: libAlloc += TRrequestedSize ? head->rsize : head->size;
726: head = head->next;
727: }
728: if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
729: head = TRhead;
730: while (head) {
731: PetscBool isLib;
733: PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
734: if (!isLib) {
735: fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->lineno,head->filename);
736: #if defined(PETSC_USE_DEBUG)
737: PetscStackPrint(&head->stack,fp);
738: #endif
739: }
740: head = head->next;
741: }
742: return(0);
743: }
745: /*@
746: PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
748: Not Collective
750: Input Arguments:
751: . logmin - minimum allocation size to log, or PETSC_DEFAULT
753: Options Database Key:
754: + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
755: . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
756: - -log_view_memory - view the memory usage also with the -log_view option
758: Level: advanced
760: Notes: Must be called after PetscMallocSetDebug()
762: Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
764: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
765: @*/
766: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
767: {
771: PetscLogMalloc = 0;
772: PetscMemorySetGetMaximumUsage();
773: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
774: PetscLogMallocThreshold = (size_t)logmin;
775: return(0);
776: }
778: /*@
779: PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
781: Not Collective
783: Output Arguments
784: . logging - PETSC_TRUE if logging is active
786: Options Database Key:
787: . -malloc_view <optional filename> - Activates PetscMallocView()
789: Level: advanced
791: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
792: @*/
793: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
794: {
797: *logging = (PetscBool)(PetscLogMalloc >= 0);
798: return(0);
799: }
801: /*@
802: PetscMallocTraceSet - Trace all calls to PetscMalloc()
804: Not Collective
806: Input Arguments:
807: + viewer - The viewer to use for tracing, or NULL to use stdout
808: . active - Flag to activate or deactivate tracing
809: - logmin - The smallest memory size that will be logged
811: Note:
812: The viewer should not be collective.
814: Level: advanced
816: .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
817: @*/
818: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
819: {
823: if (!active) {PetscLogMallocTrace = -1; return(0);}
824: PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
825: PetscLogMallocTrace = 0;
826: PetscMemorySetGetMaximumUsage();
827: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
828: PetscLogMallocTraceThreshold = (size_t) logmin;
829: return(0);
830: }
832: /*@
833: PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
835: Not Collective
837: Output Argument:
838: . logging - PETSC_TRUE if logging is active
840: Options Database Key:
841: . -malloc_view <optional filename> - Activates PetscMallocView()
843: Level: advanced
845: .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
846: @*/
847: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
848: {
851: *logging = (PetscBool) (PetscLogMallocTrace >= 0);
852: return(0);
853: }
855: /*@C
856: PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
857: PetscMemoryGetMaximumUsage()
859: Not Collective
861: Input Parameter:
862: . fp - file pointer; or NULL
864: Options Database Key:
865: . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
867: Level: advanced
869: Fortran Note:
870: The calling sequence in Fortran is PetscMallocView(integer ierr)
871: The fp defaults to stdout.
873: Notes:
874: PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
876: PetscMemoryView() gives a brief summary of current memory usage
878: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
879: @*/
880: PetscErrorCode PetscMallocView(FILE *fp)
881: {
882: PetscInt i,j,n,*perm;
883: size_t *shortlength;
884: int *shortcount,err;
885: PetscMPIInt rank;
886: PetscBool match;
887: const char **shortfunction;
888: PetscLogDouble rss;
892: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
893: err = fflush(fp);
894: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
896: 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()");
898: if (!fp) fp = PETSC_STDOUT;
899: PetscMemoryGetMaximumUsage(&rss);
900: if (rss) {
901: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
902: } else {
903: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
904: }
905: shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
906: shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
907: shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
908: for (i=0,n=0; i<PetscLogMalloc; i++) {
909: for (j=0; j<n; j++) {
910: PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
911: if (match) {
912: shortlength[j] += PetscLogMallocLength[i];
913: shortcount[j]++;
914: goto foundit;
915: }
916: }
917: shortfunction[n] = PetscLogMallocFunction[i];
918: shortlength[n] = PetscLogMallocLength[i];
919: shortcount[n] = 1;
920: n++;
921: foundit:;
922: }
924: perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
925: for (i=0; i<n; i++) perm[i] = i;
926: PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);
928: (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
929: for (i=0; i<n; i++) {
930: (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
931: }
932: free(perm);
933: free(shortlength);
934: free(shortcount);
935: free((char**)shortfunction);
936: err = fflush(fp);
937: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
938: return(0);
939: }
941: /* ---------------------------------------------------------------------------- */
943: /*@
944: PetscMallocSetDebug - Set's PETSc memory debugging
946: Not Collective
948: Input Parameter:
949: + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
950: - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
952: Options Database:
953: + -malloc_debug <true or false> - turns on or off debugging
954: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
955: . -malloc_view_threshold t - log only allocations larger than t
956: . -malloc_dump <filename> - print a list of all memory that has not been freed
957: . -malloc no - (deprecated) same as -malloc_debug no
958: - -malloc_log - (deprecated) same as -malloc_view
960: Level: developer
962: Notes: This is called in PetscInitialize() and should not be called elsewhere
964: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
965: @*/
966: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
967: {
971: 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()");
972: PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);
974: TRallocated = 0;
975: TRfrags = 0;
976: TRhead = NULL;
977: TRid = 0;
978: TRdebugLevel = eachcall;
979: TRMaxMem = 0;
980: PetscLogMallocMax = 10000;
981: PetscLogMalloc = -1;
982: TRdebugIinitializenan = initializenan;
983: return(0);
984: }
986: /*@
987: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
989: Not Collective
991: Output Parameters:
992: + basic - doing basic debugging
993: . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
994: - initializenan - initializes memory with NaN
996: Level: intermediate
998: Notes:
999: By default, the debug version always does some debugging unless you run with -malloc_debug no
1001: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
1002: @*/
1003: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
1004: {
1006: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
1007: if (eachcall) *eachcall = TRdebugLevel;
1008: if (initializenan) *initializenan = TRdebugIinitializenan;
1009: return(0);
1010: }
1012: /*@
1013: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1015: Not Collective
1017: Input Parameter:
1018: . flg - PETSC_TRUE to log the requested memory size
1020: Options Database:
1021: . -malloc_requested_size <bool> - Sets this flag
1023: Level: developer
1025: .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1026: @*/
1027: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1028: {
1030: TRrequestedSize = flg;
1031: return(0);
1032: }
1034: /*@
1035: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1037: Not Collective
1039: Output Parameter:
1040: . flg - PETSC_TRUE if we log the requested memory size
1042: Level: developer
1044: .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1045: @*/
1046: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1047: {
1049: *flg = TRrequestedSize;
1050: return(0);
1051: }