Actual source code: mtr.c
petsc-3.12.3 2020-01-03
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;
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 TRdebugIintializenan = PETSC_FALSE;
55: static size_t TRMaxMem = 0;
56: static int NumTRMaxMems = 0;
57: static size_t TRMaxMems[MAXTRMAXMEMS];
58: static int TRMaxMemsEvents[MAXTRMAXMEMS];
59: /*
60: Arrays to log information on mallocs for PetscMallocView()
61: */
62: static int PetscLogMallocMax = 10000;
63: static int PetscLogMalloc = -1;
64: static size_t PetscLogMallocThreshold = 0;
65: static size_t *PetscLogMallocLength;
66: static const char **PetscLogMallocFile,**PetscLogMallocFunction;
68: /*@C
69: PetscMallocValidate - Test the memory for corruption. This can be called at any time between PetscInitialize() and PetscFinalize()
71: Input Parameters:
72: + line - line number where call originated.
73: . function - name of function calling
74: - file - file where function is
76: Return value:
77: The number of errors detected.
79: Options Database:.
80: + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
81: - -malloc_debug - turns this feature on anytime
83: Output Effect:
84: Error messages are written to stdout.
86: Level: advanced
88: Notes:
89: 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)
91: You should generally use CHKMEMQ as a short cut for calling this routine.
93: The Fortran calling sequence is simply PetscMallocValidate(ierr)
95: No output is generated if there are no problems detected.
97: Developers Note:
98: Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run
100: .seealso: CHKMEMQ
102: @*/
103: PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[])
104: {
105: TRSPACE *head,*lasthead;
106: char *a;
107: PetscClassId *nend;
109: if (!TRdebugLevel) return 0;
111: head = TRhead; lasthead = NULL;
112: while (head) {
113: if (head->classid != CLASSID_VALUE) {
114: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
115: (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
116: (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
117: if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
118: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
119: }
120: a = (char*)(((TrSPACE*)head) + 1);
121: nend = (PetscClassId*)(a + head->size);
122: if (*nend != CLASSID_VALUE) {
123: (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
124: if (*nend == ALREADY_FREED) {
125: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
126: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
127: } else {
128: (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
129: (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
130: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
131: }
132: }
133: lasthead = head;
134: head = head->next;
135: }
136: return(0);
137: }
139: /*
140: PetscTrMallocDefault - Malloc with tracing.
142: Input Parameters:
143: + a - number of bytes to allocate
144: . lineno - line number where used. Use __LINE__ for this
145: - filename - file name where used. Use __FILE__ for this
147: Returns:
148: double aligned pointer to requested storage, or null if not available.
149: */
150: PetscErrorCode PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
151: {
152: TRSPACE *head;
153: char *inew;
154: size_t nsize;
158: /* Do not try to handle empty blocks */
159: if (!a) { *result = NULL; return(0); }
161: PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
163: nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
164: PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);
166: head = (TRSPACE*)inew;
167: inew += sizeof(TrSPACE);
169: if (TRhead) TRhead->prev = head;
170: head->next = TRhead;
171: TRhead = head;
172: head->prev = NULL;
173: head->size = nsize;
174: head->id = TRid;
175: head->lineno = lineno;
177: head->filename = filename;
178: head->functionname = function;
179: head->classid = CLASSID_VALUE;
180: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
182: TRallocated += nsize;
183: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
184: if (PetscLogMemory) {
185: PetscInt i;
186: for (i=0; i<NumTRMaxMems; i++) {
187: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
188: }
189: }
190: TRfrags++;
192: #if defined(PETSC_USE_DEBUG)
193: if (PetscStackActive()) {
194: PetscStackCopy(petscstack,&head->stack);
196: head->stack.line[head->stack.currentsize-2] = lineno;
197: } else {
198: head->stack.currentsize = 0;
199: }
200: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
201: if (!clear && TRdebugIintializenan) {
202: size_t i, n = a/sizeof(PetscReal);
203: PetscReal *s = (PetscReal*) inew;
204: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
205: #if defined(PETSC_USE_REAL_SINGLE)
206: int nas = 0x7F800002;
207: #else
208: PetscInt64 nas = 0x7FF0000000000002;
209: #endif
210: for (i=0; i<n; i++) {
211: memcpy(s+i,&nas,sizeof(PetscReal));
212: }
213: }
214: #endif
215: #endif
217: /*
218: Allow logging of all mallocs made.
219: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
220: */
221: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
222: if (!PetscLogMalloc) {
223: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
224: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
226: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
227: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
229: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
230: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
231: }
232: PetscLogMallocLength[PetscLogMalloc] = nsize;
233: PetscLogMallocFile[PetscLogMalloc] = filename;
234: PetscLogMallocFunction[PetscLogMalloc++] = function;
235: }
236: *result = (void*)inew;
237: return(0);
238: }
240: /*
241: PetscTrFreeDefault - Free with tracing.
243: Input Parameters:
244: . a - pointer to a block allocated with PetscTrMalloc
245: . lineno - line number where used. Use __LINE__ for this
246: . file - file name where used. Use __FILE__ for this
247: */
248: PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
249: {
250: char *a = (char*)aa;
251: TRSPACE *head;
252: char *ahead;
254: PetscClassId *nend;
257: /* Do not try to handle empty blocks */
258: if (!a) return(0);
260: PetscMallocValidate(line,function,file);
262: ahead = a;
263: a = a - sizeof(TrSPACE);
264: head = (TRSPACE*)a;
266: if (head->classid != CLASSID_VALUE) {
267: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
268: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
269: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
270: }
271: nend = (PetscClassId*)(ahead + head->size);
272: if (*nend != CLASSID_VALUE) {
273: if (*nend == ALREADY_FREED) {
274: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
275: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
276: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
277: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
278: } else {
279: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
280: }
281: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
282: } else {
283: /* Damaged tail */
284: (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
285: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
286: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
287: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
288: }
289: }
290: /* Mark the location freed */
291: *nend = ALREADY_FREED;
292: /* Save location where freed. If we suspect the line number, mark as allocated location */
293: if (line > 0 && line < 50000) {
294: head->lineno = line;
295: head->filename = file;
296: head->functionname = function;
297: } else {
298: head->lineno = -head->lineno;
299: }
300: if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
301: TRallocated -= head->size;
302: TRfrags--;
303: if (head->prev) head->prev->next = head->next;
304: else TRhead = head->next;
306: if (head->next) head->next->prev = head->prev;
307: PetscFreeAlign(a,line,function,file);
308: return(0);
309: }
311: /*
312: PetscTrReallocDefault - Realloc with tracing.
314: Input Parameters:
315: + len - number of bytes to allocate
316: . lineno - line number where used. Use __LINE__ for this
317: . filename - file name where used. Use __FILE__ for this
318: - result - original memory
320: Output Parameter:
321: . result - double aligned pointer to requested storage, or null if not available.
323: Level: developer
325: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
326: */
327: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
328: {
329: char *a = (char *) *result;
330: TRSPACE *head;
331: char *ahead, *inew;
332: PetscClassId *nend;
333: size_t nsize;
337: /* Realloc requests zero space so just free the current space */
338: if (!len) {
339: PetscTrFreeDefault(*result,lineno,function,filename);
340: *result = NULL;
341: return(0);
342: }
343: /* If the orginal space was NULL just use the regular malloc() */
344: if (!*result) {
345: PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
346: return(0);
347: }
349: PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
351: ahead = a;
352: a = a - sizeof(TrSPACE);
353: head = (TRSPACE *) a;
354: inew = a;
356: if (head->classid != CLASSID_VALUE) {
357: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
358: (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
359: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
360: }
361: nend = (PetscClassId *)(ahead + head->size);
362: if (*nend != CLASSID_VALUE) {
363: if (*nend == ALREADY_FREED) {
364: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
365: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
366: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
367: (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
368: } else {
369: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
370: }
371: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
372: } else {
373: /* Damaged tail */
374: (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
375: (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
376: (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
377: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
378: }
379: }
381: /* remove original reference to the memory allocated from the PETSc debugging heap */
382: TRallocated -= head->size;
383: TRfrags--;
384: if (head->prev) head->prev->next = head->next;
385: else TRhead = head->next;
386: if (head->next) head->next->prev = head->prev;
388: nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
389: PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);
391: head = (TRSPACE*)inew;
392: inew += sizeof(TrSPACE);
394: if (TRhead) TRhead->prev = head;
395: head->next = TRhead;
396: TRhead = head;
397: head->prev = NULL;
398: head->size = nsize;
399: head->id = TRid;
400: head->lineno = lineno;
402: head->filename = filename;
403: head->functionname = function;
404: head->classid = CLASSID_VALUE;
405: *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
407: TRallocated += nsize;
408: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
409: if (PetscLogMemory) {
410: PetscInt i;
411: for (i=0; i<NumTRMaxMems; i++) {
412: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
413: }
414: }
415: TRfrags++;
417: #if defined(PETSC_USE_DEBUG)
418: if (PetscStackActive()) {
419: PetscStackCopy(petscstack,&head->stack);
421: head->stack.line[head->stack.currentsize-2] = lineno;
422: } else {
423: head->stack.currentsize = 0;
424: }
425: #endif
427: /*
428: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
429: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
430: */
431: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
432: if (!PetscLogMalloc) {
433: PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
434: if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
436: PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
437: if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
439: PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
440: if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
441: }
442: PetscLogMallocLength[PetscLogMalloc] = nsize;
443: PetscLogMallocFile[PetscLogMalloc] = filename;
444: PetscLogMallocFunction[PetscLogMalloc++] = function;
445: }
446: *result = (void*)inew;
447: return(0);
448: }
450: /*@C
451: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
453: Collective on PetscViewer
455: Input Parameter:
456: + viewer - the viewer that defines the communicator
457: - message - string printed before values
459: Options Database:
460: + -malloc_debug - have PETSc track how much memory it has allocated
461: - -memory_view - during PetscFinalize() have this routine called
463: Level: intermediate
465: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
466: @*/
467: PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[])
468: {
469: PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
470: PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
472: MPI_Comm comm;
475: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
476: PetscMallocGetCurrentUsage(&allocated);
477: PetscMallocGetMaximumUsage(&allocatedmax);
478: PetscMemoryGetCurrentUsage(&resident);
479: PetscMemoryGetMaximumUsage(&residentmax);
480: if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
481: PetscObjectGetComm((PetscObject)viewer,&comm);
482: PetscViewerASCIIPrintf(viewer,message);
483: if (resident && residentmax && allocated) {
484: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
485: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
486: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
487: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
488: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
489: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
490: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
491: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
492: MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
493: MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
494: MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
495: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);
496: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
497: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
498: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
499: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
500: } else if (resident && residentmax) {
501: MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
502: MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
503: MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
504: PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
505: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
506: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
507: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
508: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
509: } else if (resident && allocated) {
510: MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
511: MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
512: MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
513: PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
514: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
515: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
516: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
517: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
518: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
519: } else if (allocated) {
520: MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
521: MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
522: MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
523: PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
524: PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
525: PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");
526: } else {
527: PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
528: }
529: PetscViewerFlush(viewer);
530: return(0);
531: }
533: /*@
534: PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
536: Not Collective
538: Output Parameters:
539: . space - number of bytes currently allocated
541: Level: intermediate
543: .seealso: PetscMallocDump(), PetscMallocLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
544: PetscMemoryGetMaximumUsage()
545: @*/
546: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
547: {
549: *space = (PetscLogDouble) TRallocated;
550: return(0);
551: }
553: /*@
554: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
555: during this run.
557: Not Collective
559: Output Parameters:
560: . space - maximum number of bytes ever allocated at one time
562: Level: intermediate
564: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
565: PetscMallocPushMaximumUsage()
566: @*/
567: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
568: {
570: *space = (PetscLogDouble) TRMaxMem;
571: return(0);
572: }
574: /*@
575: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
577: Not Collective
579: Input Parameter:
580: . event - an event id; this is just for error checking
582: Level: developer
584: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
585: PetscMallocPopMaximumUsage()
586: @*/
587: PetscErrorCode PetscMallocPushMaximumUsage(int event)
588: {
590: if (++NumTRMaxMems > MAXTRMAXMEMS) return(0);
591: TRMaxMems[NumTRMaxMems-1] = TRallocated;
592: TRMaxMemsEvents[NumTRMaxMems-1] = event;
593: return(0);
594: }
596: /*@
597: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
599: Not Collective
601: Input Parameter:
602: . event - an event id; this is just for error checking
604: Output Parameter:
605: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
607: Level: developer
609: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
610: PetscMallocPushMaximumUsage()
611: @*/
612: PetscErrorCode PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
613: {
615: *mu = 0;
616: if (NumTRMaxMems-- > MAXTRMAXMEMS) return(0);
617: if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
618: *mu = TRMaxMems[NumTRMaxMems];
619: return(0);
620: }
622: #if defined(PETSC_USE_DEBUG)
623: /*@C
624: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
626: Collective on PETSC_COMM_WORLD
628: Input Parameter:
629: . ptr - the memory location
631: Output Paramter:
632: . stack - the stack indicating where the program allocated this memory
634: Level: intermediate
636: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView()
637: @*/
638: PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack)
639: {
640: TRSPACE *head;
643: head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
644: *stack = &head->stack;
645: return(0);
646: }
647: #else
648: PetscErrorCode PetscMallocGetStack(void *ptr,void **stack)
649: {
651: *stack = NULL;
652: return(0);
653: }
654: #endif
656: /*@C
657: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
658: printed is: size of space (in bytes), address of space, id of space,
659: file in which space was allocated, and line number at which it was
660: allocated.
662: Not Collective
664: Input Parameter:
665: . fp - file pointer. If fp is NULL, stdout is assumed.
667: Options Database Key:
668: . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
670: Level: intermediate
672: Fortran Note:
673: The calling sequence in Fortran is PetscMallocDump(integer ierr)
674: The fp defaults to stdout.
676: Notes:
677: Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
679: When called in PetscFinalize() dumps only the allocations that have not been properly freed
681: PetscMallocView() prints a list of all memory ever allocated
683: .seealso: PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet()
684: @*/
685: PetscErrorCode PetscMallocDump(FILE *fp)
686: {
687: TRSPACE *head;
688: size_t libAlloc = 0;
690: PetscMPIInt rank;
693: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
694: if (!fp) fp = PETSC_STDOUT;
695: head = TRhead;
696: while (head) {
697: libAlloc += head->size;
698: head = head->next;
699: }
700: if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
701: head = TRhead;
702: while (head) {
703: PetscBool isLib;
705: PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
706: if (!isLib) {
707: fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
708: #if defined(PETSC_USE_DEBUG)
709: PetscStackPrint(&head->stack,fp);
710: #endif
711: }
712: head = head->next;
713: }
714: return(0);
715: }
717: /*@
718: PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
720: Not Collective
722: Input Arguments:
723: . logmin - minimum allocation size to log, or PETSC_DEFAULT
725: Options Database Key:
726: + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
727: - -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
729: Level: advanced
731: Notes: Must be called after PetscMallocSetDebug()
733: Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
735: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet()
736: @*/
737: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
738: {
742: PetscLogMalloc = 0;
743: PetscMemorySetGetMaximumUsage();
744: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
745: PetscLogMallocThreshold = (size_t)logmin;
746: return(0);
747: }
749: /*@
750: PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
752: Not Collective
754: Output Arguments
755: . logging - PETSC_TRUE if logging is active
757: Options Database Key:
758: . -malloc_view <optional filename> - Activates PetscMallocView()
760: Level: advanced
762: .seealso: PetscMallocDump(), PetscMallocView()
763: @*/
764: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
765: {
768: *logging = (PetscBool)(PetscLogMalloc >= 0);
769: return(0);
770: }
772: /*@C
773: PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
774: PetscMemoryGetMaximumUsage()
776: Not Collective
778: Input Parameter:
779: . fp - file pointer; or NULL
781: Options Database Key:
782: . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
784: Level: advanced
786: Fortran Note:
787: The calling sequence in Fortran is PetscMallocView(integer ierr)
788: The fp defaults to stdout.
790: Notes:
791: PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
793: PetscMemoryView() gives a brief summary of current memory usage
795: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
796: @*/
797: PetscErrorCode PetscMallocView(FILE *fp)
798: {
799: PetscInt i,j,n,*perm;
800: size_t *shortlength;
801: int *shortcount,err;
802: PetscMPIInt rank;
803: PetscBool match;
804: const char **shortfunction;
805: PetscLogDouble rss;
809: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
810: err = fflush(fp);
811: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
813: 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()");
815: if (!fp) fp = PETSC_STDOUT;
816: PetscMemoryGetMaximumUsage(&rss);
817: if (rss) {
818: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
819: } else {
820: (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
821: }
822: shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
823: shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
824: shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
825: for (i=0,n=0; i<PetscLogMalloc; i++) {
826: for (j=0; j<n; j++) {
827: PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
828: if (match) {
829: shortlength[j] += PetscLogMallocLength[i];
830: shortcount[j]++;
831: goto foundit;
832: }
833: }
834: shortfunction[n] = PetscLogMallocFunction[i];
835: shortlength[n] = PetscLogMallocLength[i];
836: shortcount[n] = 1;
837: n++;
838: foundit:;
839: }
841: perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
842: for (i=0; i<n; i++) perm[i] = i;
843: PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);
845: (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
846: for (i=0; i<n; i++) {
847: (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
848: }
849: free(perm);
850: free(shortlength);
851: free(shortcount);
852: free((char**)shortfunction);
853: err = fflush(fp);
854: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
855: return(0);
856: }
858: /* ---------------------------------------------------------------------------- */
860: /*@
861: PetscMallocSetDebug - Set's PETSc memory debugging
863: Not Collective
865: Input Parameter:
866: + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
867: - intializenan - initializes all memory with NaN to catch use of unintialized floating point arrays
869: Options Database:
870: + -malloc_debug <true or false> - turns on or off debugging
871: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
872: . -malloc_view_threshold t - log only allocations larger than t
873: . -malloc_dump <filename> - print a list of all memory that has not been freed
874: . -malloc no - (deprecated) same as -malloc_debug no
875: - -malloc_log - (deprecated) same as -malloc_view
877: Level: developer
879: Notes: This is called in PetscInitialize() and should not be called elsewhere
881: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
882: @*/
883: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
884: {
888: 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()");
889: PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);
891: TRallocated = 0;
892: TRfrags = 0;
893: TRhead = NULL;
894: TRid = 0;
895: TRdebugLevel = eachcall;
896: TRMaxMem = 0;
897: PetscLogMallocMax = 10000;
898: PetscLogMalloc = -1;
899: TRdebugIintializenan = initializenan;
900: return(0);
901: }
903: /*@
904: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
906: Not Collective
908: Output Parameters:
909: + basic - doing basic debugging
910: . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
911: - initializenan - initializes memory with NaN
913: Level: intermediate
915: Notes:
916: By default, the debug version always does some debugging unless you run with -malloc_debug no
918: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
919: @*/
920: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
921: {
923: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
924: if (eachcall) *eachcall = TRdebugLevel;
925: if (initializenan) *initializenan = TRdebugIintializenan;
926: return(0);
927: }