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 PetscDefined(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 COOKIE_VALUE -253701943
18: #define ALREADY_FREED 252579228
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: PetscInt specialcookie;
28: #if PetscDefined(USE_DEBUG)
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 TRSPACE *TRhead = NULL;
51: static int TRid = 0;
52: static PetscBool TRdebug = PETSC_FALSE;
53: static PetscBool TRdebugIinitializenan = PETSC_FALSE;
54: static PetscBool TRrequestedSize = PETSC_FALSE;
55: static size_t TRMaxMem = 0;
56: static int NumTRMaxMems = 0;
57: static size_t TRMaxMems[MAXTRMAXMEMS];
58: static int TRMaxMemsEvents[MAXTRMAXMEMS];
59: /*
60: Arrays to log information on mallocs for PetscMallocView()
61: */
62: static int PetscLogMallocMax = 10000;
63: static int PetscLogMalloc = -1;
64: static size_t PetscLogMallocThreshold = 0;
65: static size_t *PetscLogMallocLength;
66: static const char **PetscLogMallocFile, **PetscLogMallocFunction;
67: static int PetscLogMallocTrace = -1;
68: static size_t PetscLogMallocTraceThreshold = 0;
69: static PetscViewer PetscLogMallocTraceViewer = NULL;
71: /*@
72: PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
74: Input Parameters:
75: + line - line number where call originated.
76: . function - name of function calling
77: - file - file where function is
79: Options Database Keys:
80: + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0`
81: - -malloc_debug (true|false) - turns this feature on anytime
83: Level: advanced
85: Notes:
86: You should generally use `CHKMEMQ` as a short cut for calling this routine.
88: Error messages are written to `stdout`.
90: 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)
92: No output is generated if there are no problems detected.
94: Fortran Notes:
95: The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
97: .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
98: @*/
99: PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
100: {
101: TRSPACE *head, *lasthead;
102: char *a;
103: PetscInt *nend;
105: if (!TRdebug) return PETSC_SUCCESS;
106: head = TRhead;
107: lasthead = NULL;
108: if (head && head->prev) {
109: TRdebug = PETSC_FALSE;
110: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
111: PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
112: return PETSC_ERR_MEMC;
113: }
114: while (head) {
115: if (head->specialcookie != COOKIE_VALUE) {
116: TRdebug = PETSC_FALSE;
117: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
118: PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
119: PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
120: if (lasthead) {
121: a = (char *)(((TrSPACE *)head) + 1);
122: 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));
123: }
124: abort();
125: return PETSC_ERR_MEMC;
126: }
127: a = (char *)(((TrSPACE *)head) + 1);
128: nend = (PetscInt *)(a + head->size);
129: if (*nend != COOKIE_VALUE) {
130: TRdebug = PETSC_FALSE;
131: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
132: if (*nend == ALREADY_FREED) {
133: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
134: return PETSC_ERR_MEMC;
135: } else {
136: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
137: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
138: return PETSC_ERR_MEMC;
139: }
140: }
141: if (head->prev && head->prev != lasthead) {
142: TRdebug = PETSC_FALSE;
143: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
144: PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
145: PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
146: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
147: return PETSC_ERR_MEMC;
148: }
149: lasthead = head;
150: head = head->next;
151: }
152: return PETSC_SUCCESS;
153: }
155: /*
156: PetscTrMallocDefault - Malloc with logging and error checking
158: */
159: static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
160: {
161: TRSPACE *head;
162: char *inew;
163: size_t nsize;
165: PetscFunctionBegin;
166: if (!a) {
167: *result = NULL;
168: PetscFunctionReturn(PETSC_SUCCESS);
169: }
171: PetscCall(PetscMallocValidate(lineno, function, filename));
173: nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
174: PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), clear, lineno, function, filename, (void **)&inew));
176: head = (TRSPACE *)inew;
177: inew += sizeof(TrSPACE);
179: if (TRhead) TRhead->prev = head;
180: head->next = TRhead;
181: TRhead = head;
182: head->prev = NULL;
183: head->size = nsize;
184: head->rsize = a;
185: head->id = TRid++;
186: head->lineno = lineno;
188: head->filename = filename;
189: head->functionname = function;
190: head->specialcookie = COOKIE_VALUE;
191: *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
193: TRallocated += TRrequestedSize ? head->rsize : head->size;
194: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
195: if (PetscLogMemory) {
196: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
197: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
198: }
199: }
201: #if PetscDefined(USE_DEBUG)
202: PetscCall(PetscStackCopy(&petscstack, &head->stack));
203: /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
204: if (head->stack.currentsize > 1 && head->stack.currentsize - 2 < PETSCSTACKSIZE) head->stack.line[head->stack.currentsize - 2] = lineno;
205: head->stack.currentsize--;
206: #if PetscDefined(USE_REAL_SINGLE) || PetscDefined(USE_REAL_DOUBLE)
207: if (!clear && TRdebugIinitializenan) {
208: size_t n = a / sizeof(PetscReal);
209: PetscReal *s = (PetscReal *)inew;
210: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
211: #if PetscDefined(USE_REAL_SINGLE)
212: int nas = 0x7F800002;
213: #else
214: PetscInt64 nas = 0x7FF0000000000002;
215: #endif
216: for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
217: }
218: #endif
219: #endif
221: /*
222: Allow logging of all mallocs made.
223: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
224: */
225: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
226: if (!PetscLogMalloc) {
227: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
228: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
230: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
231: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
233: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
234: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
235: }
236: PetscLogMallocLength[PetscLogMalloc] = nsize;
237: PetscLogMallocFile[PetscLogMalloc] = filename;
238: PetscLogMallocFunction[PetscLogMalloc++] = function;
239: }
240: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
241: *result = (void *)inew;
242: PetscFunctionReturn(PETSC_SUCCESS);
243: }
245: /*
246: PetscTrFreeDefault - Free with logging and error checking
248: */
249: static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
250: {
251: char *a = (char *)aa;
252: TRSPACE *head;
253: char *ahead;
254: size_t asize;
255: PetscInt *nend;
257: PetscFunctionBegin;
258: if (!a) PetscFunctionReturn(PETSC_SUCCESS);
260: PetscCall(PetscMallocValidate(lineno, function, filename));
262: ahead = a;
263: a = a - sizeof(TrSPACE);
264: head = (TRSPACE *)a;
266: if (head->specialcookie != COOKIE_VALUE) {
267: TRdebug = PETSC_FALSE;
268: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
269: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
270: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
271: }
272: nend = (PetscInt *)(ahead + head->size);
273: if (*nend != COOKIE_VALUE) {
274: TRdebug = PETSC_FALSE;
275: if (*nend == ALREADY_FREED) {
276: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
277: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
278: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
279: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
280: } else {
281: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
282: }
283: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
284: } else {
285: /* Damaged tail */
286: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
287: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
288: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
289: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
290: }
291: }
292: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
293: *nend = ALREADY_FREED;
294: /* Save location where freed. If we suspect the line number, mark as allocated location */
295: if (lineno > 0 && lineno < 50000) {
296: head->lineno = lineno;
297: head->filename = filename;
298: head->functionname = function;
299: } else {
300: head->lineno = -head->lineno;
301: }
302: asize = TRrequestedSize ? head->rsize : head->size;
303: PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
304: TRallocated -= asize;
305: if (head->prev) head->prev->next = head->next;
306: else TRhead = head->next;
308: if (head->next) head->next->prev = head->prev;
309: PetscCall(PetscFreeAlign(a, lineno, function, filename));
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: /*
314: PetscTrReallocDefault - Realloc with logging and error checking
316: */
317: static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
318: {
319: char *a = (char *)*result;
320: TRSPACE *head;
321: char *ahead, *inew;
322: PetscInt *nend;
323: size_t nsize;
325: PetscFunctionBegin;
326: /* Realloc requests zero space so just free the current space */
327: if (!len) {
328: PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
329: *result = NULL;
330: PetscFunctionReturn(PETSC_SUCCESS);
331: }
332: /* If the original space was NULL just use the regular malloc() */
333: if (!*result) {
334: PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: PetscCall(PetscMallocValidate(lineno, function, filename));
340: ahead = a;
341: a = a - sizeof(TrSPACE);
342: head = (TRSPACE *)a;
343: inew = a;
345: if (head->specialcookie != COOKIE_VALUE) {
346: TRdebug = PETSC_FALSE;
347: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
348: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
349: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
350: }
351: nend = (PetscInt *)(ahead + head->size);
352: if (*nend != COOKIE_VALUE) {
353: TRdebug = PETSC_FALSE;
354: if (*nend == ALREADY_FREED) {
355: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
356: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
357: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
358: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
359: } else {
360: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
361: }
362: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
363: } else {
364: /* Damaged tail */
365: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
366: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
367: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
368: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
369: }
370: }
372: /* remove original reference to the memory allocated from the PETSc debugging heap */
373: TRallocated -= TRrequestedSize ? head->rsize : head->size;
374: if (head->prev) head->prev->next = head->next;
375: else TRhead = head->next;
376: if (head->next) head->next->prev = head->prev;
378: nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
379: PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), lineno, function, filename, (void **)&inew));
381: head = (TRSPACE *)inew;
382: inew += sizeof(TrSPACE);
384: if (TRhead) TRhead->prev = head;
385: head->next = TRhead;
386: TRhead = head;
387: head->prev = NULL;
388: head->size = nsize;
389: head->rsize = len;
390: head->id = TRid++;
391: head->lineno = lineno;
393: head->filename = filename;
394: head->functionname = function;
395: head->specialcookie = COOKIE_VALUE;
396: *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
398: TRallocated += TRrequestedSize ? head->rsize : head->size;
399: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
400: if (PetscLogMemory) {
401: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
402: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
403: }
404: }
406: #if PetscDefined(USE_DEBUG)
407: PetscCall(PetscStackCopy(&petscstack, &head->stack));
408: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
409: if (head->stack.currentsize > 1 && head->stack.currentsize - 2 < PETSCSTACKSIZE) head->stack.line[head->stack.currentsize - 2] = lineno;
410: head->stack.currentsize--;
411: #endif
413: /*
414: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
415: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
416: */
417: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
418: if (!PetscLogMalloc) {
419: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
420: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
422: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
423: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
425: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
426: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
427: }
428: PetscLogMallocLength[PetscLogMalloc] = nsize;
429: PetscLogMallocFile[PetscLogMalloc] = filename;
430: PetscLogMallocFunction[PetscLogMalloc++] = function;
431: }
432: *result = (void *)inew;
433: PetscFunctionReturn(PETSC_SUCCESS);
434: }
436: /*@
437: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
439: Collective
441: Input Parameters:
442: + viewer - the viewer to output the information on
443: - message - string printed before values
445: Options Database Keys:
446: + -malloc_debug (true|false) - have PETSc track how much memory it has allocated
447: . -log_view_memory (true|false) - print memory usage per event when `-log_view` is used
448: - -memory_view (true|false) - during `PetscFinalize()` have this routine called with `PETSC_VIEWER_STDOUT_WORLD`
450: Level: intermediate
452: .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
453: @*/
454: PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
455: {
456: PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
457: PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
458: MPI_Comm comm;
460: PetscFunctionBegin;
461: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
462: PetscCall(PetscMallocGetCurrentUsage(&allocated));
463: PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
464: PetscCall(PetscMemoryGetCurrentUsage(&resident));
465: PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
466: if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
467: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
468: PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
469: if (resident && residentmax && allocated) {
470: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
471: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
472: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
473: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
474: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
475: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
476: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
477: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
478: PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
479: PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
480: PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
481: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
482: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
483: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
484: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
485: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
486: } else if (resident && residentmax) {
487: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
488: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
489: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
490: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
491: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
492: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
493: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
494: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
495: } else if (resident && allocated) {
496: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
497: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
498: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
499: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
500: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
501: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
502: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
503: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
504: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
505: } else if (allocated) {
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: PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
512: } else {
513: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
514: }
515: PetscCall(PetscViewerFlush(viewer));
516: PetscFunctionReturn(PETSC_SUCCESS);
517: }
519: /*@
520: PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
522: Not Collective
524: Output Parameter:
525: . space - number of bytes currently allocated
527: Level: intermediate
529: Note:
530: This only works if `-memory_view` or `-log_view_memory` have been used
532: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
533: `PetscMemoryGetMaximumUsage()`
534: @*/
535: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
536: {
537: PetscFunctionBegin;
538: *space = (PetscLogDouble)TRallocated;
539: PetscFunctionReturn(PETSC_SUCCESS);
540: }
542: /*@
543: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
544: during this run, the high water mark.
546: Not Collective
548: Output Parameter:
549: . space - maximum number of bytes ever allocated at one time
551: Level: intermediate
553: Note:
554: This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
556: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
557: `PetscMallocPushMaximumUsage()`
558: @*/
559: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
560: {
561: PetscFunctionBegin;
562: *space = (PetscLogDouble)TRMaxMem;
563: PetscFunctionReturn(PETSC_SUCCESS);
564: }
566: /*@
567: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
569: Not Collective
571: Input Parameter:
572: . event - an event id; this is just for error checking
574: Level: developer
576: Note:
577: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
579: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
580: `PetscMallocPopMaximumUsage()`
581: @*/
582: PetscErrorCode PetscMallocPushMaximumUsage(int event)
583: {
584: PetscFunctionBegin;
585: if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
586: TRMaxMems[NumTRMaxMems - 1] = TRallocated;
587: TRMaxMemsEvents[NumTRMaxMems - 1] = event;
588: PetscFunctionReturn(PETSC_SUCCESS);
589: }
591: /*@
592: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
594: Not Collective
596: Input Parameter:
597: . event - an event id; this is just for error checking
599: Output Parameter:
600: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
602: Level: developer
604: Note:
605: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
607: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
608: `PetscMallocPushMaximumUsage()`
609: @*/
610: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
611: {
612: PetscFunctionBegin;
613: *mu = 0;
614: if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
615: PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
616: *mu = (PetscLogDouble)TRMaxMems[NumTRMaxMems];
617: PetscFunctionReturn(PETSC_SUCCESS);
618: }
620: /*@
621: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
623: Not Collective, No Fortran Support
625: Input Parameter:
626: . ptr - the memory location
628: Output Parameter:
629: . stack - the stack indicating where the program allocated this memory, or `NULL` if unavailable
631: Level: intermediate
633: Note:
634: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
636: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
637: @*/
638: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
639: {
640: #if PetscDefined(USE_DEBUG)
641: TRSPACE *head;
643: PetscFunctionBegin;
644: *stack = NULL;
645: if (PetscTrMalloc != PetscTrMallocDefault) PetscFunctionReturn(PETSC_SUCCESS);
646: head = (TRSPACE *)((char *)ptr - HEADER_BYTES);
647: *stack = &head->stack;
648: PetscFunctionReturn(PETSC_SUCCESS);
649: #else
650: *stack = NULL;
651: return PETSC_SUCCESS;
652: #endif
653: }
655: /*@
656: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
657: printed is: size of space (in bytes), address of space, id of space,
658: file in which space was allocated, and line number at which it was
659: allocated.
661: Not Collective
663: Input Parameter:
664: . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed.
666: Options Database Key:
667: . -malloc_dump [filename] - Print summary of unfreed memory during call to `PetscFinalize()`, writing to `filename` if given otherwise `stdout`
669: Level: intermediate
671: Notes:
672: Uses `MPI_COMM_WORLD` to display the MPI rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
674: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
676: `PetscMallocView()` prints a list of all memory ever allocated
678: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
680: Fortran Notes:
681: The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
683: Developer Notes:
684: This should be absorbed into `PetscMallocView()`
686: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
687: @*/
688: PetscErrorCode PetscMallocDump(FILE *fp)
689: {
690: TRSPACE *head;
691: size_t libAlloc = 0;
692: PetscMPIInt rank;
694: PetscFunctionBegin;
695: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
696: if (!fp) fp = PETSC_STDOUT;
697: head = TRhead;
698: while (head) {
699: libAlloc += TRrequestedSize ? head->rsize : head->size;
700: head = head->next;
701: }
702: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
703: head = TRhead;
704: while (head) {
705: PetscBool isLib;
707: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
708: if (!isLib) {
709: #if PetscDefined(USE_DEBUG)
710: fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
711: PetscCall(PetscStackPrint(&head->stack, fp));
712: #else
713: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
714: #endif
715: }
716: head = head->next;
717: }
718: PetscFunctionReturn(PETSC_SUCCESS);
719: }
721: /*@
722: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
724: Not Collective
726: Input Parameter:
727: . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
729: Options Database Keys:
730: + -malloc_view [filename] - Activates `PetscMallocView()` in `PetscFinalize()`
731: . -malloc_view_threshold logmin - Sets a minimum size if `-malloc_view` is used
732: - -log_view_memory (true|false) - View the memory usage also with the `-log_view` option
734: Level: advanced
736: Note:
737: Must be called after `PetscMallocSetDebug()`
739: Developer Notes:
740: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
742: .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
743: @*/
744: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
745: {
746: PetscFunctionBegin;
747: PetscLogMalloc = 0;
748: PetscCall(PetscMemorySetGetMaximumUsage());
749: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
750: PetscLogMallocThreshold = (size_t)logmin;
751: PetscFunctionReturn(PETSC_SUCCESS);
752: }
754: /*@
755: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
757: Not Collective
759: Output Parameter:
760: . logging - `PETSC_TRUE` if logging is active
762: Level: advanced
764: .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
765: @*/
766: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
767: {
768: PetscFunctionBegin;
769: *logging = (PetscBool)(PetscLogMalloc >= 0);
770: PetscFunctionReturn(PETSC_SUCCESS);
771: }
773: /*@
774: PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
776: Not Collective
778: Input Parameters:
779: + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
780: . active - Flag to activate or deactivate tracing
781: - logmin - The smallest memory size that will be logged
783: Level: advanced
785: Note:
786: The viewer should not be collective.
788: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
790: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
791: @*/
792: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
793: {
794: PetscFunctionBegin;
795: if (!active) {
796: PetscLogMallocTrace = -1;
797: PetscFunctionReturn(PETSC_SUCCESS);
798: }
799: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
801: PetscLogMallocTraceViewer = viewer;
802: PetscLogMallocTrace = 0;
803: PetscCall(PetscMemorySetGetMaximumUsage());
804: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
805: PetscLogMallocTraceThreshold = (size_t)logmin;
806: PetscFunctionReturn(PETSC_SUCCESS);
807: }
809: /*@
810: PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
812: Not Collective
814: Output Parameter:
815: . logging - `PETSC_TRUE` if logging is active
817: Level: advanced
819: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
821: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
822: @*/
823: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
824: {
825: PetscFunctionBegin;
826: *logging = (PetscBool)(PetscLogMallocTrace >= 0);
827: PetscFunctionReturn(PETSC_SUCCESS);
828: }
830: /*@
831: PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
833: Not Collective
835: Input Parameter:
836: . fp - file pointer; or `NULL`
838: Options Database Key:
839: . -malloc_view [filename] - Activates `PetscMallocView()` in `PetscFinalize()`
841: Level: advanced
843: Notes:
844: `PetscMallocDump()` dumps only the currently unfreed memory, this routine dumps all memory ever allocated
846: `PetscMemoryView()` gives a brief summary of current memory usage
848: Fortran Notes:
849: The calling sequence in Fortran is `PetscMallocView`(integer ierr) and can only write to `stdout`
851: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
852: @*/
853: PetscErrorCode PetscMallocView(FILE *fp)
854: {
855: PetscInt n, *perm;
856: size_t *shortlength;
857: int *shortcount;
858: PetscMPIInt rank;
859: PetscBool match;
860: const char **shortfunction;
861: PetscLogDouble rss;
863: PetscFunctionBegin;
864: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
865: PetscCall(PetscFFlush(fp));
867: 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()");
869: if (!fp) fp = PETSC_STDOUT;
870: PetscCall(PetscMemoryGetMaximumUsage(&rss));
871: if (rss) {
872: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
873: } else {
874: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
875: }
876: if (PetscLogMalloc > 0) {
877: shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
878: PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
879: shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
880: PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
881: shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
882: PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
883: n = 0;
884: for (PetscInt i = 0; i < PetscLogMalloc; i++) {
885: for (PetscInt j = 0; j < n; j++) {
886: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
887: if (match) {
888: shortlength[j] += PetscLogMallocLength[i];
889: shortcount[j]++;
890: goto foundit;
891: }
892: }
893: shortfunction[n] = PetscLogMallocFunction[i];
894: shortlength[n] = PetscLogMallocLength[i];
895: shortcount[n] = 1;
896: n++;
897: foundit:;
898: }
900: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
901: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
902: for (PetscInt i = 0; i < n; i++) perm[i] = i;
903: PetscCall(PetscSortStrWithPermutation(n, shortfunction, perm));
905: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
906: 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]]);
907: free(perm);
908: free(shortlength);
909: free(shortcount);
910: free((char **)shortfunction);
911: }
912: PetscCall(PetscFFlush(fp));
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
916: /*@
917: PetscMallocSetDebug - Set's PETSc memory debugging
919: Not Collective
921: Input Parameters:
922: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
923: - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
925: Options Database Keys:
926: + -malloc_debug (true|false) - turns on or off debugging
927: . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
928: . -malloc_view_threshold logmin - log only allocations larger than `logmin`
929: - -malloc_dump [filename] - print a list of all memory that has not been freed, in `PetscFinalize()`
931: Level: developer
933: Note:
934: This is called in `PetscInitialize()` and should not be called elsewhere
936: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
937: @*/
938: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
939: {
940: PetscFunctionBegin;
941: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
942: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
944: TRallocated = 0;
945: TRhead = NULL;
946: TRid = 0;
947: TRdebug = eachcall;
948: TRMaxMem = 0;
949: PetscLogMallocMax = 10000;
950: PetscLogMalloc = -1;
951: TRdebugIinitializenan = initializenan;
952: PetscFunctionReturn(PETSC_SUCCESS);
953: }
955: /*@
956: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
958: Not Collective
960: Output Parameters:
961: + basic - doing basic debugging
962: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
963: - initializenan - initializes memory with `NaN`
965: Level: intermediate
967: Note:
968: By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
970: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
971: @*/
972: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
973: {
974: PetscFunctionBegin;
975: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
976: if (eachcall) *eachcall = TRdebug;
977: if (initializenan) *initializenan = TRdebugIinitializenan;
978: PetscFunctionReturn(PETSC_SUCCESS);
979: }
981: /*@
982: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
984: Not Collective
986: Input Parameter:
987: . flg - `PETSC_TRUE` to log the requested memory size
989: Options Database Key:
990: . -malloc_requested_size (true|false) - Sets this flag
992: Level: developer
994: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
995: @*/
996: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
997: {
998: PetscFunctionBegin;
999: TRrequestedSize = flg;
1000: PetscFunctionReturn(PETSC_SUCCESS);
1001: }
1003: /*@
1004: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1006: Not Collective
1008: Output Parameter:
1009: . flg - `PETSC_TRUE` if we log the requested memory size
1011: Level: developer
1013: .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1014: @*/
1015: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1016: {
1017: PetscFunctionBegin;
1018: *flg = TRrequestedSize;
1019: PetscFunctionReturn(PETSC_SUCCESS);
1020: }