Actual source code: mtr.c
1: /*
2: Logging of memory usage and some error checking
3: */
4: #include <petsc/private/petscimpl.h>
5: #if PetscDefined(HAVE_MALLOC_H)
6: #include <malloc.h>
7: #endif
9: /*
10: These are defined in mal.c and ensure that malloced space is PetscScalar aligned
11: */
12: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
13: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
14: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
16: #define COOKIE_VALUE -253701943
17: #define ALREADY_FREED 252579228
19: /* this is the header put at the beginning of each PetscTrMallocDefault() for tracking allocated space and checking of allocated space heap */
20: typedef struct _trSPACE {
21: size_t size, rsize; /* Aligned size and requested size */
22: int id;
23: int lineno;
24: const char *filename;
25: const char *functionname;
26: PetscInt specialcookie;
27: #if PetscDefined(USE_DEBUG)
28: PetscStack stack;
29: #endif
30: struct _trSPACE *next, *prev;
31: } TRSPACE;
33: /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
34: It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
35: */
36: #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
38: /* This union is used to insure that the block passed to the user retains
39: a minimum alignment of PETSC_MEMALIGN.
40: */
41: typedef union
42: {
43: TRSPACE sp;
44: char v[HEADER_BYTES];
45: } TrSPACE;
47: #define MAXTRMAXMEMS 50
48: static size_t TRallocated = 0;
49: static TRSPACE *TRhead = NULL;
50: static int TRid = 0;
51: static PetscBool TRdebug = PETSC_FALSE;
52: static PetscBool TRdebugIinitializenan = PETSC_FALSE;
53: static PetscBool TRrequestedSize = PETSC_FALSE;
54: static size_t TRMaxMem = 0;
55: static int NumTRMaxMems = 0;
56: static size_t TRMaxMems[MAXTRMAXMEMS];
57: static int TRMaxMemsEvents[MAXTRMAXMEMS];
58: /*
59: Arrays to log information on mallocs for PetscMallocView()
60: */
61: static int PetscLogMallocMax = 10000;
62: static int PetscLogMalloc = -1;
63: static size_t PetscLogMallocThreshold = 0;
64: static size_t *PetscLogMallocLength;
65: static const char **PetscLogMallocFile, **PetscLogMallocFunction;
66: static int PetscLogMallocTrace = -1;
67: static size_t PetscLogMallocTraceThreshold = 0;
68: static PetscViewer PetscLogMallocTraceViewer = NULL;
70: /*@
71: PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
73: Input Parameters:
74: + line - line number where call originated.
75: . function - name of function calling
76: - file - file where function is
78: Options Database Keys:
79: + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0`
80: - -malloc_debug (true|false) - turns this feature on anytime
82: Level: advanced
84: Notes:
85: You should generally use `CHKMEMQ` as a short cut for calling this routine.
87: Error messages are written to `stdout`.
89: This is only run if `PetscMallocSetDebug()` has been called which is set by `-malloc_test` (if debugging is turned on) or `-malloc_debug` (any time)
91: No output is generated if there are no problems detected.
93: Fortran Notes:
94: The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
96: .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
97: @*/
98: PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
99: {
100: TRSPACE *head, *lasthead;
101: char *a;
102: PetscInt *nend;
104: if (!TRdebug) return PETSC_SUCCESS;
105: head = TRhead;
106: lasthead = NULL;
107: if (head && head->prev) {
108: TRdebug = PETSC_FALSE;
109: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
110: PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
111: return PETSC_ERR_MEMC;
112: }
113: while (head) {
114: if (head->specialcookie != COOKIE_VALUE) {
115: TRdebug = PETSC_FALSE;
116: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
117: PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
118: PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
119: if (lasthead) {
120: a = (char *)(((TrSPACE *)head) + 1);
121: 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));
122: }
123: abort();
124: return PETSC_ERR_MEMC;
125: }
126: a = (char *)(((TrSPACE *)head) + 1);
127: nend = (PetscInt *)(a + head->size);
128: if (*nend != COOKIE_VALUE) {
129: TRdebug = PETSC_FALSE;
130: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
131: if (*nend == ALREADY_FREED) {
132: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
133: return PETSC_ERR_MEMC;
134: } else {
135: PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
136: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
137: return PETSC_ERR_MEMC;
138: }
139: }
140: if (head->prev && head->prev != lasthead) {
141: TRdebug = PETSC_FALSE;
142: PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
143: PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
144: PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
145: PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
146: return PETSC_ERR_MEMC;
147: }
148: lasthead = head;
149: head = head->next;
150: }
151: return PETSC_SUCCESS;
152: }
154: /*
155: PetscTrMallocDefault - Malloc with logging and error checking
157: */
158: static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
159: {
160: TRSPACE *head;
161: char *inew;
162: size_t nsize;
164: PetscFunctionBegin;
165: if (!a) {
166: *result = NULL;
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: PetscCall(PetscMallocValidate(lineno, function, filename));
172: nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
173: PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), clear, lineno, function, filename, (void **)&inew));
175: head = (TRSPACE *)inew;
176: inew += sizeof(TrSPACE);
178: if (TRhead) TRhead->prev = head;
179: head->next = TRhead;
180: TRhead = head;
181: head->prev = NULL;
182: head->size = nsize;
183: head->rsize = a;
184: head->id = TRid++;
185: head->lineno = lineno;
187: head->filename = filename;
188: head->functionname = function;
189: head->specialcookie = COOKIE_VALUE;
190: *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
192: TRallocated += TRrequestedSize ? head->rsize : head->size;
193: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
194: if (PetscLogMemory) {
195: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
196: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
197: }
198: }
200: #if PetscDefined(USE_DEBUG)
201: PetscCall(PetscStackCopy(&petscstack, &head->stack));
202: /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
203: if (head->stack.currentsize > 1 && head->stack.currentsize - 2 < PETSCSTACKSIZE) head->stack.line[head->stack.currentsize - 2] = lineno;
204: head->stack.currentsize--;
205: #if PetscDefined(USE_REAL_SINGLE) || PetscDefined(USE_REAL_DOUBLE)
206: if (!clear && TRdebugIinitializenan) {
207: size_t n = a / sizeof(PetscReal);
208: PetscReal *s = (PetscReal *)inew;
209: /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
210: #if PetscDefined(USE_REAL_SINGLE)
211: int nas = 0x7F800002;
212: #else
213: PetscInt64 nas = 0x7FF0000000000002;
214: #endif
215: for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
216: }
217: #endif
218: #endif
220: /*
221: Allow logging of all mallocs made.
222: TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
223: */
224: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
225: if (!PetscLogMalloc) {
226: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
227: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
229: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
230: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
232: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
233: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
234: }
235: PetscLogMallocLength[PetscLogMalloc] = nsize;
236: PetscLogMallocFile[PetscLogMalloc] = filename;
237: PetscLogMallocFunction[PetscLogMalloc++] = function;
238: }
239: if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
240: *result = (void *)inew;
241: PetscFunctionReturn(PETSC_SUCCESS);
242: }
244: /*
245: PetscTrFreeDefault - Free with logging and error checking
247: */
248: static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
249: {
250: char *a = (char *)aa;
251: TRSPACE *head;
252: char *ahead;
253: size_t asize;
254: PetscInt *nend;
256: PetscFunctionBegin;
257: if (!a) PetscFunctionReturn(PETSC_SUCCESS);
259: PetscCall(PetscMallocValidate(lineno, function, filename));
261: ahead = a;
262: a = a - sizeof(TrSPACE);
263: head = (TRSPACE *)a;
265: if (head->specialcookie != COOKIE_VALUE) {
266: TRdebug = PETSC_FALSE;
267: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
268: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
269: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
270: }
271: nend = (PetscInt *)(ahead + head->size);
272: if (*nend != COOKIE_VALUE) {
273: TRdebug = PETSC_FALSE;
274: if (*nend == ALREADY_FREED) {
275: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
276: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
277: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
278: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
279: } else {
280: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
281: }
282: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
283: } else {
284: /* Damaged tail */
285: PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
286: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
287: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
288: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
289: }
290: }
291: if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
292: *nend = ALREADY_FREED;
293: /* Save location where freed. If we suspect the line number, mark as allocated location */
294: if (lineno > 0 && lineno < 50000) {
295: head->lineno = lineno;
296: head->filename = filename;
297: head->functionname = function;
298: } else {
299: head->lineno = -head->lineno;
300: }
301: asize = TRrequestedSize ? head->rsize : head->size;
302: PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
303: TRallocated -= asize;
304: if (head->prev) head->prev->next = head->next;
305: else TRhead = head->next;
307: if (head->next) head->next->prev = head->prev;
308: PetscCall(PetscFreeAlign(a, lineno, function, filename));
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /*
313: PetscTrReallocDefault - Realloc with logging and error checking
315: */
316: static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
317: {
318: char *a = (char *)*result;
319: TRSPACE *head;
320: char *ahead, *inew;
321: PetscInt *nend;
322: size_t nsize;
324: PetscFunctionBegin;
325: /* Realloc requests zero space so just free the current space */
326: if (!len) {
327: PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
328: *result = NULL;
329: PetscFunctionReturn(PETSC_SUCCESS);
330: }
331: /* If the original space was NULL just use the regular malloc() */
332: if (!*result) {
333: PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: PetscCall(PetscMallocValidate(lineno, function, filename));
339: ahead = a;
340: a = a - sizeof(TrSPACE);
341: head = (TRSPACE *)a;
342: inew = a;
344: if (head->specialcookie != COOKIE_VALUE) {
345: TRdebug = PETSC_FALSE;
346: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
347: PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
348: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
349: }
350: nend = (PetscInt *)(ahead + head->size);
351: if (*nend != COOKIE_VALUE) {
352: TRdebug = PETSC_FALSE;
353: if (*nend == ALREADY_FREED) {
354: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
355: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
356: if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
357: PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
358: } else {
359: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
360: }
361: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
362: } else {
363: /* Damaged tail */
364: PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
365: PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
366: PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
367: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
368: }
369: }
371: /* remove original reference to the memory allocated from the PETSc debugging heap */
372: TRallocated -= TRrequestedSize ? head->rsize : head->size;
373: if (head->prev) head->prev->next = head->next;
374: else TRhead = head->next;
375: if (head->next) head->next->prev = head->prev;
377: nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
378: PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), lineno, function, filename, (void **)&inew));
380: head = (TRSPACE *)inew;
381: inew += sizeof(TrSPACE);
383: if (TRhead) TRhead->prev = head;
384: head->next = TRhead;
385: TRhead = head;
386: head->prev = NULL;
387: head->size = nsize;
388: head->rsize = len;
389: head->id = TRid++;
390: head->lineno = lineno;
392: head->filename = filename;
393: head->functionname = function;
394: head->specialcookie = COOKIE_VALUE;
395: *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
397: TRallocated += TRrequestedSize ? head->rsize : head->size;
398: if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
399: if (PetscLogMemory) {
400: for (PetscInt i = 0; i < NumTRMaxMems; i++) {
401: if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
402: }
403: }
405: #if PetscDefined(USE_DEBUG)
406: PetscCall(PetscStackCopy(&petscstack, &head->stack));
407: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
408: if (head->stack.currentsize > 1 && head->stack.currentsize - 2 < PETSCSTACKSIZE) head->stack.line[head->stack.currentsize - 2] = lineno;
409: head->stack.currentsize--;
410: #endif
412: /*
413: Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
414: and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
415: */
416: if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
417: if (!PetscLogMalloc) {
418: PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
419: PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
421: PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
422: PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
424: PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
425: PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
426: }
427: PetscLogMallocLength[PetscLogMalloc] = nsize;
428: PetscLogMallocFile[PetscLogMalloc] = filename;
429: PetscLogMallocFunction[PetscLogMalloc++] = function;
430: }
431: *result = (void *)inew;
432: PetscFunctionReturn(PETSC_SUCCESS);
433: }
435: /*@
436: PetscMemoryView - Shows the amount of memory currently being used in a communicator.
438: Collective
440: Input Parameters:
441: + viewer - the viewer to output the information on
442: - message - string printed before values
444: Options Database Keys:
445: + -malloc_debug (true|false) - have PETSc track how much memory it has allocated
446: . -log_view_memory (true|false) - print memory usage per event when `-log_view` is used
447: - -memory_view (true|false) - during `PetscFinalize()` have this routine called with `PETSC_VIEWER_STDOUT_WORLD`
449: Level: intermediate
451: .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
452: @*/
453: PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
454: {
455: PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
456: PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
457: MPI_Comm comm;
459: PetscFunctionBegin;
460: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
461: PetscCall(PetscMallocGetCurrentUsage(&allocated));
462: PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
463: PetscCall(PetscMemoryGetCurrentUsage(&resident));
464: PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
465: if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
466: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
467: PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
468: if (resident && residentmax && allocated) {
469: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
470: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
471: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
472: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
473: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
474: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
475: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
476: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
477: PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
478: PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
479: PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
480: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
481: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
482: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
483: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
484: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
485: } else if (resident && residentmax) {
486: PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
487: PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
488: PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
489: PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
490: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
491: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
492: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
493: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
494: } else if (resident && allocated) {
495: PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
496: PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
497: PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
498: PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
499: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
500: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
501: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
502: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
503: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
504: } else if (allocated) {
505: PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
506: PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
507: PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
508: PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
509: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
510: PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
511: } else {
512: PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
513: }
514: PetscCall(PetscViewerFlush(viewer));
515: PetscFunctionReturn(PETSC_SUCCESS);
516: }
518: /*@
519: PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
521: Not Collective
523: Output Parameter:
524: . space - number of bytes currently allocated
526: Level: intermediate
528: Note:
529: This only works if `-memory_view` or `-log_view_memory` have been used
531: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
532: `PetscMemoryGetMaximumUsage()`
533: @*/
534: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
535: {
536: PetscFunctionBegin;
537: *space = (PetscLogDouble)TRallocated;
538: PetscFunctionReturn(PETSC_SUCCESS);
539: }
541: /*@
542: PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
543: during this run, the high water mark.
545: Not Collective
547: Output Parameter:
548: . space - maximum number of bytes ever allocated at one time
550: Level: intermediate
552: Note:
553: This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
555: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
556: `PetscMallocPushMaximumUsage()`
557: @*/
558: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
559: {
560: PetscFunctionBegin;
561: *space = (PetscLogDouble)TRMaxMem;
562: PetscFunctionReturn(PETSC_SUCCESS);
563: }
565: /*@
566: PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
568: Not Collective
570: Input Parameter:
571: . event - an event id; this is just for error checking
573: Level: developer
575: Note:
576: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
578: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
579: `PetscMallocPopMaximumUsage()`
580: @*/
581: PetscErrorCode PetscMallocPushMaximumUsage(int event)
582: {
583: PetscFunctionBegin;
584: if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
585: TRMaxMems[NumTRMaxMems - 1] = TRallocated;
586: TRMaxMemsEvents[NumTRMaxMems - 1] = event;
587: PetscFunctionReturn(PETSC_SUCCESS);
588: }
590: /*@
591: PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
593: Not Collective
595: Input Parameter:
596: . event - an event id; this is just for error checking
598: Output Parameter:
599: . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
601: Level: developer
603: Note:
604: This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
606: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
607: `PetscMallocPushMaximumUsage()`
608: @*/
609: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
610: {
611: PetscFunctionBegin;
612: *mu = 0;
613: if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
614: PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
615: *mu = (PetscLogDouble)TRMaxMems[NumTRMaxMems];
616: PetscFunctionReturn(PETSC_SUCCESS);
617: }
619: /*@
620: PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
622: Not Collective, No Fortran Support
624: Input Parameter:
625: . ptr - the memory location
627: Output Parameter:
628: . stack - the stack indicating where the program allocated this memory, or `NULL` if unavailable
630: Level: intermediate
632: Note:
633: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
635: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
636: @*/
637: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
638: {
639: #if PetscDefined(USE_DEBUG)
640: TRSPACE *head;
642: PetscFunctionBegin;
643: *stack = NULL;
644: if (PetscTrMalloc != PetscTrMallocDefault) PetscFunctionReturn(PETSC_SUCCESS);
645: head = (TRSPACE *)((char *)ptr - HEADER_BYTES);
646: *stack = &head->stack;
647: PetscFunctionReturn(PETSC_SUCCESS);
648: #else
649: *stack = NULL;
650: return PETSC_SUCCESS;
651: #endif
652: }
654: /*@
655: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
656: printed is: size of space (in bytes), address of space, id of space,
657: file in which space was allocated, and line number at which it was
658: allocated.
660: Not Collective
662: Input Parameter:
663: . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed.
665: Options Database Key:
666: . -malloc_dump [filename] - Print summary of unfreed memory during call to `PetscFinalize()`, writing to `filename` if given otherwise `stdout`
668: Level: intermediate
670: Notes:
671: Uses `MPI_COMM_WORLD` to display the MPI rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
673: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
675: `PetscMallocView()` prints a list of all memory ever allocated
677: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
679: Fortran Notes:
680: The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
682: Developer Notes:
683: This should be absorbed into `PetscMallocView()`
685: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
686: @*/
687: PetscErrorCode PetscMallocDump(FILE *fp)
688: {
689: TRSPACE *head;
690: size_t libAlloc = 0;
691: PetscMPIInt rank;
693: PetscFunctionBegin;
694: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
695: if (!fp) fp = PETSC_STDOUT;
696: head = TRhead;
697: while (head) {
698: libAlloc += TRrequestedSize ? head->rsize : head->size;
699: head = head->next;
700: }
701: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
702: head = TRhead;
703: while (head) {
704: PetscBool isLib;
706: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
707: if (!isLib) {
708: #if PetscDefined(USE_DEBUG)
709: fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
710: PetscCall(PetscStackPrint(&head->stack, fp));
711: #else
712: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
713: #endif
714: }
715: head = head->next;
716: }
717: PetscFunctionReturn(PETSC_SUCCESS);
718: }
720: /*@
721: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
723: Not Collective
725: Input Parameter:
726: . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
728: Options Database Keys:
729: + -malloc_view [filename] - Activates `PetscMallocView()` in `PetscFinalize()`
730: . -malloc_view_threshold logmin - Sets a minimum size if `-malloc_view` is used
731: - -log_view_memory (true|false) - View the memory usage also with the `-log_view` option
733: Level: advanced
735: Note:
736: Must be called after `PetscMallocSetDebug()`
738: Developer Notes:
739: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
741: .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
742: @*/
743: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
744: {
745: PetscFunctionBegin;
746: PetscLogMalloc = 0;
747: PetscCall(PetscMemorySetGetMaximumUsage());
748: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
749: PetscLogMallocThreshold = (size_t)logmin;
750: PetscFunctionReturn(PETSC_SUCCESS);
751: }
753: /*@
754: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
756: Not Collective
758: Output Parameter:
759: . logging - `PETSC_TRUE` if logging is active
761: Level: advanced
763: .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
764: @*/
765: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
766: {
767: PetscFunctionBegin;
768: *logging = (PetscBool)(PetscLogMalloc >= 0);
769: PetscFunctionReturn(PETSC_SUCCESS);
770: }
772: /*@
773: PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
775: Not Collective
777: Input Parameters:
778: + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
779: . active - Flag to activate or deactivate tracing
780: - logmin - The smallest memory size that will be logged
782: Level: advanced
784: Note:
785: The viewer should not be collective.
787: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
789: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
790: @*/
791: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
792: {
793: PetscFunctionBegin;
794: if (!active) {
795: PetscLogMallocTrace = -1;
796: PetscFunctionReturn(PETSC_SUCCESS);
797: }
798: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
800: PetscLogMallocTraceViewer = viewer;
801: PetscLogMallocTrace = 0;
802: PetscCall(PetscMemorySetGetMaximumUsage());
803: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
804: PetscLogMallocTraceThreshold = (size_t)logmin;
805: PetscFunctionReturn(PETSC_SUCCESS);
806: }
808: /*@
809: PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
811: Not Collective
813: Output Parameter:
814: . logging - `PETSC_TRUE` if logging is active
816: Level: advanced
818: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
820: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
821: @*/
822: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
823: {
824: PetscFunctionBegin;
825: *logging = (PetscBool)(PetscLogMallocTrace >= 0);
826: PetscFunctionReturn(PETSC_SUCCESS);
827: }
829: /*@
830: PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
832: Not Collective
834: Input Parameter:
835: . fp - file pointer; or `NULL`
837: Options Database Key:
838: . -malloc_view [filename] - Activates `PetscMallocView()` in `PetscFinalize()`
840: Level: advanced
842: Notes:
843: `PetscMallocDump()` dumps only the currently unfreed memory, this routine dumps all memory ever allocated
845: `PetscMemoryView()` gives a brief summary of current memory usage
847: Fortran Notes:
848: The calling sequence in Fortran is `PetscMallocView`(integer ierr) and can only write to `stdout`
850: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
851: @*/
852: PetscErrorCode PetscMallocView(FILE *fp)
853: {
854: PetscInt n, *perm;
855: size_t *shortlength;
856: int *shortcount;
857: PetscMPIInt rank;
858: PetscBool match;
859: const char **shortfunction;
860: PetscLogDouble rss;
862: PetscFunctionBegin;
863: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
864: PetscCall(PetscFFlush(fp));
866: 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()");
868: if (!fp) fp = PETSC_STDOUT;
869: PetscCall(PetscMemoryGetMaximumUsage(&rss));
870: if (rss) {
871: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
872: } else {
873: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
874: }
875: if (PetscLogMalloc > 0) {
876: shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
877: PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
878: shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
879: PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
880: shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
881: PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
882: n = 0;
883: for (PetscInt i = 0; i < PetscLogMalloc; i++) {
884: for (PetscInt j = 0; j < n; j++) {
885: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
886: if (match) {
887: shortlength[j] += PetscLogMallocLength[i];
888: shortcount[j]++;
889: goto foundit;
890: }
891: }
892: shortfunction[n] = PetscLogMallocFunction[i];
893: shortlength[n] = PetscLogMallocLength[i];
894: shortcount[n] = 1;
895: n++;
896: foundit:;
897: }
899: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
900: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
901: for (PetscInt i = 0; i < n; i++) perm[i] = i;
902: PetscCall(PetscSortStrWithPermutation(n, shortfunction, perm));
904: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
905: 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]]);
906: free(perm);
907: free(shortlength);
908: free(shortcount);
909: free((char **)shortfunction);
910: }
911: PetscCall(PetscFFlush(fp));
912: PetscFunctionReturn(PETSC_SUCCESS);
913: }
915: /*@
916: PetscMallocSetDebug - Set's PETSc memory debugging
918: Not Collective
920: Input Parameters:
921: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
922: - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
924: Options Database Keys:
925: + -malloc_debug (true|false) - turns on or off debugging
926: . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
927: . -malloc_view_threshold logmin - log only allocations larger than `logmin`
928: - -malloc_dump [filename] - print a list of all memory that has not been freed, in `PetscFinalize()`
930: Level: developer
932: Note:
933: This is called in `PetscInitialize()` and should not be called elsewhere
935: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
936: @*/
937: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
938: {
939: PetscFunctionBegin;
940: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
941: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
943: TRallocated = 0;
944: TRhead = NULL;
945: TRid = 0;
946: TRdebug = eachcall;
947: TRMaxMem = 0;
948: PetscLogMallocMax = 10000;
949: PetscLogMalloc = -1;
950: TRdebugIinitializenan = initializenan;
951: PetscFunctionReturn(PETSC_SUCCESS);
952: }
954: /*@
955: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
957: Not Collective
959: Output Parameters:
960: + basic - doing basic debugging
961: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
962: - initializenan - initializes memory with `NaN`
964: Level: intermediate
966: Note:
967: By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
969: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
970: @*/
971: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
972: {
973: PetscFunctionBegin;
974: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
975: if (eachcall) *eachcall = TRdebug;
976: if (initializenan) *initializenan = TRdebugIinitializenan;
977: PetscFunctionReturn(PETSC_SUCCESS);
978: }
980: /*@
981: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
983: Not Collective
985: Input Parameter:
986: . flg - `PETSC_TRUE` to log the requested memory size
988: Options Database Key:
989: . -malloc_requested_size (true|false) - Sets this flag
991: Level: developer
993: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
994: @*/
995: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
996: {
997: PetscFunctionBegin;
998: TRrequestedSize = flg;
999: PetscFunctionReturn(PETSC_SUCCESS);
1000: }
1002: /*@
1003: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1005: Not Collective
1007: Output Parameter:
1008: . flg - `PETSC_TRUE` if we log the requested memory size
1010: Level: developer
1012: .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1013: @*/
1014: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1015: {
1016: PetscFunctionBegin;
1017: *flg = TRrequestedSize;
1018: PetscFunctionReturn(PETSC_SUCCESS);
1019: }