Actual source code: mtr.c
2: /*
3: Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4: */
5: #include <petsc/private/petscimpl.h>
6: #include <petscviewer.h>
7: #if defined(PETSC_HAVE_MALLOC_H)
8: #include <malloc.h>
9: #endif
11: /*
12: These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13: */
14: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
15: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
16: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
18: #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
19: #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
21: /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22: typedef struct _trSPACE {
23: size_t size, rsize; /* Aligned size and requested size */
24: int id;
25: int lineno;
26: const char *filename;
27: const char *functionname;
28: PetscClassId classid;
29: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
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: {
45: TRSPACE sp;
46: char v[HEADER_BYTES];
47: } TrSPACE;
49: #define MAXTRMAXMEMS 50
50: static size_t TRallocated = 0;
51: static int TRfrags = 0;
52: static TRSPACE *TRhead = NULL;
53: static int TRid = 0;
54: static PetscBool TRdebugLevel = PETSC_FALSE;
55: static PetscBool TRdebugIinitializenan = PETSC_FALSE;
56: static PetscBool TRrequestedSize = PETSC_FALSE;
57: static size_t TRMaxMem = 0;
58: static int NumTRMaxMems = 0;
59: static size_t TRMaxMems[MAXTRMAXMEMS];
60: static int TRMaxMemsEvents[MAXTRMAXMEMS];
61: /*
62: Arrays to log information on mallocs for PetscMallocView()
63: */
64: static int PetscLogMallocMax = 10000;
65: static int PetscLogMalloc = -1;
66: static size_t PetscLogMallocThreshold = 0;
67: static size_t *PetscLogMallocLength;
68: static const char **PetscLogMallocFile, **PetscLogMallocFunction;
69: static int PetscLogMallocTrace = -1;
70: static size_t PetscLogMallocTraceThreshold = 0;
71: static PetscViewer PetscLogMallocTraceViewer = NULL;
73: /*@C
74: PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
76: Input Parameters:
77: + line - line number where call originated.
78: . function - name of function calling
79: - file - file where function is
81: Return value:
82: The number of errors detected.
84: Options Database Keys:.
85: + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
86: - -malloc_debug - turns this feature on anytime
88: Output Effect:
89: Error messages are written to stdout.
91: Level: advanced
93: Notes:
94: 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)
96: You should generally use `CHKMEMQ` as a short cut for calling this routine.
98: No output is generated if there are no problems detected.
100: Fortran Note:
101: The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
103: Developers Note:
104: Uses the flg `TRdebugLevel` (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run
106: .seealso: `CHKMEMQ`
107: @*/
108: PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
109: {
110: TRSPACE *head, *lasthead;
111: char *a;
112: PetscClassId *nend;
114: if (!TRdebugLevel) return PETSC_SUCCESS;
115: head = TRhead;
116: lasthead = NULL;
117: if (head && head->prev) {
118: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
119: PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
120: return PETSC_ERR_MEMC;
121: }
122: while (head) {
123: if (head->classid != CLASSID_VALUE) {
124: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
125: PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
126: PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
127: if (lasthead) {
128: a = (char *)(((TrSPACE *)head) + 1);
129: 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));
130: }
131: abort();
132: return PETSC_ERR_MEMC;
133: }
134: a = (char *)(((TrSPACE *)head) + 1);
135: nend = (PetscClassId *)(a + head->size);
136: if (*nend != CLASSID_VALUE) {
137: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
138: if (*nend == ALREADY_FREED) {
139: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
140: return PETSC_ERR_MEMC;
141: } else {
142: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
143: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
144: return PETSC_ERR_MEMC;
145: }
146: }
147: if (head->prev && head->prev != lasthead) {
148: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
149: PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
150: PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
151: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
152: return PETSC_ERR_MEMC;
153: }
154: lasthead = head;
155: head = head->next;
156: }
157: return PETSC_SUCCESS;
158: }
160: /*
161: PetscTrMallocDefault - Malloc with tracing.
163: Input Parameters:
164: + a - number of bytes to allocate
165: . lineno - line number where used. Use __LINE__ for this
166: - filename - file name where used. Use __FILE__ for this
168: Returns:
169: double aligned pointer to requested storage, or null if not available.
170: */
171: PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
172: {
173: TRSPACE *head;
174: char *inew;
175: size_t nsize;
177: PetscFunctionBegin;
178: /* Do not try to handle empty blocks */
179: if (!a) {
180: *result = NULL;
181: PetscFunctionReturn(PETSC_SUCCESS);
182: }
184: PetscCall(PetscMallocValidate(lineno, function, filename));
186: nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
187: PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
189: head = (TRSPACE *)inew;
190: inew += sizeof(TrSPACE);
192: if (TRhead) TRhead->prev = head;
193: head->next = TRhead;
194: TRhead = head;
195: head->prev = NULL;
196: head->size = nsize;
197: head->rsize = a;
198: head->id = TRid++;
199: head->lineno = lineno;
201: head->filename = filename;
202: head->functionname = function;
203: head->classid = CLASSID_VALUE;
204: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
206: TRallocated += TRrequestedSize ? head->rsize : head->size;
207: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
208: if (PetscLogMemory) {
209: PetscInt i;
210: for (i = 0; i < NumTRMaxMems; i++) {
211: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
212: }
213: }
214: TRfrags++;
216: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
217: PetscCall(PetscStackCopy(&petscstack, &head->stack));
218: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
219: head->stack.line[head->stack.currentsize - 2] = lineno;
220: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
221: if (!clear && TRdebugIinitializenan) {
222: size_t i, n = a / sizeof(PetscReal);
223: PetscReal *s = (PetscReal *)inew;
224: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
225: #if defined(PETSC_USE_REAL_SINGLE)
226: int nas = 0x7F800002;
227: #else
228: PetscInt64 nas = 0x7FF0000000000002;
229: #endif
230: for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
231: }
232: #endif
233: #endif
235: /*
236: Allow logging of all mallocs made.
237: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
238: */
239: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
240: if (!PetscLogMalloc) {
241: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
242: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
244: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
245: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
247: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
248: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
249: }
250: PetscLogMallocLength[PetscLogMalloc] = nsize;
251: PetscLogMallocFile[PetscLogMalloc] = filename;
252: PetscLogMallocFunction[PetscLogMalloc++] = function;
253: }
254: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
255: *result = (void *)inew;
256: PetscFunctionReturn(PETSC_SUCCESS);
257: }
259: /*
260: PetscTrFreeDefault - Free with tracing.
262: Input Parameters:
263: . a - pointer to a block allocated with PetscTrMalloc
264: . lineno - line number where used. Use __LINE__ for this
265: . filename - file name where used. Use __FILE__ for this
266: */
267: PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
268: {
269: char *a = (char *)aa;
270: TRSPACE *head;
271: char *ahead;
272: size_t asize;
273: PetscClassId *nend;
275: PetscFunctionBegin;
276: /* Do not try to handle empty blocks */
277: if (!a) PetscFunctionReturn(PETSC_SUCCESS);
279: PetscCall(PetscMallocValidate(lineno, function, filename));
281: ahead = a;
282: a = a - sizeof(TrSPACE);
283: head = (TRSPACE *)a;
285: if (head->classid != CLASSID_VALUE) {
286: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
287: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
288: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
289: }
290: nend = (PetscClassId *)(ahead + head->size);
291: if (*nend != CLASSID_VALUE) {
292: if (*nend == ALREADY_FREED) {
293: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
294: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
295: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
296: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
297: } else {
298: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
299: }
300: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
301: } else {
302: /* Damaged tail */
303: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
304: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
305: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
306: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
307: }
308: }
309: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
310: PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
311: }
312: /* Mark the location freed */
313: *nend = ALREADY_FREED;
314: /* Save location where freed. If we suspect the line number, mark as allocated location */
315: if (lineno > 0 && lineno < 50000) {
316: head->lineno = lineno;
317: head->filename = filename;
318: head->functionname = function;
319: } else {
320: head->lineno = -head->lineno;
321: }
322: asize = TRrequestedSize ? head->rsize : head->size;
323: PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
324: TRallocated -= asize;
325: TRfrags--;
326: if (head->prev) head->prev->next = head->next;
327: else TRhead = head->next;
329: if (head->next) head->next->prev = head->prev;
330: PetscCall(PetscFreeAlign(a, lineno, function, filename));
331: PetscFunctionReturn(PETSC_SUCCESS);
332: }
334: /*
335: PetscTrReallocDefault - Realloc with tracing.
337: Input Parameters:
338: + len - number of bytes to allocate
339: . lineno - line number where used. Use __LINE__ for this
340: . filename - file name where used. Use __FILE__ for this
341: - result - original memory
343: Output Parameter:
344: . result - double aligned pointer to requested storage, or null if not available.
346: Level: developer
348: .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
349: */
350: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
351: {
352: char *a = (char *)*result;
353: TRSPACE *head;
354: char *ahead, *inew;
355: PetscClassId *nend;
356: size_t nsize;
358: PetscFunctionBegin;
359: /* Realloc requests zero space so just free the current space */
360: if (!len) {
361: PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
362: *result = NULL;
363: PetscFunctionReturn(PETSC_SUCCESS);
364: }
365: /* If the original space was NULL just use the regular malloc() */
366: if (!*result) {
367: PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
368: PetscFunctionReturn(PETSC_SUCCESS);
369: }
371: PetscCall(PetscMallocValidate(lineno, function, filename));
373: ahead = a;
374: a = a - sizeof(TrSPACE);
375: head = (TRSPACE *)a;
376: inew = a;
378: if (head->classid != CLASSID_VALUE) {
379: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
380: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
381: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
382: }
383: nend = (PetscClassId *)(ahead + head->size);
384: if (*nend != CLASSID_VALUE) {
385: if (*nend == ALREADY_FREED) {
386: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
387: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
388: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
389: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
390: } else {
391: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
392: }
393: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
394: } else {
395: /* Damaged tail */
396: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
397: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
398: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
399: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
400: }
401: }
403: /* remove original reference to the memory allocated from the PETSc debugging heap */
404: TRallocated -= TRrequestedSize ? head->rsize : head->size;
405: TRfrags--;
406: if (head->prev) head->prev->next = head->next;
407: else TRhead = head->next;
408: if (head->next) head->next->prev = head->prev;
410: nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
411: PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
413: head = (TRSPACE *)inew;
414: inew += sizeof(TrSPACE);
416: if (TRhead) TRhead->prev = head;
417: head->next = TRhead;
418: TRhead = head;
419: head->prev = NULL;
420: head->size = nsize;
421: head->rsize = len;
422: head->id = TRid++;
423: head->lineno = lineno;
425: head->filename = filename;
426: head->functionname = function;
427: head->classid = CLASSID_VALUE;
428: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
430: TRallocated += TRrequestedSize ? head->rsize : head->size;
431: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
432: if (PetscLogMemory) {
433: PetscInt i;
434: for (i = 0; i < NumTRMaxMems; i++) {
435: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
436: }
437: }
438: TRfrags++;
440: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
441: PetscCall(PetscStackCopy(&petscstack, &head->stack));
442: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
443: head->stack.line[head->stack.currentsize - 2] = lineno;
444: #endif
446: /*
447: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
448: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
449: */
450: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
451: if (!PetscLogMalloc) {
452: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
453: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
455: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
456: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
458: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
459: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
460: }
461: PetscLogMallocLength[PetscLogMalloc] = nsize;
462: PetscLogMallocFile[PetscLogMalloc] = filename;
463: PetscLogMallocFunction[PetscLogMalloc++] = function;
464: }
465: *result = (void *)inew;
466: PetscFunctionReturn(PETSC_SUCCESS);
467: }
469: /*@C
470: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
472: Collective
474: Input Parameters:
475: + viewer - the viewer that defines the communicator
476: - message - string printed before values
478: Options Database Keys:
479: + -malloc_debug - have PETSc track how much memory it has allocated
480: . -log_view_memory - print memory usage per event
481: - -memory_view - during PetscFinalize() have this routine called
483: Level: intermediate
485: .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
486: @*/
487: PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
488: {
489: PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
490: PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
491: MPI_Comm comm;
493: PetscFunctionBegin;
494: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
495: PetscCall(PetscMallocGetCurrentUsage(&allocated));
496: PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
497: PetscCall(PetscMemoryGetCurrentUsage(&resident));
498: PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
499: if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
500: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
501: PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
502: if (resident && residentmax && allocated) {
503: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
504: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
505: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
506: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
507: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
508: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
509: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
510: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
511: PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
512: PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
513: PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
514: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
515: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
516: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
517: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
518: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
519: } else if (resident && residentmax) {
520: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
521: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
522: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
523: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
524: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
525: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
526: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
527: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
528: } else if (resident && allocated) {
529: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
530: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
531: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
532: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
533: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
534: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
535: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
536: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
537: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
538: } else if (allocated) {
539: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
540: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
541: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
542: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
543: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
544: PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
545: } else {
546: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
547: }
548: PetscCall(PetscViewerFlush(viewer));
549: PetscFunctionReturn(PETSC_SUCCESS);
550: }
552: /*@
553: PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
555: Not Collective
557: Output Parameter:
558: . space - number of bytes currently allocated
560: Level: intermediate
562: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
563: `PetscMemoryGetMaximumUsage()`
564: @*/
565: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
566: {
567: PetscFunctionBegin;
568: *space = (PetscLogDouble)TRallocated;
569: PetscFunctionReturn(PETSC_SUCCESS);
570: }
572: /*@
573: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
574: during this run, the high water mark.
576: Not Collective
578: Output Parameter:
579: . space - maximum number of bytes ever allocated at one time
581: Level: intermediate
583: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
584: `PetscMallocPushMaximumUsage()`
585: @*/
586: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
587: {
588: PetscFunctionBegin;
589: *space = (PetscLogDouble)TRMaxMem;
590: PetscFunctionReturn(PETSC_SUCCESS);
591: }
593: /*@
594: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
596: Not Collective
598: Input Parameter:
599: . event - an event id; this is just for error checking
601: Level: developer
603: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
604: `PetscMallocPopMaximumUsage()`
605: @*/
606: PetscErrorCode PetscMallocPushMaximumUsage(int event)
607: {
608: PetscFunctionBegin;
609: if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
610: TRMaxMems[NumTRMaxMems - 1] = TRallocated;
611: TRMaxMemsEvents[NumTRMaxMems - 1] = event;
612: PetscFunctionReturn(PETSC_SUCCESS);
613: }
615: /*@
616: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
618: Not Collective
620: Input Parameter:
621: . event - an event id; this is just for error checking
623: Output Parameter:
624: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
626: Level: developer
628: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
629: `PetscMallocPushMaximumUsage()`
630: @*/
631: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
632: {
633: PetscFunctionBegin;
634: *mu = 0;
635: if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
636: PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
637: *mu = TRMaxMems[NumTRMaxMems];
638: PetscFunctionReturn(PETSC_SUCCESS);
639: }
641: /*@C
642: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
644: Collective on `PETSC_COMM_WORLD`
646: Input Parameter:
647: . ptr - the memory location
649: Output Parameter:
650: . stack - the stack indicating where the program allocated this memory
652: Level: intermediate
654: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
655: @*/
656: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
657: {
658: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
659: TRSPACE *head;
661: PetscFunctionBegin;
662: head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
663: *stack = &head->stack;
664: PetscFunctionReturn(PETSC_SUCCESS);
665: #else
666: *stack = NULL;
667: return PETSC_SUCCESS;
668: #endif
669: }
671: /*@C
672: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
673: printed is: size of space (in bytes), address of space, id of space,
674: file in which space was allocated, and line number at which it was
675: allocated.
677: Not Collective
679: Input Parameter:
680: . fp - file pointer. If fp is NULL, stdout is assumed.
682: Options Database Key:
683: . -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()`
685: Level: intermediate
687: Notes:
688: Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
690: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
692: `PetscMallocView()` prints a list of all memory ever allocated
694: Fortran Notes:
695: The calling sequence in Fortran is PetscMallocDump(integer ierr)
697: The `fp` defaults to stdout.
699: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
700: @*/
701: PetscErrorCode PetscMallocDump(FILE *fp)
702: {
703: TRSPACE *head;
704: size_t libAlloc = 0;
705: PetscMPIInt rank;
707: PetscFunctionBegin;
708: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
709: if (!fp) fp = PETSC_STDOUT;
710: head = TRhead;
711: while (head) {
712: libAlloc += TRrequestedSize ? head->rsize : head->size;
713: head = head->next;
714: }
715: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
716: head = TRhead;
717: while (head) {
718: PetscBool isLib;
720: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
721: if (!isLib) {
722: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
723: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
724: PetscCall(PetscStackPrint(&head->stack, fp));
725: #endif
726: }
727: head = head->next;
728: }
729: PetscFunctionReturn(PETSC_SUCCESS);
730: }
732: /*@
733: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
735: Not Collective
737: Input Parameter:
738: . logmin - minimum allocation size to log, or `PETSC_DEFAULT`
740: Options Database Key:
741: + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
742: . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
743: - -log_view_memory - view the memory usage also with the -log_view option
745: Level: advanced
747: Notes:
748: Must be called after `PetscMallocSetDebug()`
750: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
752: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
753: @*/
754: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
755: {
756: PetscFunctionBegin;
757: PetscLogMalloc = 0;
758: PetscCall(PetscMemorySetGetMaximumUsage());
759: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
760: PetscLogMallocThreshold = (size_t)logmin;
761: PetscFunctionReturn(PETSC_SUCCESS);
762: }
764: /*@
765: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
767: Not Collective
769: Output Parameter
770: . logging - `PETSC_TRUE` if logging is active
772: Options Database Key:
773: . -malloc_view <optional filename> - Activates `PetscMallocView()`
775: Level: advanced
777: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
778: @*/
779: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
780: {
781: PetscFunctionBegin;
782: *logging = (PetscBool)(PetscLogMalloc >= 0);
783: PetscFunctionReturn(PETSC_SUCCESS);
784: }
786: /*@
787: PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
789: Not Collective
791: Input Parameters:
792: + viewer - The viewer to use for tracing, or NULL to use stdout
793: . active - Flag to activate or deactivate tracing
794: - logmin - The smallest memory size that will be logged
796: Note:
797: The viewer should not be collective.
799: Level: advanced
801: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
802: @*/
803: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
804: {
805: PetscFunctionBegin;
806: if (!active) {
807: PetscLogMallocTrace = -1;
808: PetscFunctionReturn(PETSC_SUCCESS);
809: }
810: PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
811: PetscLogMallocTrace = 0;
812: PetscCall(PetscMemorySetGetMaximumUsage());
813: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
814: PetscLogMallocTraceThreshold = (size_t)logmin;
815: PetscFunctionReturn(PETSC_SUCCESS);
816: }
818: /*@
819: PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
821: Not Collective
823: Output Parameter:
824: . logging - `PETSC_TRUE` if logging is active
826: Options Database Key:
827: . -malloc_view <optional filename> - Activates PetscMallocView()
829: Level: advanced
831: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
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
842: `PetscMemoryGetMaximumUsage()`
844: Not Collective
846: Input Parameter:
847: . fp - file pointer; or NULL
849: Options Database Key:
850: . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
852: Level: advanced
854: Notes:
855: `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
857: `PetscMemoryView()` gives a brief summary of current memory usage
859: Fortran Notes:
860: The calling sequence in Fortran is PetscMallocView(integer ierr)
862: The `fp` defaults to stdout.
864: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
865: @*/
866: PetscErrorCode PetscMallocView(FILE *fp)
867: {
868: PetscInt i, j, n, *perm;
869: size_t *shortlength;
870: int *shortcount;
871: PetscMPIInt rank;
872: PetscBool match;
873: const char **shortfunction;
874: PetscLogDouble rss;
876: PetscFunctionBegin;
877: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
878: PetscCall(PetscFFlush(fp));
880: PetscCheck(PetscLogMalloc >= 0, 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()");
882: if (!fp) fp = PETSC_STDOUT;
883: PetscCall(PetscMemoryGetMaximumUsage(&rss));
884: if (rss) {
885: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
886: } else {
887: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
888: }
889: if (PetscLogMalloc > 0) {
890: shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
891: PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
892: shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
893: PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
894: shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
895: PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
896: for (i = 0, n = 0; i < PetscLogMalloc; i++) {
897: for (j = 0; j < n; j++) {
898: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
899: if (match) {
900: shortlength[j] += PetscLogMallocLength[i];
901: shortcount[j]++;
902: goto foundit;
903: }
904: }
905: shortfunction[n] = PetscLogMallocFunction[i];
906: shortlength[n] = PetscLogMallocLength[i];
907: shortcount[n] = 1;
908: n++;
909: foundit:;
910: }
912: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
913: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
914: for (i = 0; i < n; i++) perm[i] = i;
915: PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
917: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
918: for (i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
919: free(perm);
920: free(shortlength);
921: free(shortcount);
922: free((char **)shortfunction);
923: }
924: PetscCall(PetscFFlush(fp));
925: PetscFunctionReturn(PETSC_SUCCESS);
926: }
928: /* ---------------------------------------------------------------------------- */
930: /*@
931: PetscMallocSetDebug - Set's PETSc memory debugging
933: Not Collective
935: Input Parameters:
936: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
937: - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
939: Options Database Keys:
940: + -malloc_debug <true or false> - turns on or off debugging
941: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
942: . -malloc_view_threshold t - log only allocations larger than t
943: . -malloc_dump <filename> - print a list of all memory that has not been freed
944: . -malloc no - (deprecated) same as -malloc_debug no
945: - -malloc_log - (deprecated) same as -malloc_view
947: Level: developer
949: Note:
950: This is called in `PetscInitialize()` and should not be called elsewhere
952: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
953: @*/
954: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
955: {
956: PetscFunctionBegin;
957: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
958: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
960: TRallocated = 0;
961: TRfrags = 0;
962: TRhead = NULL;
963: TRid = 0;
964: TRdebugLevel = eachcall;
965: TRMaxMem = 0;
966: PetscLogMallocMax = 10000;
967: PetscLogMalloc = -1;
968: TRdebugIinitializenan = initializenan;
969: PetscFunctionReturn(PETSC_SUCCESS);
970: }
972: /*@
973: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
975: Not Collective
977: Output Parameters:
978: + basic - doing basic debugging
979: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
980: - initializenan - initializes memory with NaN
982: Level: intermediate
984: Note:
985: By default, the debug version always does some debugging unless you run with -malloc_debug no
987: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
988: @*/
989: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
990: {
991: PetscFunctionBegin;
992: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
993: if (eachcall) *eachcall = TRdebugLevel;
994: if (initializenan) *initializenan = TRdebugIinitializenan;
995: PetscFunctionReturn(PETSC_SUCCESS);
996: }
998: /*@
999: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1001: Not Collective
1003: Input Parameter:
1004: . flg - `PETSC_TRUE` to log the requested memory size
1006: Options Database Key:
1007: . -malloc_requested_size <bool> - Sets this flag
1009: Level: developer
1011: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
1012: @*/
1013: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1014: {
1015: PetscFunctionBegin;
1016: TRrequestedSize = flg;
1017: PetscFunctionReturn(PETSC_SUCCESS);
1018: }
1020: /*@
1021: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1023: Not Collective
1025: Output Parameter:
1026: . flg - `PETSC_TRUE` if we log the requested memory size
1028: Level: developer
1030: .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1031: @*/
1032: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1033: {
1034: PetscFunctionBegin;
1035: *flg = TRrequestedSize;
1036: PetscFunctionReturn(PETSC_SUCCESS);
1037: }