Actual source code: mtr.c
1: /*
2: Logging of memory usage and some error checking
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
6: #if defined(PETSC_HAVE_MALLOC_H)
7: #include <malloc.h>
8: #endif
10: /*
11: These are defined in mal.c and ensure that malloced space is PetscScalar aligned
12: */
13: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
14: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
15: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
17: #define 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 defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
29: PetscStack stack;
30: #endif
31: struct _trSPACE *next, *prev;
32: } TRSPACE;
34: /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
35: It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
36: */
37: #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
39: /* This union is used to insure that the block passed to the user retains
40: a minimum alignment of PETSC_MEMALIGN.
41: */
42: typedef union
43: {
44: TRSPACE sp;
45: char v[HEADER_BYTES];
46: } TrSPACE;
48: #define MAXTRMAXMEMS 50
49: static size_t TRallocated = 0;
50: static 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: /*@C
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 - 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 defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
202: PetscCall(PetscStackCopy(&petscstack, &head->stack));
203: /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
204: head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
205: head->stack.currentsize--;
206: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_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 defined(PETSC_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 defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
407: PetscCall(PetscStackCopy(&petscstack, &head->stack));
408: /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
409: head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
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: /*@C
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 - have PETSc track how much memory it has allocated
446: . -log_view_memory - print memory usage per event when `-log_view` is used
447: - -memory_view - during `PetscFinalize()` have this routine called
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: /*@C
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
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 defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
640: TRSPACE *head;
642: PetscFunctionBegin;
643: head = (TRSPACE *)((char *)ptr - HEADER_BYTES);
644: *stack = &head->stack;
645: PetscFunctionReturn(PETSC_SUCCESS);
646: #else
647: *stack = NULL;
648: return PETSC_SUCCESS;
649: #endif
650: }
652: /*@C
653: PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
654: printed is: size of space (in bytes), address of space, id of space,
655: file in which space was allocated, and line number at which it was
656: allocated.
658: Not Collective
660: Input Parameter:
661: . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed.
663: Options Database Key:
664: . -malloc_dump optional filename - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
666: Level: intermediate
668: Notes:
669: Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
671: When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
673: `PetscMallocView()` prints a list of all memory ever allocated
675: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
677: Fortran Notes:
678: The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
680: Developer Notes:
681: This should be absorbed into `PetscMallocView()`
683: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
684: @*/
685: PetscErrorCode PetscMallocDump(FILE *fp)
686: {
687: TRSPACE *head;
688: size_t libAlloc = 0;
689: PetscMPIInt rank;
691: PetscFunctionBegin;
692: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
693: if (!fp) fp = PETSC_STDOUT;
694: head = TRhead;
695: while (head) {
696: libAlloc += TRrequestedSize ? head->rsize : head->size;
697: head = head->next;
698: }
699: if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
700: head = TRhead;
701: while (head) {
702: PetscBool isLib;
704: PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
705: if (!isLib) {
706: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
707: fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
708: PetscCall(PetscStackPrint(&head->stack, fp));
709: #else
710: fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
711: #endif
712: }
713: head = head->next;
714: }
715: PetscFunctionReturn(PETSC_SUCCESS);
716: }
718: /*@
719: PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
721: Not Collective
723: Input Parameter:
724: . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
726: Options Database Keys:
727: + -malloc_view optional filename - Activates `PetscMallocView()` in `PetscFinalize()`
728: . -malloc_view_threshold min - Sets a minimum size if `-malloc_view` is used
729: - -log_view_memory - view the memory usage also with the -log_view option
731: Level: advanced
733: Note:
734: Must be called after `PetscMallocSetDebug()`
736: Developer Notes:
737: Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
739: .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
740: @*/
741: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
742: {
743: PetscFunctionBegin;
744: PetscLogMalloc = 0;
745: PetscCall(PetscMemorySetGetMaximumUsage());
746: if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
747: PetscLogMallocThreshold = (size_t)logmin;
748: PetscFunctionReturn(PETSC_SUCCESS);
749: }
751: /*@
752: PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
754: Not Collective
756: Output Parameter:
757: . logging - `PETSC_TRUE` if logging is active
759: Options Database Key:
760: . -malloc_view optional filename - Activates `PetscMallocView()`
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: Options Database Key:
818: . -malloc_view optional filename - Activates `PetscMallocView()`
820: Level: advanced
822: This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
824: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
825: @*/
826: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
827: {
828: PetscFunctionBegin;
829: *logging = (PetscBool)(PetscLogMallocTrace >= 0);
830: PetscFunctionReturn(PETSC_SUCCESS);
831: }
833: /*@C
834: PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
836: Not Collective
838: Input Parameter:
839: . fp - file pointer; or `NULL`
841: Options Database Key:
842: . -malloc_view optional filename - Activates `PetscMallocView()` in `PetscFinalize()`
844: Level: advanced
846: Notes:
847: `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
849: `PetscMemoryView()` gives a brief summary of current memory usage
851: Fortran Notes:
852: The calling sequence in Fortran is `PetscMallocView`(integer ierr)
854: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
855: @*/
856: PetscErrorCode PetscMallocView(FILE *fp)
857: {
858: PetscInt n, *perm;
859: size_t *shortlength;
860: int *shortcount;
861: PetscMPIInt rank;
862: PetscBool match;
863: const char **shortfunction;
864: PetscLogDouble rss;
866: PetscFunctionBegin;
867: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
868: PetscCall(PetscFFlush(fp));
870: 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()");
872: if (!fp) fp = PETSC_STDOUT;
873: PetscCall(PetscMemoryGetMaximumUsage(&rss));
874: if (rss) {
875: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
876: } else {
877: (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
878: }
879: if (PetscLogMalloc > 0) {
880: shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
881: PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
882: shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
883: PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
884: shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
885: PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
886: n = 0;
887: for (PetscInt i = 0; i < PetscLogMalloc; i++) {
888: for (PetscInt j = 0; j < n; j++) {
889: PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
890: if (match) {
891: shortlength[j] += PetscLogMallocLength[i];
892: shortcount[j]++;
893: goto foundit;
894: }
895: }
896: shortfunction[n] = PetscLogMallocFunction[i];
897: shortlength[n] = PetscLogMallocLength[i];
898: shortcount[n] = 1;
899: n++;
900: foundit:;
901: }
903: perm = (PetscInt *)malloc(n * sizeof(PetscInt));
904: PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
905: for (PetscInt i = 0; i < n; i++) perm[i] = i;
906: PetscCall(PetscSortStrWithPermutation(n, shortfunction, perm));
908: (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
909: 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]]);
910: free(perm);
911: free(shortlength);
912: free(shortcount);
913: free((char **)shortfunction);
914: }
915: PetscCall(PetscFFlush(fp));
916: PetscFunctionReturn(PETSC_SUCCESS);
917: }
919: /*@
920: PetscMallocSetDebug - Set's PETSc memory debugging
922: Not Collective
924: Input Parameters:
925: + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
926: - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
928: Options Database Keys:
929: + -malloc_debug (true|false) - turns on or off debugging
930: . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
931: . -malloc_view_threshold t - log only allocations larger than t
932: - -malloc_dump filename - print a list of all memory that has not been freed, in `PetscFinalize()`
934: Level: developer
936: Note:
937: This is called in `PetscInitialize()` and should not be called elsewhere
939: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
940: @*/
941: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
942: {
943: PetscFunctionBegin;
944: PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
945: PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
947: TRallocated = 0;
948: TRhead = NULL;
949: TRid = 0;
950: TRdebug = eachcall;
951: TRMaxMem = 0;
952: PetscLogMallocMax = 10000;
953: PetscLogMalloc = -1;
954: TRdebugIinitializenan = initializenan;
955: PetscFunctionReturn(PETSC_SUCCESS);
956: }
958: /*@
959: PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
961: Not Collective
963: Output Parameters:
964: + basic - doing basic debugging
965: . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
966: - initializenan - initializes memory with `NaN`
968: Level: intermediate
970: Note:
971: By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
973: .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
974: @*/
975: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
976: {
977: PetscFunctionBegin;
978: if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
979: if (eachcall) *eachcall = TRdebug;
980: if (initializenan) *initializenan = TRdebugIinitializenan;
981: PetscFunctionReturn(PETSC_SUCCESS);
982: }
984: /*@
985: PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
987: Not Collective
989: Input Parameter:
990: . flg - `PETSC_TRUE` to log the requested memory size
992: Options Database Key:
993: . -malloc_requested_size (true|false) - Sets this flag
995: Level: developer
997: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
998: @*/
999: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1000: {
1001: PetscFunctionBegin;
1002: TRrequestedSize = flg;
1003: PetscFunctionReturn(PETSC_SUCCESS);
1004: }
1006: /*@
1007: PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1009: Not Collective
1011: Output Parameter:
1012: . flg - `PETSC_TRUE` if we log the requested memory size
1014: Level: developer
1016: .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1017: @*/
1018: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1019: {
1020: PetscFunctionBegin;
1021: *flg = TRrequestedSize;
1022: PetscFunctionReturn(PETSC_SUCCESS);
1023: }