Actual source code: mtr.c
1: /*
2: Logging of memory usage and some error checking
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
6: #if defined(PETSC_HAVE_MALLOC_H)
7: #include <malloc.h>
8: #endif
10: /*
11: These are defined in mal.c and ensure that malloced space is PetscScalar aligned
12: */
13: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
14: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
15: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
17: #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
18: #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
20: /* this is the header put at the beginning of each PetscTrMallocDefault() for tracking allocated space and checking of allocated space heap */
21: typedef struct _trSPACE {
22: size_t size, rsize; /* Aligned size and requested size */
23: int id;
24: int lineno;
25: const char *filename;
26: const char *functionname;
27: PetscClassId classid;
28: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
29: PetscStack stack;
30: #endif
31: struct _trSPACE *next, *prev;
32: } TRSPACE;
34: /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
35: It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
36: */
37: #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
39: /* This union is used to insure that the block passed to the user retains
40: a minimum alignment of PETSC_MEMALIGN.
41: */
42: typedef union
43: {
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 TRdebug = 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: Options Database Keys:
81: + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0`
82: - -malloc_debug - turns this feature on anytime
84: Level: advanced
86: Notes:
87: You should generally use `CHKMEMQ` as a short cut for calling this routine.
89: Error messages are written to `stdout`.
91: 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)
93: No output is generated if there are no problems detected.
95: Fortran Notes:
96: The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
98: .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
99: @*/
100: PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
101: {
102: TRSPACE *head, *lasthead;
103: char *a;
104: PetscClassId *nend;
106: if (!TRdebug) return PETSC_SUCCESS;
107: head = TRhead;
108: lasthead = NULL;
109: if (head && head->prev) {
110: TRdebug = PETSC_FALSE;
111: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
112: PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
113: return PETSC_ERR_MEMC;
114: }
115: while (head) {
116: if (head->classid != CLASSID_VALUE) {
117: TRdebug = PETSC_FALSE;
118: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
119: PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
120: PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
121: if (lasthead) {
122: a = (char *)(((TrSPACE *)head) + 1);
123: PetscCall((*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n", lasthead->id, (PetscLogDouble)lasthead->size, a, lasthead->functionname, lasthead->filename, lasthead->lineno));
124: }
125: abort();
126: return PETSC_ERR_MEMC;
127: }
128: a = (char *)(((TrSPACE *)head) + 1);
129: nend = (PetscClassId *)(a + head->size);
130: if (*nend != CLASSID_VALUE) {
131: TRdebug = PETSC_FALSE;
132: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
133: if (*nend == ALREADY_FREED) {
134: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
135: return PETSC_ERR_MEMC;
136: } else {
137: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
138: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
139: return PETSC_ERR_MEMC;
140: }
141: }
142: if (head->prev && head->prev != lasthead) {
143: TRdebug = PETSC_FALSE;
144: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
145: PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
146: PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
147: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
148: return PETSC_ERR_MEMC;
149: }
150: lasthead = head;
151: head = head->next;
152: }
153: return PETSC_SUCCESS;
154: }
156: /*
157: PetscTrMallocDefault - Malloc with logging and error checking
159: */
160: static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
161: {
162: TRSPACE *head;
163: char *inew;
164: size_t nsize;
166: PetscFunctionBegin;
167: if (!a) {
168: *result = NULL;
169: PetscFunctionReturn(PETSC_SUCCESS);
170: }
172: PetscCall(PetscMallocValidate(lineno, function, filename));
174: nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
175: PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
177: head = (TRSPACE *)inew;
178: inew += sizeof(TrSPACE);
180: if (TRhead) TRhead->prev = head;
181: head->next = TRhead;
182: TRhead = head;
183: head->prev = NULL;
184: head->size = nsize;
185: head->rsize = a;
186: head->id = TRid++;
187: head->lineno = lineno;
189: head->filename = filename;
190: head->functionname = function;
191: head->classid = CLASSID_VALUE;
192: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
194: TRallocated += TRrequestedSize ? head->rsize : head->size;
195: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
196: if (PetscLogMemory) {
197: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
198: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
199: }
200: }
201: TRfrags++;
203: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
204: PetscCall(PetscStackCopy(&petscstack, &head->stack));
205: /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
206: head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
207: head->stack.currentsize--;
208: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
209: if (!clear && TRdebugIinitializenan) {
210: size_t n = a / sizeof(PetscReal);
211: PetscReal *s = (PetscReal *)inew;
212: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
213: #if defined(PETSC_USE_REAL_SINGLE)
214: int nas = 0x7F800002;
215: #else
216: PetscInt64 nas = 0x7FF0000000000002;
217: #endif
218: for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
219: }
220: #endif
221: #endif
223: /*
224: Allow logging of all mallocs made.
225: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
226: */
227: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
228: if (!PetscLogMalloc) {
229: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
230: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
232: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
233: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
235: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
236: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
237: }
238: PetscLogMallocLength[PetscLogMalloc] = nsize;
239: PetscLogMallocFile[PetscLogMalloc] = filename;
240: PetscLogMallocFunction[PetscLogMalloc++] = function;
241: }
242: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
243: *result = (void *)inew;
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*
248: PetscTrFreeDefault - Free with logging and error checking
250: */
251: static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
252: {
253: char *a = (char *)aa;
254: TRSPACE *head;
255: char *ahead;
256: size_t asize;
257: PetscClassId *nend;
259: PetscFunctionBegin;
260: if (!a) PetscFunctionReturn(PETSC_SUCCESS);
262: PetscCall(PetscMallocValidate(lineno, function, filename));
264: ahead = a;
265: a = a - sizeof(TrSPACE);
266: head = (TRSPACE *)a;
268: if (head->classid != CLASSID_VALUE) {
269: TRdebug = PETSC_FALSE;
270: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
271: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
272: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
273: }
274: nend = (PetscClassId *)(ahead + head->size);
275: if (*nend != CLASSID_VALUE) {
276: TRdebug = PETSC_FALSE;
277: if (*nend == ALREADY_FREED) {
278: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
279: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
280: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
281: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
282: } else {
283: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
284: }
285: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
286: } else {
287: /* Damaged tail */
288: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
289: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
290: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
291: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
292: }
293: }
294: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
295: PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
296: }
297: *nend = ALREADY_FREED;
298: /* Save location where freed. If we suspect the line number, mark as allocated location */
299: if (lineno > 0 && lineno < 50000) {
300: head->lineno = lineno;
301: head->filename = filename;
302: head->functionname = function;
303: } else {
304: head->lineno = -head->lineno;
305: }
306: asize = TRrequestedSize ? head->rsize : head->size;
307: PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
308: TRallocated -= asize;
309: TRfrags--;
310: if (head->prev) head->prev->next = head->next;
311: else TRhead = head->next;
313: if (head->next) head->next->prev = head->prev;
314: PetscCall(PetscFreeAlign(a, lineno, function, filename));
315: PetscFunctionReturn(PETSC_SUCCESS);
316: }
318: /*
319: PetscTrReallocDefault - Realloc with logging and error checking
321: */
322: static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
323: {
324: char *a = (char *)*result;
325: TRSPACE *head;
326: char *ahead, *inew;
327: PetscClassId *nend;
328: size_t nsize;
330: PetscFunctionBegin;
331: /* Realloc requests zero space so just free the current space */
332: if (!len) {
333: PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
334: *result = NULL;
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
337: /* If the original space was NULL just use the regular malloc() */
338: if (!*result) {
339: PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
340: PetscFunctionReturn(PETSC_SUCCESS);
341: }
343: PetscCall(PetscMallocValidate(lineno, function, filename));
345: ahead = a;
346: a = a - sizeof(TrSPACE);
347: head = (TRSPACE *)a;
348: inew = a;
350: if (head->classid != CLASSID_VALUE) {
351: TRdebug = PETSC_FALSE;
352: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
353: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
354: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
355: }
356: nend = (PetscClassId *)(ahead + head->size);
357: if (*nend != CLASSID_VALUE) {
358: TRdebug = PETSC_FALSE;
359: if (*nend == ALREADY_FREED) {
360: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
361: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
362: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
363: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
364: } else {
365: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
366: }
367: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
368: } else {
369: /* Damaged tail */
370: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
371: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
372: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
373: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
374: }
375: }
377: /* remove original reference to the memory allocated from the PETSc debugging heap */
378: TRallocated -= TRrequestedSize ? head->rsize : head->size;
379: TRfrags--;
380: if (head->prev) head->prev->next = head->next;
381: else TRhead = head->next;
382: if (head->next) head->next->prev = head->prev;
384: nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
385: PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
387: head = (TRSPACE *)inew;
388: inew += sizeof(TrSPACE);
390: if (TRhead) TRhead->prev = head;
391: head->next = TRhead;
392: TRhead = head;
393: head->prev = NULL;
394: head->size = nsize;
395: head->rsize = len;
396: head->id = TRid++;
397: head->lineno = lineno;
399: head->filename = filename;
400: head->functionname = function;
401: head->classid = CLASSID_VALUE;
402: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
404: TRallocated += TRrequestedSize ? head->rsize : head->size;
405: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
406: if (PetscLogMemory) {
407: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
408: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
409: }
410: }
411: TRfrags++;
413: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
414: PetscCall(PetscStackCopy(&petscstack, &head->stack));
415: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
416: head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
417: #endif
419: /*
420: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
421: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
422: */
423: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
424: if (!PetscLogMalloc) {
425: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
426: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
428: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
429: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
431: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
432: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
433: }
434: PetscLogMallocLength[PetscLogMalloc] = nsize;
435: PetscLogMallocFile[PetscLogMalloc] = filename;
436: PetscLogMallocFunction[PetscLogMalloc++] = function;
437: }
438: *result = (void *)inew;
439: PetscFunctionReturn(PETSC_SUCCESS);
440: }
442: /*@C
443: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
445: Collective
447: Input Parameters:
448: + viewer - the viewer to output the information on
449: - message - string printed before values
451: Options Database Keys:
452: + -malloc_debug - have PETSc track how much memory it has allocated
453: . -log_view_memory - print memory usage per event when `-log_view` is used
454: - -memory_view - during `PetscFinalize()` have this routine called
456: Level: intermediate
458: .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
459: @*/
460: PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
461: {
462: PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
463: PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
464: MPI_Comm comm;
466: PetscFunctionBegin;
467: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
468: PetscCall(PetscMallocGetCurrentUsage(&allocated));
469: PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
470: PetscCall(PetscMemoryGetCurrentUsage(&resident));
471: PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
472: if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
473: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
474: PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
475: if (resident && residentmax && allocated) {
476: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
477: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
478: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
479: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
480: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
481: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
482: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
483: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
484: PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
485: PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
486: PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
487: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
488: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
489: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
490: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
491: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
492: } else if (resident && residentmax) {
493: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
494: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
495: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
496: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
497: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
498: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
499: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
500: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
501: } else if (resident && allocated) {
502: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
503: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
504: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
505: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
506: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
507: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
508: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
509: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
510: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
511: } else if (allocated) {
512: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
513: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
514: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
515: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
516: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
517: PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
518: } else {
519: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
520: }
521: PetscCall(PetscViewerFlush(viewer));
522: PetscFunctionReturn(PETSC_SUCCESS);
523: }
525: /*@
526: PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
528: Not Collective
530: Output Parameter:
531: . space - number of bytes currently allocated
533: Level: intermediate
535: Note:
536: This only works if `-memory_view` or `-log_view_memory` have been used
538: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
539: `PetscMemoryGetMaximumUsage()`
540: @*/
541: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
542: {
543: PetscFunctionBegin;
544: *space = (PetscLogDouble)TRallocated;
545: PetscFunctionReturn(PETSC_SUCCESS);
546: }
548: /*@
549: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
550: during this run, the high water mark.
552: Not Collective
554: Output Parameter:
555: . space - maximum number of bytes ever allocated at one time
557: Level: intermediate
559: Note:
560: This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
562: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
563: `PetscMallocPushMaximumUsage()`
564: @*/
565: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
566: {
567: PetscFunctionBegin;
568: *space = (PetscLogDouble)TRMaxMem;
569: PetscFunctionReturn(PETSC_SUCCESS);
570: }
572: /*@
573: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
575: Not Collective
577: Input Parameter:
578: . event - an event id; this is just for error checking
580: Level: developer
582: Note:
583: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
585: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
586: `PetscMallocPopMaximumUsage()`
587: @*/
588: PetscErrorCode PetscMallocPushMaximumUsage(int event)
589: {
590: PetscFunctionBegin;
591: if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
592: TRMaxMems[NumTRMaxMems - 1] = TRallocated;
593: TRMaxMemsEvents[NumTRMaxMems - 1] = event;
594: PetscFunctionReturn(PETSC_SUCCESS);
595: }
597: /*@
598: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
600: Not Collective
602: Input Parameter:
603: . event - an event id; this is just for error checking
605: Output Parameter:
606: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
608: Level: developer
610: Note:
611: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
613: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
614: `PetscMallocPushMaximumUsage()`
615: @*/
616: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
617: {
618: PetscFunctionBegin;
619: *mu = 0;
620: if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
621: PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
622: *mu = TRMaxMems[NumTRMaxMems];
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
626: /*@C
627: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
629: Not Collective
631: Input Parameter:
632: . ptr - the memory location
634: Output Parameter:
635: . stack - the stack indicating where the program allocated this memory
637: Level: intermediate
639: Note:
640: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
642: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
643: @*/
644: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
645: {
646: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
647: TRSPACE *head;
649: PetscFunctionBegin;
650: head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
651: *stack = &head->stack;
652: PetscFunctionReturn(PETSC_SUCCESS);
653: #else
654: *stack = NULL;
655: return PETSC_SUCCESS;
656: #endif
657: }
659: /*@C
660: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
661: printed is: size of space (in bytes), address of space, id of space,
662: file in which space was allocated, and line number at which it was
663: allocated.
665: Not Collective
667: Input Parameter:
668: . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed.
670: Options Database Key:
671: . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
673: Level: intermediate
675: Notes:
676: Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
678: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
680: `PetscMallocView()` prints a list of all memory ever allocated
682: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
684: Fortran Notes:
685: The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
687: Developer Notes:
688: This should be absorbed into `PetscMallocView()`
690: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
691: @*/
692: PetscErrorCode PetscMallocDump(FILE *fp)
693: {
694: TRSPACE *head;
695: size_t libAlloc = 0;
696: PetscMPIInt rank;
698: PetscFunctionBegin;
699: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
700: if (!fp) fp = PETSC_STDOUT;
701: head = TRhead;
702: while (head) {
703: libAlloc += TRrequestedSize ? head->rsize : head->size;
704: head = head->next;
705: }
706: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
707: head = TRhead;
708: while (head) {
709: PetscBool isLib;
711: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
712: if (!isLib) {
713: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
714: fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
715: PetscCall(PetscStackPrint(&head->stack, fp));
716: #else
717: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
718: #endif
719: }
720: head = head->next;
721: }
722: PetscFunctionReturn(PETSC_SUCCESS);
723: }
725: /*@
726: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
728: Not Collective
730: Input Parameter:
731: . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
733: Options Database Keys:
734: + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
735: . -malloc_view_threshold <min> - Sets a minimum size if `-malloc_view` is used
736: - -log_view_memory - view the memory usage also with the -log_view option
738: Level: advanced
740: Note:
741: Must be called after `PetscMallocSetDebug()`
743: Developer Notes:
744: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
746: .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
747: @*/
748: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
749: {
750: PetscFunctionBegin;
751: PetscLogMalloc = 0;
752: PetscCall(PetscMemorySetGetMaximumUsage());
753: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
754: PetscLogMallocThreshold = (size_t)logmin;
755: PetscFunctionReturn(PETSC_SUCCESS);
756: }
758: /*@
759: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
761: Not Collective
763: Output Parameter:
764: . logging - `PETSC_TRUE` if logging is active
766: Options Database Key:
767: . -malloc_view <optional filename> - Activates `PetscMallocView()`
769: Level: advanced
771: .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
772: @*/
773: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
774: {
775: PetscFunctionBegin;
776: *logging = (PetscBool)(PetscLogMalloc >= 0);
777: PetscFunctionReturn(PETSC_SUCCESS);
778: }
780: /*@
781: PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
783: Not Collective
785: Input Parameters:
786: + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
787: . active - Flag to activate or deactivate tracing
788: - logmin - The smallest memory size that will be logged
790: Level: advanced
792: Note:
793: The viewer should not be collective.
795: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
797: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
798: @*/
799: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
800: {
801: PetscFunctionBegin;
802: if (!active) {
803: PetscLogMallocTrace = -1;
804: PetscFunctionReturn(PETSC_SUCCESS);
805: }
806: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
808: PetscLogMallocTraceViewer = viewer;
809: PetscLogMallocTrace = 0;
810: PetscCall(PetscMemorySetGetMaximumUsage());
811: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
812: PetscLogMallocTraceThreshold = (size_t)logmin;
813: PetscFunctionReturn(PETSC_SUCCESS);
814: }
816: /*@
817: PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
819: Not Collective
821: Output Parameter:
822: . logging - `PETSC_TRUE` if logging is active
824: Options Database Key:
825: . -malloc_view <optional filename> - Activates `PetscMallocView()`
827: Level: advanced
829: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
831: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
832: @*/
833: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
834: {
835: PetscFunctionBegin;
836: *logging = (PetscBool)(PetscLogMallocTrace >= 0);
837: PetscFunctionReturn(PETSC_SUCCESS);
838: }
840: /*@C
841: PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
843: Not Collective
845: Input Parameter:
846: . fp - file pointer; or `NULL`
848: Options Database Key:
849: . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
851: Level: advanced
853: Notes:
854: `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
856: `PetscMemoryView()` gives a brief summary of current memory usage
858: Fortran Notes:
859: The calling sequence in Fortran is `PetscMallocView`(integer ierr)
861: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
862: @*/
863: PetscErrorCode PetscMallocView(FILE *fp)
864: {
865: PetscInt n, *perm;
866: size_t *shortlength;
867: int *shortcount;
868: PetscMPIInt rank;
869: PetscBool match;
870: const char **shortfunction;
871: PetscLogDouble rss;
873: PetscFunctionBegin;
874: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
875: PetscCall(PetscFFlush(fp));
877: PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
879: if (!fp) fp = PETSC_STDOUT;
880: PetscCall(PetscMemoryGetMaximumUsage(&rss));
881: if (rss) {
882: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
883: } else {
884: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
885: }
886: if (PetscLogMalloc > 0) {
887: shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
888: PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
889: shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
890: PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
891: shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
892: PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
893: n = 0;
894: for (PetscInt i = 0; i < PetscLogMalloc; i++) {
895: for (PetscInt j = 0; j < n; j++) {
896: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
897: if (match) {
898: shortlength[j] += PetscLogMallocLength[i];
899: shortcount[j]++;
900: goto foundit;
901: }
902: }
903: shortfunction[n] = PetscLogMallocFunction[i];
904: shortlength[n] = PetscLogMallocLength[i];
905: shortcount[n] = 1;
906: n++;
907: foundit:;
908: }
910: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
911: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
912: for (PetscInt i = 0; i < n; i++) perm[i] = i;
913: PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
915: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
916: for (PetscInt i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
917: free(perm);
918: free(shortlength);
919: free(shortcount);
920: free((char **)shortfunction);
921: }
922: PetscCall(PetscFFlush(fp));
923: PetscFunctionReturn(PETSC_SUCCESS);
924: }
926: /*@
927: PetscMallocSetDebug - Set's PETSc memory debugging
929: Not Collective
931: Input Parameters:
932: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
933: - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
935: Options Database Keys:
936: + -malloc_debug <true or false> - turns on or off debugging
937: . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
938: . -malloc_view_threshold t - log only allocations larger than t
939: - -malloc_dump <filename> - print a list of all memory that has not been freed, in `PetscFinalize()`
941: Level: developer
943: Note:
944: This is called in `PetscInitialize()` and should not be called elsewhere
946: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
947: @*/
948: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
949: {
950: PetscFunctionBegin;
951: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
952: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
954: TRallocated = 0;
955: TRfrags = 0;
956: TRhead = NULL;
957: TRid = 0;
958: TRdebug = eachcall;
959: TRMaxMem = 0;
960: PetscLogMallocMax = 10000;
961: PetscLogMalloc = -1;
962: TRdebugIinitializenan = initializenan;
963: PetscFunctionReturn(PETSC_SUCCESS);
964: }
966: /*@
967: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
969: Not Collective
971: Output Parameters:
972: + basic - doing basic debugging
973: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
974: - initializenan - initializes memory with `NaN`
976: Level: intermediate
978: Note:
979: By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
981: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
982: @*/
983: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
984: {
985: PetscFunctionBegin;
986: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
987: if (eachcall) *eachcall = TRdebug;
988: if (initializenan) *initializenan = TRdebugIinitializenan;
989: PetscFunctionReturn(PETSC_SUCCESS);
990: }
992: /*@
993: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
995: Not Collective
997: Input Parameter:
998: . flg - `PETSC_TRUE` to log the requested memory size
1000: Options Database Key:
1001: . -malloc_requested_size <bool> - Sets this flag
1003: Level: developer
1005: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1006: @*/
1007: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1008: {
1009: PetscFunctionBegin;
1010: TRrequestedSize = flg;
1011: PetscFunctionReturn(PETSC_SUCCESS);
1012: }
1014: /*@
1015: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1017: Not Collective
1019: Output Parameter:
1020: . flg - `PETSC_TRUE` if we log the requested memory size
1022: Level: developer
1024: .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1025: @*/
1026: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1027: {
1028: PetscFunctionBegin;
1029: *flg = TRrequestedSize;
1030: PetscFunctionReturn(PETSC_SUCCESS);
1031: }