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: The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
100: No output is generated if there are no problems detected.
102: Developers Note:
103: Uses the flg TRdebugLevel (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run
105: .seealso: `CHKMEMQ`
106: @*/
107: PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
108: {
109: TRSPACE *head, *lasthead;
110: char *a;
111: PetscClassId *nend;
113: if (!TRdebugLevel) return PETSC_SUCCESS;
114: head = TRhead;
115: lasthead = NULL;
116: if (head && head->prev) {
117: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
118: PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
119: return PETSC_ERR_MEMC;
120: }
121: while (head) {
122: if (head->classid != CLASSID_VALUE) {
123: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
124: PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
125: PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
126: if (lasthead) {
127: a = (char *)(((TrSPACE *)head) + 1);
128: 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));
129: }
130: abort();
131: return PETSC_ERR_MEMC;
132: }
133: a = (char *)(((TrSPACE *)head) + 1);
134: nend = (PetscClassId *)(a + head->size);
135: if (*nend != CLASSID_VALUE) {
136: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
137: if (*nend == ALREADY_FREED) {
138: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
139: return PETSC_ERR_MEMC;
140: } else {
141: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
142: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
143: return PETSC_ERR_MEMC;
144: }
145: }
146: if (head->prev && head->prev != lasthead) {
147: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
148: PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
149: PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
150: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
151: return PETSC_ERR_MEMC;
152: }
153: lasthead = head;
154: head = head->next;
155: }
156: return PETSC_SUCCESS;
157: }
159: /*
160: PetscTrMallocDefault - Malloc with tracing.
162: Input Parameters:
163: + a - number of bytes to allocate
164: . lineno - line number where used. Use __LINE__ for this
165: - filename - file name where used. Use __FILE__ for this
167: Returns:
168: double aligned pointer to requested storage, or null if not available.
169: */
170: PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
171: {
172: TRSPACE *head;
173: char *inew;
174: size_t nsize;
176: PetscFunctionBegin;
177: /* Do not try to handle empty blocks */
178: if (!a) {
179: *result = NULL;
180: PetscFunctionReturn(PETSC_SUCCESS);
181: }
183: PetscCall(PetscMallocValidate(lineno, function, filename));
185: nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
186: PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
188: head = (TRSPACE *)inew;
189: inew += sizeof(TrSPACE);
191: if (TRhead) TRhead->prev = head;
192: head->next = TRhead;
193: TRhead = head;
194: head->prev = NULL;
195: head->size = nsize;
196: head->rsize = a;
197: head->id = TRid++;
198: head->lineno = lineno;
200: head->filename = filename;
201: head->functionname = function;
202: head->classid = CLASSID_VALUE;
203: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
205: TRallocated += TRrequestedSize ? head->rsize : head->size;
206: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
207: if (PetscLogMemory) {
208: PetscInt i;
209: for (i = 0; i < NumTRMaxMems; i++) {
210: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
211: }
212: }
213: TRfrags++;
215: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
216: PetscCall(PetscStackCopy(&petscstack, &head->stack));
217: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
218: head->stack.line[head->stack.currentsize - 2] = lineno;
219: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
220: if (!clear && TRdebugIinitializenan) {
221: size_t i, n = a / sizeof(PetscReal);
222: PetscReal *s = (PetscReal *)inew;
223: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
224: #if defined(PETSC_USE_REAL_SINGLE)
225: int nas = 0x7F800002;
226: #else
227: PetscInt64 nas = 0x7FF0000000000002;
228: #endif
229: for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
230: }
231: #endif
232: #endif
234: /*
235: Allow logging of all mallocs made.
236: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
237: */
238: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
239: if (!PetscLogMalloc) {
240: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
241: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
243: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
244: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
246: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
247: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
248: }
249: PetscLogMallocLength[PetscLogMalloc] = nsize;
250: PetscLogMallocFile[PetscLogMalloc] = filename;
251: PetscLogMallocFunction[PetscLogMalloc++] = function;
252: }
253: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
254: *result = (void *)inew;
255: PetscFunctionReturn(PETSC_SUCCESS);
256: }
258: /*
259: PetscTrFreeDefault - Free with tracing.
261: Input Parameters:
262: . a - pointer to a block allocated with PetscTrMalloc
263: . lineno - line number where used. Use __LINE__ for this
264: . filename - file name where used. Use __FILE__ for this
265: */
266: PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
267: {
268: char *a = (char *)aa;
269: TRSPACE *head;
270: char *ahead;
271: size_t asize;
272: PetscClassId *nend;
274: PetscFunctionBegin;
275: /* Do not try to handle empty blocks */
276: if (!a) PetscFunctionReturn(PETSC_SUCCESS);
278: PetscCall(PetscMallocValidate(lineno, function, filename));
280: ahead = a;
281: a = a - sizeof(TrSPACE);
282: head = (TRSPACE *)a;
284: if (head->classid != CLASSID_VALUE) {
285: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
286: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
287: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
288: }
289: nend = (PetscClassId *)(ahead + head->size);
290: if (*nend != CLASSID_VALUE) {
291: if (*nend == ALREADY_FREED) {
292: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
293: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
294: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
295: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
296: } else {
297: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
298: }
299: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
300: } else {
301: /* Damaged tail */
302: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
303: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
304: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
305: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
306: }
307: }
308: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
309: PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
310: }
311: /* Mark the location freed */
312: *nend = ALREADY_FREED;
313: /* Save location where freed. If we suspect the line number, mark as allocated location */
314: if (lineno > 0 && lineno < 50000) {
315: head->lineno = lineno;
316: head->filename = filename;
317: head->functionname = function;
318: } else {
319: head->lineno = -head->lineno;
320: }
321: asize = TRrequestedSize ? head->rsize : head->size;
322: PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
323: TRallocated -= asize;
324: TRfrags--;
325: if (head->prev) head->prev->next = head->next;
326: else TRhead = head->next;
328: if (head->next) head->next->prev = head->prev;
329: PetscCall(PetscFreeAlign(a, lineno, function, filename));
330: PetscFunctionReturn(PETSC_SUCCESS);
331: }
333: /*
334: PetscTrReallocDefault - Realloc with tracing.
336: Input Parameters:
337: + len - number of bytes to allocate
338: . lineno - line number where used. Use __LINE__ for this
339: . filename - file name where used. Use __FILE__ for this
340: - result - original memory
342: Output Parameter:
343: . result - double aligned pointer to requested storage, or null if not available.
345: Level: developer
347: .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
348: */
349: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
350: {
351: char *a = (char *)*result;
352: TRSPACE *head;
353: char *ahead, *inew;
354: PetscClassId *nend;
355: size_t nsize;
357: PetscFunctionBegin;
358: /* Realloc requests zero space so just free the current space */
359: if (!len) {
360: PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
361: *result = NULL;
362: PetscFunctionReturn(PETSC_SUCCESS);
363: }
364: /* If the original space was NULL just use the regular malloc() */
365: if (!*result) {
366: PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
367: PetscFunctionReturn(PETSC_SUCCESS);
368: }
370: PetscCall(PetscMallocValidate(lineno, function, filename));
372: ahead = a;
373: a = a - sizeof(TrSPACE);
374: head = (TRSPACE *)a;
375: inew = a;
377: if (head->classid != CLASSID_VALUE) {
378: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
379: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
380: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
381: }
382: nend = (PetscClassId *)(ahead + head->size);
383: if (*nend != CLASSID_VALUE) {
384: if (*nend == ALREADY_FREED) {
385: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
386: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
387: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
388: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
389: } else {
390: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
391: }
392: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
393: } else {
394: /* Damaged tail */
395: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
396: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
397: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
398: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
399: }
400: }
402: /* remove original reference to the memory allocated from the PETSc debugging heap */
403: TRallocated -= TRrequestedSize ? head->rsize : head->size;
404: TRfrags--;
405: if (head->prev) head->prev->next = head->next;
406: else TRhead = head->next;
407: if (head->next) head->next->prev = head->prev;
409: nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
410: PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
412: head = (TRSPACE *)inew;
413: inew += sizeof(TrSPACE);
415: if (TRhead) TRhead->prev = head;
416: head->next = TRhead;
417: TRhead = head;
418: head->prev = NULL;
419: head->size = nsize;
420: head->rsize = len;
421: head->id = TRid++;
422: head->lineno = lineno;
424: head->filename = filename;
425: head->functionname = function;
426: head->classid = CLASSID_VALUE;
427: *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
429: TRallocated += TRrequestedSize ? head->rsize : head->size;
430: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
431: if (PetscLogMemory) {
432: PetscInt i;
433: for (i = 0; i < NumTRMaxMems; i++) {
434: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
435: }
436: }
437: TRfrags++;
439: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
440: PetscCall(PetscStackCopy(&petscstack, &head->stack));
441: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
442: head->stack.line[head->stack.currentsize - 2] = lineno;
443: #endif
445: /*
446: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
447: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
448: */
449: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
450: if (!PetscLogMalloc) {
451: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
452: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
454: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
455: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
457: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
458: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
459: }
460: PetscLogMallocLength[PetscLogMalloc] = nsize;
461: PetscLogMallocFile[PetscLogMalloc] = filename;
462: PetscLogMallocFunction[PetscLogMalloc++] = function;
463: }
464: *result = (void *)inew;
465: PetscFunctionReturn(PETSC_SUCCESS);
466: }
468: /*@C
469: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
471: Collective
473: Input Parameters:
474: + viewer - the viewer that defines the communicator
475: - message - string printed before values
477: Options Database Keys:
478: + -malloc_debug - have PETSc track how much memory it has allocated
479: . -log_view_memory - print memory usage per event
480: - -memory_view - during PetscFinalize() have this routine called
482: Level: intermediate
484: .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
485: @*/
486: PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
487: {
488: PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
489: PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
490: MPI_Comm comm;
492: PetscFunctionBegin;
493: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
494: PetscCall(PetscMallocGetCurrentUsage(&allocated));
495: PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
496: PetscCall(PetscMemoryGetCurrentUsage(&resident));
497: PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
498: if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
499: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
500: PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
501: if (resident && residentmax && allocated) {
502: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
503: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
504: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
505: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
506: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
507: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
508: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
509: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
510: PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
511: PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
512: PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
513: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
514: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
515: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
516: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
517: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
518: } else if (resident && residentmax) {
519: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
520: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
521: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
522: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
523: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
524: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
525: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
526: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
527: } else if (resident && allocated) {
528: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
529: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
530: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
531: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
532: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
533: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
534: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
535: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
536: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
537: } else if (allocated) {
538: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
539: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
540: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
541: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
542: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
543: PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
544: } else {
545: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
546: }
547: PetscCall(PetscViewerFlush(viewer));
548: PetscFunctionReturn(PETSC_SUCCESS);
549: }
551: /*@
552: PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
554: Not Collective
556: Output Parameters:
557: . space - number of bytes currently allocated
559: Level: intermediate
561: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
562: `PetscMemoryGetMaximumUsage()`
563: @*/
564: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
565: {
566: PetscFunctionBegin;
567: *space = (PetscLogDouble)TRallocated;
568: PetscFunctionReturn(PETSC_SUCCESS);
569: }
571: /*@
572: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
573: during this run, the high water mark.
575: Not Collective
577: Output Parameters:
578: . space - maximum number of bytes ever allocated at one time
580: Level: intermediate
582: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
583: `PetscMallocPushMaximumUsage()`
584: @*/
585: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
586: {
587: PetscFunctionBegin;
588: *space = (PetscLogDouble)TRMaxMem;
589: PetscFunctionReturn(PETSC_SUCCESS);
590: }
592: /*@
593: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
595: Not Collective
597: Input Parameter:
598: . event - an event id; this is just for error checking
600: Level: developer
602: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
603: `PetscMallocPopMaximumUsage()`
604: @*/
605: PetscErrorCode PetscMallocPushMaximumUsage(int event)
606: {
607: PetscFunctionBegin;
608: if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
609: TRMaxMems[NumTRMaxMems - 1] = TRallocated;
610: TRMaxMemsEvents[NumTRMaxMems - 1] = event;
611: PetscFunctionReturn(PETSC_SUCCESS);
612: }
614: /*@
615: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
617: Not Collective
619: Input Parameter:
620: . event - an event id; this is just for error checking
622: Output Parameter:
623: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
625: Level: developer
627: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
628: `PetscMallocPushMaximumUsage()`
629: @*/
630: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
631: {
632: PetscFunctionBegin;
633: *mu = 0;
634: if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
635: PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
636: *mu = TRMaxMems[NumTRMaxMems];
637: PetscFunctionReturn(PETSC_SUCCESS);
638: }
640: /*@C
641: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
643: Collective on `PETSC_COMM_WORLD`
645: Input Parameter:
646: . ptr - the memory location
648: Output Parameter:
649: . stack - the stack indicating where the program allocated this memory
651: Level: intermediate
653: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
654: @*/
655: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
656: {
657: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
658: TRSPACE *head;
660: PetscFunctionBegin;
661: head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
662: *stack = &head->stack;
663: PetscFunctionReturn(PETSC_SUCCESS);
664: #else
665: *stack = NULL;
666: return PETSC_SUCCESS;
667: #endif
668: }
670: /*@C
671: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
672: printed is: size of space (in bytes), address of space, id of space,
673: file in which space was allocated, and line number at which it was
674: allocated.
676: Not Collective
678: Input Parameter:
679: . fp - file pointer. If fp is NULL, stdout is assumed.
681: Options Database Key:
682: . -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()`
684: Level: intermediate
686: Fortran Note:
687: The calling sequence in Fortran is PetscMallocDump(integer ierr)
688: The fp defaults to stdout.
690: Notes:
691: Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
693: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
695: `PetscMallocView()` prints a list of all memory ever allocated
697: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
698: @*/
699: PetscErrorCode PetscMallocDump(FILE *fp)
700: {
701: TRSPACE *head;
702: size_t libAlloc = 0;
703: PetscMPIInt rank;
705: PetscFunctionBegin;
706: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
707: if (!fp) fp = PETSC_STDOUT;
708: head = TRhead;
709: while (head) {
710: libAlloc += TRrequestedSize ? head->rsize : head->size;
711: head = head->next;
712: }
713: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
714: head = TRhead;
715: while (head) {
716: PetscBool isLib;
718: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
719: if (!isLib) {
720: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
721: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
722: PetscCall(PetscStackPrint(&head->stack, fp));
723: #endif
724: }
725: head = head->next;
726: }
727: PetscFunctionReturn(PETSC_SUCCESS);
728: }
730: /*@
731: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
733: Not Collective
735: Input Parameter:
736: . logmin - minimum allocation size to log, or `PETSC_DEFAULT`
738: Options Database Key:
739: + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
740: . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
741: - -log_view_memory - view the memory usage also with the -log_view option
743: Level: advanced
745: Notes:
746: Must be called after `PetscMallocSetDebug()`
748: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
750: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
751: @*/
752: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
753: {
754: PetscFunctionBegin;
755: PetscLogMalloc = 0;
756: PetscCall(PetscMemorySetGetMaximumUsage());
757: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
758: PetscLogMallocThreshold = (size_t)logmin;
759: PetscFunctionReturn(PETSC_SUCCESS);
760: }
762: /*@
763: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
765: Not Collective
767: Output Parameter
768: . logging - `PETSC_TRUE` if logging is active
770: Options Database Key:
771: . -malloc_view <optional filename> - Activates `PetscMallocView()`
773: Level: advanced
775: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
776: @*/
777: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
778: {
779: PetscFunctionBegin;
780: *logging = (PetscBool)(PetscLogMalloc >= 0);
781: PetscFunctionReturn(PETSC_SUCCESS);
782: }
784: /*@
785: PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
787: Not Collective
789: Input Parameters:
790: + viewer - The viewer to use for tracing, or NULL to use stdout
791: . active - Flag to activate or deactivate tracing
792: - logmin - The smallest memory size that will be logged
794: Note:
795: The viewer should not be collective.
797: Level: advanced
799: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
800: @*/
801: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
802: {
803: PetscFunctionBegin;
804: if (!active) {
805: PetscLogMallocTrace = -1;
806: PetscFunctionReturn(PETSC_SUCCESS);
807: }
808: PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : 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: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
830: @*/
831: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
832: {
833: PetscFunctionBegin;
834: *logging = (PetscBool)(PetscLogMallocTrace >= 0);
835: PetscFunctionReturn(PETSC_SUCCESS);
836: }
838: /*@C
839: PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
840: `PetscMemoryGetMaximumUsage()`
842: Not Collective
844: Input Parameter:
845: . fp - file pointer; or NULL
847: Options Database Key:
848: . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
850: Level: advanced
852: Fortran Note:
853: The calling sequence in Fortran is PetscMallocView(integer ierr)
854: The fp defaults to stdout.
856: Notes:
857: `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
859: `PetscMemoryView()` gives a brief summary of current memory usage
861: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
862: @*/
863: PetscErrorCode PetscMallocView(FILE *fp)
864: {
865: PetscInt i, j, 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\n 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: for (i = 0, n = 0; i < PetscLogMalloc; i++) {
894: for (j = 0; j < n; j++) {
895: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
896: if (match) {
897: shortlength[j] += PetscLogMallocLength[i];
898: shortcount[j]++;
899: goto foundit;
900: }
901: }
902: shortfunction[n] = PetscLogMallocFunction[i];
903: shortlength[n] = PetscLogMallocLength[i];
904: shortcount[n] = 1;
905: n++;
906: foundit:;
907: }
909: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
910: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
911: for (i = 0; i < n; i++) perm[i] = i;
912: PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
914: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
915: 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]]);
916: free(perm);
917: free(shortlength);
918: free(shortcount);
919: free((char **)shortfunction);
920: }
921: PetscCall(PetscFFlush(fp));
922: PetscFunctionReturn(PETSC_SUCCESS);
923: }
925: /* ---------------------------------------------------------------------------- */
927: /*@
928: PetscMallocSetDebug - Set's PETSc memory debugging
930: Not Collective
932: Input Parameters:
933: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
934: - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
936: Options Database Keys:
937: + -malloc_debug <true or false> - turns on or off debugging
938: . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
939: . -malloc_view_threshold t - log only allocations larger than t
940: . -malloc_dump <filename> - print a list of all memory that has not been freed
941: . -malloc no - (deprecated) same as -malloc_debug no
942: - -malloc_log - (deprecated) same as -malloc_view
944: Level: developer
946: Note:
947: This is called in `PetscInitialize()` and should not be called elsewhere
949: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
950: @*/
951: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
952: {
953: PetscFunctionBegin;
954: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
955: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
957: TRallocated = 0;
958: TRfrags = 0;
959: TRhead = NULL;
960: TRid = 0;
961: TRdebugLevel = eachcall;
962: TRMaxMem = 0;
963: PetscLogMallocMax = 10000;
964: PetscLogMalloc = -1;
965: TRdebugIinitializenan = initializenan;
966: PetscFunctionReturn(PETSC_SUCCESS);
967: }
969: /*@
970: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
972: Not Collective
974: Output Parameters:
975: + basic - doing basic debugging
976: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
977: - initializenan - initializes memory with NaN
979: Level: intermediate
981: Note:
982: By default, the debug version always does some debugging unless you run with -malloc_debug no
984: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
985: @*/
986: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
987: {
988: PetscFunctionBegin;
989: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
990: if (eachcall) *eachcall = TRdebugLevel;
991: if (initializenan) *initializenan = TRdebugIinitializenan;
992: PetscFunctionReturn(PETSC_SUCCESS);
993: }
995: /*@
996: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
998: Not Collective
1000: Input Parameter:
1001: . flg - `PETSC_TRUE` to log the requested memory size
1003: Options Database Key:
1004: . -malloc_requested_size <bool> - Sets this flag
1006: Level: developer
1008: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
1009: @*/
1010: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1011: {
1012: PetscFunctionBegin;
1013: TRrequestedSize = flg;
1014: PetscFunctionReturn(PETSC_SUCCESS);
1015: }
1017: /*@
1018: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1020: Not Collective
1022: Output Parameter:
1023: . flg - `PETSC_TRUE` if we log the requested memory size
1025: Level: developer
1027: .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1028: @*/
1029: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1030: {
1031: PetscFunctionBegin;
1032: *flg = TRrequestedSize;
1033: PetscFunctionReturn(PETSC_SUCCESS);
1034: }