1e5c89e4eSSatish Balay /*
22d853995SBarry Smith Logging of memory usage and some error checking
3e5c89e4eSSatish Balay */
427104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
5665c2dedSJed Brown #include <petscviewer.h>
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
7e5c89e4eSSatish Balay #include <malloc.h>
8e5c89e4eSSatish Balay #endif
9e5c89e4eSSatish Balay
10e5c89e4eSSatish Balay /*
11e5c89e4eSSatish Balay These are defined in mal.c and ensure that malloced space is PetscScalar aligned
12e5c89e4eSSatish Balay */
13071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
1495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
16e5c89e4eSSatish Balay
17835f2295SStefano Zampini #define COOKIE_VALUE -253701943
18835f2295SStefano Zampini #define ALREADY_FREED 252579228
19e5c89e4eSSatish Balay
202d853995SBarry Smith /* this is the header put at the beginning of each PetscTrMallocDefault() for tracking allocated space and checking of allocated space heap */
21e5c89e4eSSatish Balay typedef struct _trSPACE {
22608c71bfSMatthew G. Knepley size_t size, rsize; /* Aligned size and requested size */
23e5c89e4eSSatish Balay int id;
24e5c89e4eSSatish Balay int lineno;
25e5c89e4eSSatish Balay const char *filename;
26e5c89e4eSSatish Balay const char *functionname;
27835f2295SStefano Zampini PetscInt specialcookie;
28dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
29e5c89e4eSSatish Balay PetscStack stack;
30e5c89e4eSSatish Balay #endif
31e5c89e4eSSatish Balay struct _trSPACE *next, *prev;
32e5c89e4eSSatish Balay } TRSPACE;
33e5c89e4eSSatish Balay
342d853995SBarry Smith /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
3592f119d6SBarry Smith It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3625b53cc9SJed Brown */
37a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
38e5c89e4eSSatish Balay
3925b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4025b53cc9SJed Brown a minimum alignment of PETSC_MEMALIGN.
4125b53cc9SJed Brown */
429371c9d4SSatish Balay typedef union
439371c9d4SSatish Balay {
44e5c89e4eSSatish Balay TRSPACE sp;
4525b53cc9SJed Brown char v[HEADER_BYTES];
46e5c89e4eSSatish Balay } TrSPACE;
47e5c89e4eSSatish Balay
48e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
49e5c89e4eSSatish Balay static size_t TRallocated = 0;
50e5c89e4eSSatish Balay static int TRfrags = 0;
51f0ba7cfcSLisandro Dalcin static TRSPACE *TRhead = NULL;
52e5c89e4eSSatish Balay static int TRid = 0;
532d853995SBarry Smith static PetscBool TRdebug = PETSC_FALSE;
542d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE;
55608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize = PETSC_FALSE;
56e5c89e4eSSatish Balay static size_t TRMaxMem = 0;
57e3ed9ee7SBarry Smith static int NumTRMaxMems = 0;
58e3ed9ee7SBarry Smith static size_t TRMaxMems[MAXTRMAXMEMS];
59e3ed9ee7SBarry Smith static int TRMaxMemsEvents[MAXTRMAXMEMS];
60e5c89e4eSSatish Balay /*
6192f119d6SBarry Smith Arrays to log information on mallocs for PetscMallocView()
62e5c89e4eSSatish Balay */
63f0ba7cfcSLisandro Dalcin static int PetscLogMallocMax = 10000;
64f0ba7cfcSLisandro Dalcin static int PetscLogMalloc = -1;
65574034a9SJed Brown static size_t PetscLogMallocThreshold = 0;
66e5c89e4eSSatish Balay static size_t *PetscLogMallocLength;
67efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction;
68608c71bfSMatthew G. Knepley static int PetscLogMallocTrace = -1;
69608c71bfSMatthew G. Knepley static size_t PetscLogMallocTraceThreshold = 0;
70608c71bfSMatthew G. Knepley static PetscViewer PetscLogMallocTraceViewer = NULL;
71b022a5c1SBarry Smith
72e5c89e4eSSatish Balay /*@C
73811af0c4SBarry Smith PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
74e5c89e4eSSatish Balay
7592f119d6SBarry Smith Input Parameters:
76e5c89e4eSSatish Balay + line - line number where call originated.
77e5c89e4eSSatish Balay . function - name of function calling
78efca3c55SSatish Balay - file - file where function is
79e5c89e4eSSatish Balay
8010450e9eSJacob Faibussowitsch Options Database Keys:
810ed210f4SBarry Smith + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0`
8292f119d6SBarry Smith - -malloc_debug - turns this feature on anytime
8392f119d6SBarry Smith
84e5c89e4eSSatish Balay Level: advanced
85e5c89e4eSSatish Balay
86e5c89e4eSSatish Balay Notes:
872d853995SBarry Smith You should generally use `CHKMEMQ` as a short cut for calling this routine.
882d853995SBarry Smith
890ed210f4SBarry Smith Error messages are written to `stdout`.
900ed210f4SBarry Smith
910ed210f4SBarry Smith 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)
9238548759SBarry Smith
93e5c89e4eSSatish Balay No output is generated if there are no problems detected.
94e5c89e4eSSatish Balay
95aec76313SJacob Faibussowitsch Fortran Notes:
9620f4b53cSBarry Smith The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
9720f4b53cSBarry Smith
980ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
99e5c89e4eSSatish Balay @*/
PetscMallocValidate(int line,const char function[],const char file[])100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
101d71ae5a4SJacob Faibussowitsch {
1026c093d5bSvictor TRSPACE *head, *lasthead;
103e5c89e4eSSatish Balay char *a;
104835f2295SStefano Zampini PetscInt *nend;
105e5c89e4eSSatish Balay
1062d853995SBarry Smith if (!TRdebug) return PETSC_SUCCESS;
1079371c9d4SSatish Balay head = TRhead;
1089371c9d4SSatish Balay lasthead = NULL;
1092cba8197SMatthew G. Knepley if (head && head->prev) {
1102d853995SBarry Smith TRdebug = PETSC_FALSE;
1113ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1123ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1134ed0ab5bSBarry Smith return PETSC_ERR_MEMC;
1142cba8197SMatthew G. Knepley }
115e5c89e4eSSatish Balay while (head) {
116835f2295SStefano Zampini if (head->specialcookie != COOKIE_VALUE) {
1172d853995SBarry Smith TRdebug = PETSC_FALSE;
1183ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1193ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1203ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
121e269983cSBarry Smith if (lasthead) {
122e269983cSBarry Smith a = (char *)(((TrSPACE *)head) + 1);
1233ba16761SJacob Faibussowitsch 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));
124e269983cSBarry Smith }
125e269983cSBarry Smith abort();
1264ed0ab5bSBarry Smith return PETSC_ERR_MEMC;
127e5c89e4eSSatish Balay }
128e5c89e4eSSatish Balay a = (char *)(((TrSPACE *)head) + 1);
129835f2295SStefano Zampini nend = (PetscInt *)(a + head->size);
130835f2295SStefano Zampini if (*nend != COOKIE_VALUE) {
1312d853995SBarry Smith TRdebug = PETSC_FALSE;
1323ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
133e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) {
1343ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1354ed0ab5bSBarry Smith return PETSC_ERR_MEMC;
136e5c89e4eSSatish Balay } else {
1373ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
1383ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1394ed0ab5bSBarry Smith return PETSC_ERR_MEMC;
140e5c89e4eSSatish Balay }
141e5c89e4eSSatish Balay }
1422cba8197SMatthew G. Knepley if (head->prev && head->prev != lasthead) {
1432d853995SBarry Smith TRdebug = PETSC_FALSE;
1443ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1453ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
1463ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
1473ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1484ed0ab5bSBarry Smith return PETSC_ERR_MEMC;
1492cba8197SMatthew G. Knepley }
1506c093d5bSvictor lasthead = head;
151e5c89e4eSSatish Balay head = head->next;
152e5c89e4eSSatish Balay }
1533ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
154e5c89e4eSSatish Balay }
155e5c89e4eSSatish Balay
156e5c89e4eSSatish Balay /*
1572d853995SBarry Smith PetscTrMallocDefault - Malloc with logging and error checking
158e5c89e4eSSatish Balay
159e5c89e4eSSatish Balay */
PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void ** result)16066976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
161d71ae5a4SJacob Faibussowitsch {
162e5c89e4eSSatish Balay TRSPACE *head;
163e5c89e4eSSatish Balay char *inew;
164e5c89e4eSSatish Balay size_t nsize;
165e5c89e4eSSatish Balay
166e5c89e4eSSatish Balay PetscFunctionBegin;
1679371c9d4SSatish Balay if (!a) {
1689371c9d4SSatish Balay *result = NULL;
1693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1709371c9d4SSatish Balay }
171f0ba7cfcSLisandro Dalcin
17211cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename));
173e5c89e4eSSatish Balay
17425b53cc9SJed Brown nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
175835f2295SStefano Zampini PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), clear, lineno, function, filename, (void **)&inew));
176e3ed9ee7SBarry Smith
177e5c89e4eSSatish Balay head = (TRSPACE *)inew;
178e5c89e4eSSatish Balay inew += sizeof(TrSPACE);
179e5c89e4eSSatish Balay
180e5c89e4eSSatish Balay if (TRhead) TRhead->prev = head;
181e5c89e4eSSatish Balay head->next = TRhead;
182e5c89e4eSSatish Balay TRhead = head;
183f0ba7cfcSLisandro Dalcin head->prev = NULL;
184e5c89e4eSSatish Balay head->size = nsize;
185608c71bfSMatthew G. Knepley head->rsize = a;
186e269983cSBarry Smith head->id = TRid++;
187e5c89e4eSSatish Balay head->lineno = lineno;
188e5c89e4eSSatish Balay
189e5c89e4eSSatish Balay head->filename = filename;
190e5c89e4eSSatish Balay head->functionname = function;
191835f2295SStefano Zampini head->specialcookie = COOKIE_VALUE;
192835f2295SStefano Zampini *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
193e5c89e4eSSatish Balay
194608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size;
195a297a907SKarl Rupp if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
196e3ed9ee7SBarry Smith if (PetscLogMemory) {
1972d853995SBarry Smith for (PetscInt i = 0; i < NumTRMaxMems; i++) {
198e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
199e3ed9ee7SBarry Smith }
200e3ed9ee7SBarry Smith }
201e5c89e4eSSatish Balay TRfrags++;
202e5c89e4eSSatish Balay
203dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2049566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack));
2052d853995SBarry Smith /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
20653dcd878SStefano Zampini head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
2072d853995SBarry Smith head->stack.currentsize--;
20892f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2092d4ee042Sprj- if (!clear && TRdebugIinitializenan) {
2102d853995SBarry Smith size_t n = a / sizeof(PetscReal);
21192f119d6SBarry Smith PetscReal *s = (PetscReal *)inew;
21292f119d6SBarry Smith /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
21392f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
214df282883SBarry Smith int nas = 0x7F800002;
21592f119d6SBarry Smith #else
21692f119d6SBarry Smith PetscInt64 nas = 0x7FF0000000000002;
21792f119d6SBarry Smith #endif
2182d853995SBarry Smith for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
21992f119d6SBarry Smith }
22092f119d6SBarry Smith #endif
221e5c89e4eSSatish Balay #endif
222e5c89e4eSSatish Balay
223e5c89e4eSSatish Balay /*
22492f119d6SBarry Smith Allow logging of all mallocs made.
22592f119d6SBarry Smith TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
226e5c89e4eSSatish Balay */
227574034a9SJed Brown if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
228e5c89e4eSSatish Balay if (!PetscLogMalloc) {
229e5c89e4eSSatish Balay PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
23028b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
231a297a907SKarl Rupp
232a2ea699eSBarry Smith PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23328b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
234a297a907SKarl Rupp
235a2ea699eSBarry Smith PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23628b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
237e5c89e4eSSatish Balay }
238e5c89e4eSSatish Balay PetscLogMallocLength[PetscLogMalloc] = nsize;
239e5c89e4eSSatish Balay PetscLogMallocFile[PetscLogMalloc] = filename;
240e5c89e4eSSatish Balay PetscLogMallocFunction[PetscLogMalloc++] = function;
241e5c89e4eSSatish Balay }
24248a46eb9SPierre Jolivet if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
243e5c89e4eSSatish Balay *result = (void *)inew;
2443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
245e5c89e4eSSatish Balay }
246e5c89e4eSSatish Balay
247e5c89e4eSSatish Balay /*
2482d853995SBarry Smith PetscTrFreeDefault - Free with logging and error checking
249e5c89e4eSSatish Balay
250e5c89e4eSSatish Balay */
PetscTrFreeDefault(void * aa,int lineno,const char function[],const char filename[])25166976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
252d71ae5a4SJacob Faibussowitsch {
253e5c89e4eSSatish Balay char *a = (char *)aa;
254e5c89e4eSSatish Balay TRSPACE *head;
255e5c89e4eSSatish Balay char *ahead;
256608c71bfSMatthew G. Knepley size_t asize;
257835f2295SStefano Zampini PetscInt *nend;
258e5c89e4eSSatish Balay
259e5c89e4eSSatish Balay PetscFunctionBegin;
2603ba16761SJacob Faibussowitsch if (!a) PetscFunctionReturn(PETSC_SUCCESS);
261e5c89e4eSSatish Balay
2629566063dSJacob Faibussowitsch PetscCall(PetscMallocValidate(lineno, function, filename));
263e5c89e4eSSatish Balay
264e5c89e4eSSatish Balay ahead = a;
265e5c89e4eSSatish Balay a = a - sizeof(TrSPACE);
266e5c89e4eSSatish Balay head = (TRSPACE *)a;
267e5c89e4eSSatish Balay
268835f2295SStefano Zampini if (head->specialcookie != COOKIE_VALUE) {
2692d853995SBarry Smith TRdebug = PETSC_FALSE;
2703ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2713ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
272e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
273e5c89e4eSSatish Balay }
274835f2295SStefano Zampini nend = (PetscInt *)(ahead + head->size);
275835f2295SStefano Zampini if (*nend != COOKIE_VALUE) {
2762d853995SBarry Smith TRdebug = PETSC_FALSE;
277e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) {
2783ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2793ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
280e5c89e4eSSatish Balay if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2813ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
282e5c89e4eSSatish Balay } else {
2833ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
284e5c89e4eSSatish Balay }
285e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
286e5c89e4eSSatish Balay } else {
287e5c89e4eSSatish Balay /* Damaged tail */
2883ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2893ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
2903ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
291e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
292e5c89e4eSSatish Balay }
293e5c89e4eSSatish Balay }
294*3a7d0413SPierre Jolivet if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
295e5c89e4eSSatish Balay *nend = ALREADY_FREED;
296e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */
297608c71bfSMatthew G. Knepley if (lineno > 0 && lineno < 50000) {
298608c71bfSMatthew G. Knepley head->lineno = lineno;
299608c71bfSMatthew G. Knepley head->filename = filename;
300e5c89e4eSSatish Balay head->functionname = function;
301e5c89e4eSSatish Balay } else {
302e5c89e4eSSatish Balay head->lineno = -head->lineno;
303e5c89e4eSSatish Balay }
304608c71bfSMatthew G. Knepley asize = TRrequestedSize ? head->rsize : head->size;
30508401ef6SPierre Jolivet PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
306608c71bfSMatthew G. Knepley TRallocated -= asize;
307e5c89e4eSSatish Balay TRfrags--;
308e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next;
309e5c89e4eSSatish Balay else TRhead = head->next;
310e5c89e4eSSatish Balay
311e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev;
3129566063dSJacob Faibussowitsch PetscCall(PetscFreeAlign(a, lineno, function, filename));
3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
314e5c89e4eSSatish Balay }
315e5c89e4eSSatish Balay
3163221ece2SMatthew G. Knepley /*
3172d853995SBarry Smith PetscTrReallocDefault - Realloc with logging and error checking
3183221ece2SMatthew G. Knepley
3193221ece2SMatthew G. Knepley */
PetscTrReallocDefault(size_t len,int lineno,const char function[],const char filename[],void ** result)32066976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
321d71ae5a4SJacob Faibussowitsch {
3223221ece2SMatthew G. Knepley char *a = (char *)*result;
3233221ece2SMatthew G. Knepley TRSPACE *head;
3243221ece2SMatthew G. Knepley char *ahead, *inew;
325835f2295SStefano Zampini PetscInt *nend;
3263221ece2SMatthew G. Knepley size_t nsize;
3273221ece2SMatthew G. Knepley
3283221ece2SMatthew G. Knepley PetscFunctionBegin;
32992f119d6SBarry Smith /* Realloc requests zero space so just free the current space */
330c22f1541SToby Isaac if (!len) {
3319566063dSJacob Faibussowitsch PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
332c22f1541SToby Isaac *result = NULL;
3333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
334c22f1541SToby Isaac }
335da81f932SPierre Jolivet /* If the original space was NULL just use the regular malloc() */
336f590eff4SLisandro Dalcin if (!*result) {
3379566063dSJacob Faibussowitsch PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
339f590eff4SLisandro Dalcin }
3403221ece2SMatthew G. Knepley
34111cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename));
3423221ece2SMatthew G. Knepley
3433221ece2SMatthew G. Knepley ahead = a;
3443221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE);
3453221ece2SMatthew G. Knepley head = (TRSPACE *)a;
3463221ece2SMatthew G. Knepley inew = a;
3473221ece2SMatthew G. Knepley
348835f2295SStefano Zampini if (head->specialcookie != COOKIE_VALUE) {
3492d853995SBarry Smith TRdebug = PETSC_FALSE;
3503ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3513ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3523221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3533221ece2SMatthew G. Knepley }
354835f2295SStefano Zampini nend = (PetscInt *)(ahead + head->size);
355835f2295SStefano Zampini if (*nend != COOKIE_VALUE) {
3562d853995SBarry Smith TRdebug = PETSC_FALSE;
3573221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) {
3583ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3593ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3603221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3613ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3623221ece2SMatthew G. Knepley } else {
3633ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3643221ece2SMatthew G. Knepley }
3653221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3663221ece2SMatthew G. Knepley } else {
3673221ece2SMatthew G. Knepley /* Damaged tail */
3683ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3693ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
3703ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3713221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3723221ece2SMatthew G. Knepley }
3733221ece2SMatthew G. Knepley }
3743221ece2SMatthew G. Knepley
37592f119d6SBarry Smith /* remove original reference to the memory allocated from the PETSc debugging heap */
376608c71bfSMatthew G. Knepley TRallocated -= TRrequestedSize ? head->rsize : head->size;
3773221ece2SMatthew G. Knepley TRfrags--;
3783221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next;
3793221ece2SMatthew G. Knepley else TRhead = head->next;
3803221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev;
3813221ece2SMatthew G. Knepley
3823221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
383835f2295SStefano Zampini PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), lineno, function, filename, (void **)&inew));
3843221ece2SMatthew G. Knepley
3853221ece2SMatthew G. Knepley head = (TRSPACE *)inew;
3863221ece2SMatthew G. Knepley inew += sizeof(TrSPACE);
3873221ece2SMatthew G. Knepley
3883221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head;
3893221ece2SMatthew G. Knepley head->next = TRhead;
3903221ece2SMatthew G. Knepley TRhead = head;
3913221ece2SMatthew G. Knepley head->prev = NULL;
3923221ece2SMatthew G. Knepley head->size = nsize;
393608c71bfSMatthew G. Knepley head->rsize = len;
394e269983cSBarry Smith head->id = TRid++;
3953221ece2SMatthew G. Knepley head->lineno = lineno;
3963221ece2SMatthew G. Knepley
3973221ece2SMatthew G. Knepley head->filename = filename;
3983221ece2SMatthew G. Knepley head->functionname = function;
399835f2295SStefano Zampini head->specialcookie = COOKIE_VALUE;
400835f2295SStefano Zampini *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
4013221ece2SMatthew G. Knepley
402608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size;
4033221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
404e3ed9ee7SBarry Smith if (PetscLogMemory) {
4052d853995SBarry Smith for (PetscInt i = 0; i < NumTRMaxMems; i++) {
406e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
407e3ed9ee7SBarry Smith }
408e3ed9ee7SBarry Smith }
4093221ece2SMatthew G. Knepley TRfrags++;
4103221ece2SMatthew G. Knepley
411dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4129566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack));
4133221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
41453dcd878SStefano Zampini head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
4153221ece2SMatthew G. Knepley #endif
4163221ece2SMatthew G. Knepley
4173221ece2SMatthew G. Knepley /*
41892f119d6SBarry Smith Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
41992f119d6SBarry Smith and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4203221ece2SMatthew G. Knepley */
4213221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4223221ece2SMatthew G. Knepley if (!PetscLogMalloc) {
4233221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
42428b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4253221ece2SMatthew G. Knepley
4263221ece2SMatthew G. Knepley PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
42728b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4283221ece2SMatthew G. Knepley
4293221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
43028b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4313221ece2SMatthew G. Knepley }
4323221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize;
4333221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename;
4343221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function;
4353221ece2SMatthew G. Knepley }
4363221ece2SMatthew G. Knepley *result = (void *)inew;
4373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4383221ece2SMatthew G. Knepley }
4393221ece2SMatthew G. Knepley
440fe7fb379SMatthew Knepley /*@C
44192f119d6SBarry Smith PetscMemoryView - Shows the amount of memory currently being used in a communicator.
442e5c89e4eSSatish Balay
443c3339decSBarry Smith Collective
444e5c89e4eSSatish Balay
445d8d19677SJose E. Roman Input Parameters:
4460ed210f4SBarry Smith + viewer - the viewer to output the information on
447e5c89e4eSSatish Balay - message - string printed before values
448e5c89e4eSSatish Balay
449811af0c4SBarry Smith Options Database Keys:
45092f119d6SBarry Smith + -malloc_debug - have PETSc track how much memory it has allocated
4510ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used
4520ed210f4SBarry Smith - -memory_view - during `PetscFinalize()` have this routine called
4530841954dSBarry Smith
454e5c89e4eSSatish Balay Level: intermediate
455e5c89e4eSSatish Balay
4560ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
457e5c89e4eSSatish Balay @*/
PetscMemoryView(PetscViewer viewer,const char message[])458d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
459d71ae5a4SJacob Faibussowitsch {
4602d853995SBarry Smith PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
4612d853995SBarry Smith PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
462e5c89e4eSSatish Balay MPI_Comm comm;
463e5c89e4eSSatish Balay
464e5c89e4eSSatish Balay PetscFunctionBegin;
465e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4669566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&allocated));
4679566063dSJacob Faibussowitsch PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4689566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&resident));
4699566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
470e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
473e5c89e4eSSatish Balay if (resident && residentmax && allocated) {
4749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
4829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
4869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
490e5c89e4eSSatish Balay } else if (resident && residentmax) {
4919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
499e5c89e4eSSatish Balay } else if (resident && allocated) {
5009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
509e5c89e4eSSatish Balay } else if (allocated) {
5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
516e5c89e4eSSatish Balay } else {
5179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
518e5c89e4eSSatish Balay }
5199566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer));
5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
521e5c89e4eSSatish Balay }
522e5c89e4eSSatish Balay
52346eb3923SBarry Smith /*@
524811af0c4SBarry Smith PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
525e5c89e4eSSatish Balay
526e5c89e4eSSatish Balay Not Collective
527e5c89e4eSSatish Balay
5282fe279fdSBarry Smith Output Parameter:
529e5c89e4eSSatish Balay . space - number of bytes currently allocated
530e5c89e4eSSatish Balay
531e5c89e4eSSatish Balay Level: intermediate
532e5c89e4eSSatish Balay
5332d853995SBarry Smith Note:
5342d853995SBarry Smith This only works if `-memory_view` or `-log_view_memory` have been used
5352d853995SBarry Smith
5360ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
537db781477SPatrick Sanan `PetscMemoryGetMaximumUsage()`
538e5c89e4eSSatish Balay @*/
PetscMallocGetCurrentUsage(PetscLogDouble * space)539d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
540d71ae5a4SJacob Faibussowitsch {
541e5c89e4eSSatish Balay PetscFunctionBegin;
542e5c89e4eSSatish Balay *space = (PetscLogDouble)TRallocated;
5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
544e5c89e4eSSatish Balay }
545e5c89e4eSSatish Balay
546dc37d89fSBarry Smith /*@
547811af0c4SBarry Smith PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
548811af0c4SBarry Smith during this run, the high water mark.
549e5c89e4eSSatish Balay
550e5c89e4eSSatish Balay Not Collective
551e5c89e4eSSatish Balay
5522fe279fdSBarry Smith Output Parameter:
553e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time
554e5c89e4eSSatish Balay
555e5c89e4eSSatish Balay Level: intermediate
556e5c89e4eSSatish Balay
5572d853995SBarry Smith Note:
5582d853995SBarry Smith This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5592d853995SBarry Smith
5600ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
561db781477SPatrick Sanan `PetscMallocPushMaximumUsage()`
562e5c89e4eSSatish Balay @*/
PetscMallocGetMaximumUsage(PetscLogDouble * space)563d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
564d71ae5a4SJacob Faibussowitsch {
565e5c89e4eSSatish Balay PetscFunctionBegin;
566e5c89e4eSSatish Balay *space = (PetscLogDouble)TRMaxMem;
5673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
568e5c89e4eSSatish Balay }
569e5c89e4eSSatish Balay
570e3ed9ee7SBarry Smith /*@
571e3ed9ee7SBarry Smith PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
572e3ed9ee7SBarry Smith
573e3ed9ee7SBarry Smith Not Collective
574e3ed9ee7SBarry Smith
575e3ed9ee7SBarry Smith Input Parameter:
576e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
577e3ed9ee7SBarry Smith
578e3ed9ee7SBarry Smith Level: developer
579e3ed9ee7SBarry Smith
5802d853995SBarry Smith Note:
5812d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5822d853995SBarry Smith
5830ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
584db781477SPatrick Sanan `PetscMallocPopMaximumUsage()`
585e3ed9ee7SBarry Smith @*/
PetscMallocPushMaximumUsage(int event)586d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
587d71ae5a4SJacob Faibussowitsch {
588e3ed9ee7SBarry Smith PetscFunctionBegin;
5892611ad71SToby Isaac if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
590e3ed9ee7SBarry Smith TRMaxMems[NumTRMaxMems - 1] = TRallocated;
591e3ed9ee7SBarry Smith TRMaxMemsEvents[NumTRMaxMems - 1] = event;
5923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
593e3ed9ee7SBarry Smith }
594e3ed9ee7SBarry Smith
595e3ed9ee7SBarry Smith /*@
596e3ed9ee7SBarry Smith PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
597e3ed9ee7SBarry Smith
598e3ed9ee7SBarry Smith Not Collective
599e3ed9ee7SBarry Smith
600e3ed9ee7SBarry Smith Input Parameter:
601e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
602e3ed9ee7SBarry Smith
603e3ed9ee7SBarry Smith Output Parameter:
604e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
605e3ed9ee7SBarry Smith
606e3ed9ee7SBarry Smith Level: developer
607e3ed9ee7SBarry Smith
6082d853995SBarry Smith Note:
6092d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
6102d853995SBarry Smith
6110ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
612db781477SPatrick Sanan `PetscMallocPushMaximumUsage()`
613e3ed9ee7SBarry Smith @*/
PetscMallocPopMaximumUsage(int event,PetscLogDouble * mu)614d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
615d71ae5a4SJacob Faibussowitsch {
616e3ed9ee7SBarry Smith PetscFunctionBegin;
617e3ed9ee7SBarry Smith *mu = 0;
6182611ad71SToby Isaac if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
61908401ef6SPierre Jolivet PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
6206497c311SBarry Smith *mu = (PetscLogDouble)TRMaxMems[NumTRMaxMems];
6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
622e3ed9ee7SBarry Smith }
623e3ed9ee7SBarry Smith
624a64a8e02SBarry Smith /*@C
625811af0c4SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
626a64a8e02SBarry Smith
627cc4c1da9SBarry Smith Not Collective, No Fortran Support
628a64a8e02SBarry Smith
629a64a8e02SBarry Smith Input Parameter:
630a64a8e02SBarry Smith . ptr - the memory location
631a64a8e02SBarry Smith
632fd292e60Sprj- Output Parameter:
633a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory
634a64a8e02SBarry Smith
635a64a8e02SBarry Smith Level: intermediate
636a64a8e02SBarry Smith
6372d853995SBarry Smith Note:
6382d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6392d853995SBarry Smith
6400ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
641a64a8e02SBarry Smith @*/
PetscMallocGetStack(void * ptr,PetscStack ** stack)642d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
643d71ae5a4SJacob Faibussowitsch {
644dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
645a64a8e02SBarry Smith TRSPACE *head;
646a64a8e02SBarry Smith
647a64a8e02SBarry Smith PetscFunctionBegin;
64857508eceSPierre Jolivet head = (TRSPACE *)((char *)ptr - HEADER_BYTES);
649a64a8e02SBarry Smith *stack = &head->stack;
6503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
65176386721SLisandro Dalcin #else
652f0ba7cfcSLisandro Dalcin *stack = NULL;
6533ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
654a64a8e02SBarry Smith #endif
655dfb7d7afSStefano Zampini }
656a64a8e02SBarry Smith
657e5c89e4eSSatish Balay /*@C
65892f119d6SBarry Smith PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
659e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space,
660e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was
661e5c89e4eSSatish Balay allocated.
662e5c89e4eSSatish Balay
66392f119d6SBarry Smith Not Collective
664e5c89e4eSSatish Balay
665e5c89e4eSSatish Balay Input Parameter:
6660ed210f4SBarry Smith . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed.
667e5c89e4eSSatish Balay
668e5c89e4eSSatish Balay Options Database Key:
6690ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
670e5c89e4eSSatish Balay
671e5c89e4eSSatish Balay Level: intermediate
672e5c89e4eSSatish Balay
67395452b02SPatrick Sanan Notes:
674811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
675e5c89e4eSSatish Balay
676811af0c4SBarry Smith When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
67792f119d6SBarry Smith
678811af0c4SBarry Smith `PetscMallocView()` prints a list of all memory ever allocated
67992f119d6SBarry Smith
6802d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6812d853995SBarry Smith
682aec76313SJacob Faibussowitsch Fortran Notes:
6830ed210f4SBarry Smith The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
68420f4b53cSBarry Smith
685aec76313SJacob Faibussowitsch Developer Notes:
6862d853995SBarry Smith This should be absorbed into `PetscMallocView()`
6872d853995SBarry Smith
6880ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
689e5c89e4eSSatish Balay @*/
PetscMallocDump(FILE * fp)690d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
691d71ae5a4SJacob Faibussowitsch {
692e5c89e4eSSatish Balay TRSPACE *head;
693e3ed9ee7SBarry Smith size_t libAlloc = 0;
694e5c89e4eSSatish Balay PetscMPIInt rank;
695e5c89e4eSSatish Balay
696e5c89e4eSSatish Balay PetscFunctionBegin;
6979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
698da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT;
699e5c89e4eSSatish Balay head = TRhead;
700e5c89e4eSSatish Balay while (head) {
701608c71bfSMatthew G. Knepley libAlloc += TRrequestedSize ? head->rsize : head->size;
7025486ca60SMatthew G. Knepley head = head->next;
7035486ca60SMatthew G. Knepley }
7045486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7055486ca60SMatthew G. Knepley head = TRhead;
7065486ca60SMatthew G. Knepley while (head) {
7075486ca60SMatthew G. Knepley PetscBool isLib;
7085486ca60SMatthew G. Knepley
7099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7105486ca60SMatthew G. Knepley if (!isLib) {
711dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7122d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
7139566063dSJacob Faibussowitsch PetscCall(PetscStackPrint(&head->stack, fp));
7142d853995SBarry Smith #else
7152d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
716e5c89e4eSSatish Balay #endif
7175486ca60SMatthew G. Knepley }
718e5c89e4eSSatish Balay head = head->next;
719e5c89e4eSSatish Balay }
7203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
721e5c89e4eSSatish Balay }
722e5c89e4eSSatish Balay
723dc37d89fSBarry Smith /*@
724811af0c4SBarry Smith PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
725574034a9SJed Brown
726574034a9SJed Brown Not Collective
727574034a9SJed Brown
7284165533cSJose E. Roman Input Parameter:
7290ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
730574034a9SJed Brown
7310ed210f4SBarry Smith Options Database Keys:
732811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7332d853995SBarry Smith . -malloc_view_threshold <min> - Sets a minimum size if `-malloc_view` is used
7348b254c29SBarry Smith - -log_view_memory - view the memory usage also with the -log_view option
735574034a9SJed Brown
736574034a9SJed Brown Level: advanced
737574034a9SJed Brown
7380ed210f4SBarry Smith Note:
739811af0c4SBarry Smith Must be called after `PetscMallocSetDebug()`
74092f119d6SBarry Smith
741aec76313SJacob Faibussowitsch Developer Notes:
742811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74392f119d6SBarry Smith
7440ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
745574034a9SJed Brown @*/
PetscMallocViewSet(PetscLogDouble logmin)746d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
747d71ae5a4SJacob Faibussowitsch {
748574034a9SJed Brown PetscFunctionBegin;
74992f119d6SBarry Smith PetscLogMalloc = 0;
7509566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage());
751574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
752574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin;
7533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
754574034a9SJed Brown }
755574034a9SJed Brown
756dc37d89fSBarry Smith /*@
757811af0c4SBarry Smith PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
75818a2528dSJed Brown
75918a2528dSJed Brown Not Collective
76018a2528dSJed Brown
76110450e9eSJacob Faibussowitsch Output Parameter:
762811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
76318a2528dSJed Brown
76418a2528dSJed Brown Options Database Key:
765811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
76618a2528dSJed Brown
76718a2528dSJed Brown Level: advanced
76818a2528dSJed Brown
7690ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
77018a2528dSJed Brown @*/
PetscMallocViewGet(PetscBool * logging)771d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
772d71ae5a4SJacob Faibussowitsch {
77318a2528dSJed Brown PetscFunctionBegin;
77418a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0);
7753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
77618a2528dSJed Brown }
77718a2528dSJed Brown
778608c71bfSMatthew G. Knepley /*@
7792d853995SBarry Smith PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
780608c71bfSMatthew G. Knepley
781608c71bfSMatthew G. Knepley Not Collective
782608c71bfSMatthew G. Knepley
7834165533cSJose E. Roman Input Parameters:
7840ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
785608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
786608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
787608c71bfSMatthew G. Knepley
7880ed210f4SBarry Smith Level: advanced
7890ed210f4SBarry Smith
790608c71bfSMatthew G. Knepley Note:
791608c71bfSMatthew G. Knepley The viewer should not be collective.
792608c71bfSMatthew G. Knepley
7932d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
7942d853995SBarry Smith
7950ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
796608c71bfSMatthew G. Knepley @*/
PetscMallocTraceSet(PetscViewer viewer,PetscBool active,PetscLogDouble logmin)797d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
798d71ae5a4SJacob Faibussowitsch {
799608c71bfSMatthew G. Knepley PetscFunctionBegin;
8009371c9d4SSatish Balay if (!active) {
8019371c9d4SSatish Balay PetscLogMallocTrace = -1;
8023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8039371c9d4SSatish Balay }
8040ed210f4SBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
8050ed210f4SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8060ed210f4SBarry Smith PetscLogMallocTraceViewer = viewer;
807608c71bfSMatthew G. Knepley PetscLogMallocTrace = 0;
8089566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage());
809608c71bfSMatthew G. Knepley if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
810608c71bfSMatthew G. Knepley PetscLogMallocTraceThreshold = (size_t)logmin;
8113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
812608c71bfSMatthew G. Knepley }
813608c71bfSMatthew G. Knepley
814608c71bfSMatthew G. Knepley /*@
815811af0c4SBarry Smith PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
816608c71bfSMatthew G. Knepley
817608c71bfSMatthew G. Knepley Not Collective
818608c71bfSMatthew G. Knepley
8194165533cSJose E. Roman Output Parameter:
820811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
821608c71bfSMatthew G. Knepley
822608c71bfSMatthew G. Knepley Options Database Key:
8230ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
824608c71bfSMatthew G. Knepley
825608c71bfSMatthew G. Knepley Level: advanced
826608c71bfSMatthew G. Knepley
8272d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
8282d853995SBarry Smith
8290ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
830608c71bfSMatthew G. Knepley @*/
PetscMallocTraceGet(PetscBool * logging)831d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
832d71ae5a4SJacob Faibussowitsch {
833608c71bfSMatthew G. Knepley PetscFunctionBegin;
834608c71bfSMatthew G. Knepley *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
836608c71bfSMatthew G. Knepley }
837608c71bfSMatthew G. Knepley
838e5c89e4eSSatish Balay /*@C
8392d853995SBarry Smith PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
840e5c89e4eSSatish Balay
84192f119d6SBarry Smith Not Collective
842e5c89e4eSSatish Balay
843e5c89e4eSSatish Balay Input Parameter:
8440ed210f4SBarry Smith . fp - file pointer; or `NULL`
845e5c89e4eSSatish Balay
846e5c89e4eSSatish Balay Options Database Key:
847811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
848e5c89e4eSSatish Balay
849e5c89e4eSSatish Balay Level: advanced
850e5c89e4eSSatish Balay
85192f119d6SBarry Smith Notes:
852811af0c4SBarry Smith `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
85392f119d6SBarry Smith
854811af0c4SBarry Smith `PetscMemoryView()` gives a brief summary of current memory usage
85592f119d6SBarry Smith
85620f4b53cSBarry Smith Fortran Notes:
8570ed210f4SBarry Smith The calling sequence in Fortran is `PetscMallocView`(integer ierr)
85820f4b53cSBarry Smith
8590ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
860e5c89e4eSSatish Balay @*/
PetscMallocView(FILE * fp)861d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
862d71ae5a4SJacob Faibussowitsch {
8632d853995SBarry Smith PetscInt n, *perm;
864e5c89e4eSSatish Balay size_t *shortlength;
865c69effb2SJacob Faibussowitsch int *shortcount;
86692f119d6SBarry Smith PetscMPIInt rank;
867ace3abfcSBarry Smith PetscBool match;
868e5c89e4eSSatish Balay const char **shortfunction;
869e5c89e4eSSatish Balay PetscLogDouble rss;
870e5c89e4eSSatish Balay
871e5c89e4eSSatish Balay PetscFunctionBegin;
8729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
873c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp));
874f56c2debSBarry Smith
87500045ab3SPierre Jolivet 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()");
876768aa557SSatish Balay
877da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT;
8789566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&rss));
879e5c89e4eSSatish Balay if (rss) {
88092f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
881e5c89e4eSSatish Balay } else {
88292f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
883e5c89e4eSSatish Balay }
884b13f2904SStefano Zampini if (PetscLogMalloc > 0) {
8859371c9d4SSatish Balay shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8869371c9d4SSatish Balay PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8879371c9d4SSatish Balay shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8889371c9d4SSatish Balay PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8899371c9d4SSatish Balay shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8909371c9d4SSatish Balay PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8912d853995SBarry Smith n = 0;
8922d853995SBarry Smith for (PetscInt i = 0; i < PetscLogMalloc; i++) {
8932d853995SBarry Smith for (PetscInt j = 0; j < n; j++) {
8949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
895e5c89e4eSSatish Balay if (match) {
896e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i];
89759ffdab8SBarry Smith shortcount[j]++;
898e5c89e4eSSatish Balay goto foundit;
899e5c89e4eSSatish Balay }
900e5c89e4eSSatish Balay }
901e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i];
902e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i];
90359ffdab8SBarry Smith shortcount[n] = 1;
904e5c89e4eSSatish Balay n++;
905e5c89e4eSSatish Balay foundit:;
906e5c89e4eSSatish Balay }
907e5c89e4eSSatish Balay
9089371c9d4SSatish Balay perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9099371c9d4SSatish Balay PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
9102d853995SBarry Smith for (PetscInt i = 0; i < n; i++) perm[i] = i;
911835f2295SStefano Zampini PetscCall(PetscSortStrWithPermutation(n, shortfunction, perm));
912e5c89e4eSSatish Balay
91392f119d6SBarry Smith (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
9142d853995SBarry Smith 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]]);
915e5c89e4eSSatish Balay free(perm);
916e5c89e4eSSatish Balay free(shortlength);
91759ffdab8SBarry Smith free(shortcount);
918e5c89e4eSSatish Balay free((char **)shortfunction);
919b13f2904SStefano Zampini }
920c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp));
9213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
922e5c89e4eSSatish Balay }
923e5c89e4eSSatish Balay
924dc37d89fSBarry Smith /*@
92592f119d6SBarry Smith PetscMallocSetDebug - Set's PETSc memory debugging
926e5c89e4eSSatish Balay
927e5c89e4eSSatish Balay Not Collective
928e5c89e4eSSatish Balay
929d8d19677SJose E. Roman Input Parameters:
930811af0c4SBarry Smith + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9310ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
932e5c89e4eSSatish Balay
933811af0c4SBarry Smith Options Database Keys:
93479dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging
9350ed210f4SBarry Smith . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
93679dccf82SBarry Smith . -malloc_view_threshold t - log only allocations larger than t
93710450e9eSJacob Faibussowitsch - -malloc_dump <filename> - print a list of all memory that has not been freed, in `PetscFinalize()`
938e5c89e4eSSatish Balay
93992f119d6SBarry Smith Level: developer
94092f119d6SBarry Smith
941811af0c4SBarry Smith Note:
942811af0c4SBarry Smith This is called in `PetscInitialize()` and should not be called elsewhere
94392f119d6SBarry Smith
9442d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
945e5c89e4eSSatish Balay @*/
PetscMallocSetDebug(PetscBool eachcall,PetscBool initializenan)946d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
947d71ae5a4SJacob Faibussowitsch {
948e5c89e4eSSatish Balay PetscFunctionBegin;
94908401ef6SPierre Jolivet PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
9509566063dSJacob Faibussowitsch PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95192f119d6SBarry Smith
95292f119d6SBarry Smith TRallocated = 0;
95392f119d6SBarry Smith TRfrags = 0;
95492f119d6SBarry Smith TRhead = NULL;
95592f119d6SBarry Smith TRid = 0;
9562d853995SBarry Smith TRdebug = eachcall;
95792f119d6SBarry Smith TRMaxMem = 0;
95892f119d6SBarry Smith PetscLogMallocMax = 10000;
95992f119d6SBarry Smith PetscLogMalloc = -1;
9602d4ee042Sprj- TRdebugIinitializenan = initializenan;
9613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
962e5c89e4eSSatish Balay }
9630acecf5bSBarry Smith
964dc37d89fSBarry Smith /*@
96592f119d6SBarry Smith PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9660acecf5bSBarry Smith
9670acecf5bSBarry Smith Not Collective
9680acecf5bSBarry Smith
96992f119d6SBarry Smith Output Parameters:
97092f119d6SBarry Smith + basic - doing basic debugging
971811af0c4SBarry Smith . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
9720ed210f4SBarry Smith - initializenan - initializes memory with `NaN`
9730acecf5bSBarry Smith
9740acecf5bSBarry Smith Level: intermediate
9750acecf5bSBarry Smith
976811af0c4SBarry Smith Note:
9772d853995SBarry Smith By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
9780acecf5bSBarry Smith
9792d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
9800acecf5bSBarry Smith @*/
PetscMallocGetDebug(PetscBool * basic,PetscBool * eachcall,PetscBool * initializenan)981d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
982d71ae5a4SJacob Faibussowitsch {
9830acecf5bSBarry Smith PetscFunctionBegin;
98479dccf82SBarry Smith if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
9852d853995SBarry Smith if (eachcall) *eachcall = TRdebug;
9862d4ee042Sprj- if (initializenan) *initializenan = TRdebugIinitializenan;
9873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
9880acecf5bSBarry Smith }
989608c71bfSMatthew G. Knepley
990608c71bfSMatthew G. Knepley /*@
991608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
992608c71bfSMatthew G. Knepley
993608c71bfSMatthew G. Knepley Not Collective
994608c71bfSMatthew G. Knepley
995608c71bfSMatthew G. Knepley Input Parameter:
996811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
997608c71bfSMatthew G. Knepley
998811af0c4SBarry Smith Options Database Key:
999608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1000608c71bfSMatthew G. Knepley
1001608c71bfSMatthew G. Knepley Level: developer
1002608c71bfSMatthew G. Knepley
10030ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1004608c71bfSMatthew G. Knepley @*/
PetscMallocLogRequestedSizeSet(PetscBool flg)1005d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1006d71ae5a4SJacob Faibussowitsch {
1007608c71bfSMatthew G. Knepley PetscFunctionBegin;
1008608c71bfSMatthew G. Knepley TRrequestedSize = flg;
10093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1010608c71bfSMatthew G. Knepley }
1011608c71bfSMatthew G. Knepley
1012608c71bfSMatthew G. Knepley /*@
1013608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1014608c71bfSMatthew G. Knepley
1015608c71bfSMatthew G. Knepley Not Collective
1016608c71bfSMatthew G. Knepley
1017608c71bfSMatthew G. Knepley Output Parameter:
1018811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1019608c71bfSMatthew G. Knepley
1020608c71bfSMatthew G. Knepley Level: developer
1021608c71bfSMatthew G. Knepley
10220ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1023608c71bfSMatthew G. Knepley @*/
PetscMallocLogRequestedSizeGet(PetscBool * flg)1024d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1025d71ae5a4SJacob Faibussowitsch {
1026608c71bfSMatthew G. Knepley PetscFunctionBegin;
1027608c71bfSMatthew G. Knepley *flg = TRrequestedSize;
10283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1029608c71bfSMatthew G. Knepley }
1030