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 @*/ 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 */ 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 */ 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 */ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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