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 170700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9) 180700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c) 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; 270700a824SBarry Smith PetscClassId classid; 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; 1040700a824SBarry Smith PetscClassId *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) { 1160700a824SBarry Smith if (head->classid != CLASSID_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); 1290700a824SBarry Smith nend = (PetscClassId *)(a + head->size); 1300700a824SBarry Smith if (*nend != CLASSID_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); 1759566063dSJacob Faibussowitsch PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), 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; 1910700a824SBarry Smith head->classid = CLASSID_VALUE; 1920700a824SBarry Smith *(PetscClassId *)(inew + nsize) = CLASSID_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; */ 206*53dcd878SStefano 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; 2570700a824SBarry Smith PetscClassId *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 2680700a824SBarry Smith if (head->classid != CLASSID_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 } 2740700a824SBarry Smith nend = (PetscClassId *)(ahead + head->size); 2750700a824SBarry Smith if (*nend != CLASSID_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 } 294608c71bfSMatthew G. Knepley if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 2959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 296608c71bfSMatthew G. Knepley } 297e5c89e4eSSatish Balay *nend = ALREADY_FREED; 298e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */ 299608c71bfSMatthew G. Knepley if (lineno > 0 && lineno < 50000) { 300608c71bfSMatthew G. Knepley head->lineno = lineno; 301608c71bfSMatthew G. Knepley head->filename = filename; 302e5c89e4eSSatish Balay head->functionname = function; 303e5c89e4eSSatish Balay } else { 304e5c89e4eSSatish Balay head->lineno = -head->lineno; 305e5c89e4eSSatish Balay } 306608c71bfSMatthew G. Knepley asize = TRrequestedSize ? head->rsize : head->size; 30708401ef6SPierre Jolivet PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 308608c71bfSMatthew G. Knepley TRallocated -= asize; 309e5c89e4eSSatish Balay TRfrags--; 310e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next; 311e5c89e4eSSatish Balay else TRhead = head->next; 312e5c89e4eSSatish Balay 313e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev; 3149566063dSJacob Faibussowitsch PetscCall(PetscFreeAlign(a, lineno, function, filename)); 3153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 316e5c89e4eSSatish Balay } 317e5c89e4eSSatish Balay 3183221ece2SMatthew G. Knepley /* 3192d853995SBarry Smith PetscTrReallocDefault - Realloc with logging and error checking 3203221ece2SMatthew G. Knepley 3213221ece2SMatthew G. Knepley */ 32266976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) 323d71ae5a4SJacob Faibussowitsch { 3243221ece2SMatthew G. Knepley char *a = (char *)*result; 3253221ece2SMatthew G. Knepley TRSPACE *head; 3263221ece2SMatthew G. Knepley char *ahead, *inew; 3273221ece2SMatthew G. Knepley PetscClassId *nend; 3283221ece2SMatthew G. Knepley size_t nsize; 3293221ece2SMatthew G. Knepley 3303221ece2SMatthew G. Knepley PetscFunctionBegin; 33192f119d6SBarry Smith /* Realloc requests zero space so just free the current space */ 332c22f1541SToby Isaac if (!len) { 3339566063dSJacob Faibussowitsch PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 334c22f1541SToby Isaac *result = NULL; 3353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 336c22f1541SToby Isaac } 337da81f932SPierre Jolivet /* If the original space was NULL just use the regular malloc() */ 338f590eff4SLisandro Dalcin if (!*result) { 3399566063dSJacob Faibussowitsch PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 3403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 341f590eff4SLisandro Dalcin } 3423221ece2SMatthew G. Knepley 34311cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename)); 3443221ece2SMatthew G. Knepley 3453221ece2SMatthew G. Knepley ahead = a; 3463221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3473221ece2SMatthew G. Knepley head = (TRSPACE *)a; 3483221ece2SMatthew G. Knepley inew = a; 3493221ece2SMatthew G. Knepley 3503221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 3512d853995SBarry Smith TRdebug = PETSC_FALSE; 3523ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3533ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a)); 3543221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 3553221ece2SMatthew G. Knepley } 3563221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3573221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3582d853995SBarry Smith TRdebug = PETSC_FALSE; 3593221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 3603ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3613ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE))); 3623221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 3633ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 3643221ece2SMatthew G. Knepley } else { 3653ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno)); 3663221ece2SMatthew G. Knepley } 3673221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 3683221ece2SMatthew G. Knepley } else { 3693221ece2SMatthew G. Knepley /* Damaged tail */ 3703ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3713ba16761SJacob 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)); 3723ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 3733221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 3743221ece2SMatthew G. Knepley } 3753221ece2SMatthew G. Knepley } 3763221ece2SMatthew G. Knepley 37792f119d6SBarry Smith /* remove original reference to the memory allocated from the PETSc debugging heap */ 378608c71bfSMatthew G. Knepley TRallocated -= TRrequestedSize ? head->rsize : head->size; 3793221ece2SMatthew G. Knepley TRfrags--; 3803221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 3813221ece2SMatthew G. Knepley else TRhead = head->next; 3823221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 3833221ece2SMatthew G. Knepley 3843221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 3859566063dSJacob Faibussowitsch PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 3863221ece2SMatthew G. Knepley 3873221ece2SMatthew G. Knepley head = (TRSPACE *)inew; 3883221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 3893221ece2SMatthew G. Knepley 3903221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 3913221ece2SMatthew G. Knepley head->next = TRhead; 3923221ece2SMatthew G. Knepley TRhead = head; 3933221ece2SMatthew G. Knepley head->prev = NULL; 3943221ece2SMatthew G. Knepley head->size = nsize; 395608c71bfSMatthew G. Knepley head->rsize = len; 396e269983cSBarry Smith head->id = TRid++; 3973221ece2SMatthew G. Knepley head->lineno = lineno; 3983221ece2SMatthew G. Knepley 3993221ece2SMatthew G. Knepley head->filename = filename; 4003221ece2SMatthew G. Knepley head->functionname = function; 4013221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4023221ece2SMatthew G. Knepley *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 4033221ece2SMatthew G. Knepley 404608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 4053221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 406e3ed9ee7SBarry Smith if (PetscLogMemory) { 4072d853995SBarry Smith for (PetscInt i = 0; i < NumTRMaxMems; i++) { 408e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 409e3ed9ee7SBarry Smith } 410e3ed9ee7SBarry Smith } 4113221ece2SMatthew G. Knepley TRfrags++; 4123221ece2SMatthew G. Knepley 413dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 4149566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 4153221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 416*53dcd878SStefano Zampini head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno; 4173221ece2SMatthew G. Knepley #endif 4183221ece2SMatthew G. Knepley 4193221ece2SMatthew G. Knepley /* 42092f119d6SBarry Smith Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 42192f119d6SBarry Smith and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 4223221ece2SMatthew G. Knepley */ 4233221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4243221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4253221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 42628b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4273221ece2SMatthew G. Knepley 4283221ece2SMatthew G. Knepley PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 42928b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4303221ece2SMatthew G. Knepley 4313221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 43228b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4333221ece2SMatthew G. Knepley } 4343221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4353221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4363221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4373221ece2SMatthew G. Knepley } 4383221ece2SMatthew G. Knepley *result = (void *)inew; 4393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4403221ece2SMatthew G. Knepley } 4413221ece2SMatthew G. Knepley 442fe7fb379SMatthew Knepley /*@C 44392f119d6SBarry Smith PetscMemoryView - Shows the amount of memory currently being used in a communicator. 444e5c89e4eSSatish Balay 445c3339decSBarry Smith Collective 446e5c89e4eSSatish Balay 447d8d19677SJose E. Roman Input Parameters: 4480ed210f4SBarry Smith + viewer - the viewer to output the information on 449e5c89e4eSSatish Balay - message - string printed before values 450e5c89e4eSSatish Balay 451811af0c4SBarry Smith Options Database Keys: 45292f119d6SBarry Smith + -malloc_debug - have PETSc track how much memory it has allocated 4530ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used 4540ed210f4SBarry Smith - -memory_view - during `PetscFinalize()` have this routine called 4550841954dSBarry Smith 456e5c89e4eSSatish Balay Level: intermediate 457e5c89e4eSSatish Balay 4580ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 459e5c89e4eSSatish Balay @*/ 460d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) 461d71ae5a4SJacob Faibussowitsch { 4622d853995SBarry Smith PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax; 4632d853995SBarry Smith PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax; 464e5c89e4eSSatish Balay MPI_Comm comm; 465e5c89e4eSSatish Balay 466e5c89e4eSSatish Balay PetscFunctionBegin; 467e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 4689566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&allocated)); 4699566063dSJacob Faibussowitsch PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 4709566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&resident)); 4719566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 472e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 4739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 4749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 475e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 4769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 4809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 4889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 492e5c89e4eSSatish Balay } else if (resident && residentmax) { 4939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 4979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 501e5c89e4eSSatish Balay } else if (resident && allocated) { 5029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 511e5c89e4eSSatish Balay } else if (allocated) { 5129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 5179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 518e5c89e4eSSatish Balay } else { 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 520e5c89e4eSSatish Balay } 5219566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 523e5c89e4eSSatish Balay } 524e5c89e4eSSatish Balay 52546eb3923SBarry Smith /*@ 526811af0c4SBarry Smith PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()` 527e5c89e4eSSatish Balay 528e5c89e4eSSatish Balay Not Collective 529e5c89e4eSSatish Balay 5302fe279fdSBarry Smith Output Parameter: 531e5c89e4eSSatish Balay . space - number of bytes currently allocated 532e5c89e4eSSatish Balay 533e5c89e4eSSatish Balay Level: intermediate 534e5c89e4eSSatish Balay 5352d853995SBarry Smith Note: 5362d853995SBarry Smith This only works if `-memory_view` or `-log_view_memory` have been used 5372d853995SBarry Smith 5380ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 539db781477SPatrick Sanan `PetscMemoryGetMaximumUsage()` 540e5c89e4eSSatish Balay @*/ 541d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 542d71ae5a4SJacob Faibussowitsch { 543e5c89e4eSSatish Balay PetscFunctionBegin; 544e5c89e4eSSatish Balay *space = (PetscLogDouble)TRallocated; 5453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546e5c89e4eSSatish Balay } 547e5c89e4eSSatish Balay 548dc37d89fSBarry Smith /*@ 549811af0c4SBarry Smith PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time 550811af0c4SBarry Smith during this run, the high water mark. 551e5c89e4eSSatish Balay 552e5c89e4eSSatish Balay Not Collective 553e5c89e4eSSatish Balay 5542fe279fdSBarry Smith Output Parameter: 555e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 556e5c89e4eSSatish Balay 557e5c89e4eSSatish Balay Level: intermediate 558e5c89e4eSSatish Balay 5592d853995SBarry Smith Note: 5602d853995SBarry Smith This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 5612d853995SBarry Smith 5620ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 563db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 564e5c89e4eSSatish Balay @*/ 565d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 566d71ae5a4SJacob Faibussowitsch { 567e5c89e4eSSatish Balay PetscFunctionBegin; 568e5c89e4eSSatish Balay *space = (PetscLogDouble)TRMaxMem; 5693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 570e5c89e4eSSatish Balay } 571e5c89e4eSSatish Balay 572e3ed9ee7SBarry Smith /*@ 573e3ed9ee7SBarry Smith PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 574e3ed9ee7SBarry Smith 575e3ed9ee7SBarry Smith Not Collective 576e3ed9ee7SBarry Smith 577e3ed9ee7SBarry Smith Input Parameter: 578e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 579e3ed9ee7SBarry Smith 580e3ed9ee7SBarry Smith Level: developer 581e3ed9ee7SBarry Smith 5822d853995SBarry Smith Note: 5832d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 5842d853995SBarry Smith 5850ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 586db781477SPatrick Sanan `PetscMallocPopMaximumUsage()` 587e3ed9ee7SBarry Smith @*/ 588d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event) 589d71ae5a4SJacob Faibussowitsch { 590e3ed9ee7SBarry Smith PetscFunctionBegin; 5912611ad71SToby Isaac if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 592e3ed9ee7SBarry Smith TRMaxMems[NumTRMaxMems - 1] = TRallocated; 593e3ed9ee7SBarry Smith TRMaxMemsEvents[NumTRMaxMems - 1] = event; 5943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 595e3ed9ee7SBarry Smith } 596e3ed9ee7SBarry Smith 597e3ed9ee7SBarry Smith /*@ 598e3ed9ee7SBarry Smith PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 599e3ed9ee7SBarry Smith 600e3ed9ee7SBarry Smith Not Collective 601e3ed9ee7SBarry Smith 602e3ed9ee7SBarry Smith Input Parameter: 603e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 604e3ed9ee7SBarry Smith 605e3ed9ee7SBarry Smith Output Parameter: 606e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 607e3ed9ee7SBarry Smith 608e3ed9ee7SBarry Smith Level: developer 609e3ed9ee7SBarry Smith 6102d853995SBarry Smith Note: 6112d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 6122d853995SBarry Smith 6130ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 614db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 615e3ed9ee7SBarry Smith @*/ 616d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) 617d71ae5a4SJacob Faibussowitsch { 618e3ed9ee7SBarry Smith PetscFunctionBegin; 619e3ed9ee7SBarry Smith *mu = 0; 6202611ad71SToby Isaac if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 62108401ef6SPierre Jolivet PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 622e3ed9ee7SBarry Smith *mu = TRMaxMems[NumTRMaxMems]; 6233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 624e3ed9ee7SBarry Smith } 625e3ed9ee7SBarry Smith 626a64a8e02SBarry Smith /*@C 627811af0c4SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory 628a64a8e02SBarry Smith 6290ed210f4SBarry Smith Not Collective 630a64a8e02SBarry Smith 631a64a8e02SBarry Smith Input Parameter: 632a64a8e02SBarry Smith . ptr - the memory location 633a64a8e02SBarry Smith 634fd292e60Sprj- Output Parameter: 635a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 636a64a8e02SBarry Smith 637a64a8e02SBarry Smith Level: intermediate 638a64a8e02SBarry Smith 6392d853995SBarry Smith Note: 6402d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 6412d853995SBarry Smith 6420ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 643a64a8e02SBarry Smith @*/ 644d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) 645d71ae5a4SJacob Faibussowitsch { 646dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 647a64a8e02SBarry Smith TRSPACE *head; 648a64a8e02SBarry Smith 649a64a8e02SBarry Smith PetscFunctionBegin; 650a64a8e02SBarry Smith head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 651a64a8e02SBarry Smith *stack = &head->stack; 6523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65376386721SLisandro Dalcin #else 654f0ba7cfcSLisandro Dalcin *stack = NULL; 6553ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 656a64a8e02SBarry Smith #endif 657dfb7d7afSStefano Zampini } 658a64a8e02SBarry Smith 659e5c89e4eSSatish Balay /*@C 66092f119d6SBarry Smith PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 661e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 662e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 663e5c89e4eSSatish Balay allocated. 664e5c89e4eSSatish Balay 66592f119d6SBarry Smith Not Collective 666e5c89e4eSSatish Balay 667e5c89e4eSSatish Balay Input Parameter: 6680ed210f4SBarry Smith . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed. 669e5c89e4eSSatish Balay 670e5c89e4eSSatish Balay Options Database Key: 6710ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given 672e5c89e4eSSatish Balay 673e5c89e4eSSatish Balay Level: intermediate 674e5c89e4eSSatish Balay 67595452b02SPatrick Sanan Notes: 676811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed. 677e5c89e4eSSatish Balay 678811af0c4SBarry Smith When called in `PetscFinalize()` dumps only the allocations that have not been properly freed 67992f119d6SBarry Smith 680811af0c4SBarry Smith `PetscMallocView()` prints a list of all memory ever allocated 68192f119d6SBarry Smith 6822d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 6832d853995SBarry Smith 684aec76313SJacob Faibussowitsch Fortran Notes: 6850ed210f4SBarry Smith The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported. 68620f4b53cSBarry Smith 687aec76313SJacob Faibussowitsch Developer Notes: 6882d853995SBarry Smith This should be absorbed into `PetscMallocView()` 6892d853995SBarry Smith 6900ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 691e5c89e4eSSatish Balay @*/ 692d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp) 693d71ae5a4SJacob Faibussowitsch { 694e5c89e4eSSatish Balay TRSPACE *head; 695e3ed9ee7SBarry Smith size_t libAlloc = 0; 696e5c89e4eSSatish Balay PetscMPIInt rank; 697e5c89e4eSSatish Balay 698e5c89e4eSSatish Balay PetscFunctionBegin; 6999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 700da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 701e5c89e4eSSatish Balay head = TRhead; 702e5c89e4eSSatish Balay while (head) { 703608c71bfSMatthew G. Knepley libAlloc += TRrequestedSize ? head->rsize : head->size; 7045486ca60SMatthew G. Knepley head = head->next; 7055486ca60SMatthew G. Knepley } 7065486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 7075486ca60SMatthew G. Knepley head = TRhead; 7085486ca60SMatthew G. Knepley while (head) { 7095486ca60SMatthew G. Knepley PetscBool isLib; 7105486ca60SMatthew G. Knepley 7119566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 7125486ca60SMatthew G. Knepley if (!isLib) { 713dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 7142d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size)); 7159566063dSJacob Faibussowitsch PetscCall(PetscStackPrint(&head->stack, fp)); 7162d853995SBarry Smith #else 7172d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 718e5c89e4eSSatish Balay #endif 7195486ca60SMatthew G. Knepley } 720e5c89e4eSSatish Balay head = head->next; 721e5c89e4eSSatish Balay } 7223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 723e5c89e4eSSatish Balay } 724e5c89e4eSSatish Balay 725dc37d89fSBarry Smith /*@ 726811af0c4SBarry Smith PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view 727574034a9SJed Brown 728574034a9SJed Brown Not Collective 729574034a9SJed Brown 7304165533cSJose E. Roman Input Parameter: 7310ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations 732574034a9SJed Brown 7330ed210f4SBarry Smith Options Database Keys: 734811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 7352d853995SBarry Smith . -malloc_view_threshold <min> - Sets a minimum size if `-malloc_view` is used 7368b254c29SBarry Smith - -log_view_memory - view the memory usage also with the -log_view option 737574034a9SJed Brown 738574034a9SJed Brown Level: advanced 739574034a9SJed Brown 7400ed210f4SBarry Smith Note: 741811af0c4SBarry Smith Must be called after `PetscMallocSetDebug()` 74292f119d6SBarry Smith 743aec76313SJacob Faibussowitsch Developer Notes: 744811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available 74592f119d6SBarry Smith 7460ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 747574034a9SJed Brown @*/ 748d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) 749d71ae5a4SJacob Faibussowitsch { 750574034a9SJed Brown PetscFunctionBegin; 75192f119d6SBarry Smith PetscLogMalloc = 0; 7529566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 753574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 754574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 7553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 756574034a9SJed Brown } 757574034a9SJed Brown 758dc37d89fSBarry Smith /*@ 759811af0c4SBarry Smith PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged 76018a2528dSJed Brown 76118a2528dSJed Brown Not Collective 76218a2528dSJed Brown 76310450e9eSJacob Faibussowitsch Output Parameter: 764811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 76518a2528dSJed Brown 76618a2528dSJed Brown Options Database Key: 767811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 76818a2528dSJed Brown 76918a2528dSJed Brown Level: advanced 77018a2528dSJed Brown 7710ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()` 77218a2528dSJed Brown @*/ 773d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging) 774d71ae5a4SJacob Faibussowitsch { 77518a2528dSJed Brown PetscFunctionBegin; 77618a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 7773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77818a2528dSJed Brown } 77918a2528dSJed Brown 780608c71bfSMatthew G. Knepley /*@ 7812d853995SBarry Smith PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer. 782608c71bfSMatthew G. Knepley 783608c71bfSMatthew G. Knepley Not Collective 784608c71bfSMatthew G. Knepley 7854165533cSJose E. Roman Input Parameters: 7860ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF` 787608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing 788608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged 789608c71bfSMatthew G. Knepley 7900ed210f4SBarry Smith Level: advanced 7910ed210f4SBarry Smith 792608c71bfSMatthew G. Knepley Note: 793608c71bfSMatthew G. Knepley The viewer should not be collective. 794608c71bfSMatthew G. Knepley 7952d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 7962d853995SBarry Smith 7970ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 798608c71bfSMatthew G. Knepley @*/ 799d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) 800d71ae5a4SJacob Faibussowitsch { 801608c71bfSMatthew G. Knepley PetscFunctionBegin; 8029371c9d4SSatish Balay if (!active) { 8039371c9d4SSatish Balay PetscLogMallocTrace = -1; 8043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8059371c9d4SSatish Balay } 8060ed210f4SBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 8070ed210f4SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 8080ed210f4SBarry Smith PetscLogMallocTraceViewer = viewer; 809608c71bfSMatthew G. Knepley PetscLogMallocTrace = 0; 8109566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 811608c71bfSMatthew G. Knepley if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 812608c71bfSMatthew G. Knepley PetscLogMallocTraceThreshold = (size_t)logmin; 8133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 814608c71bfSMatthew G. Knepley } 815608c71bfSMatthew G. Knepley 816608c71bfSMatthew G. Knepley /*@ 817811af0c4SBarry Smith PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced 818608c71bfSMatthew G. Knepley 819608c71bfSMatthew G. Knepley Not Collective 820608c71bfSMatthew G. Knepley 8214165533cSJose E. Roman Output Parameter: 822811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 823608c71bfSMatthew G. Knepley 824608c71bfSMatthew G. Knepley Options Database Key: 8250ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 826608c71bfSMatthew G. Knepley 827608c71bfSMatthew G. Knepley Level: advanced 828608c71bfSMatthew G. Knepley 8292d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 8302d853995SBarry Smith 8310ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 832608c71bfSMatthew G. Knepley @*/ 833d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging) 834d71ae5a4SJacob Faibussowitsch { 835608c71bfSMatthew G. Knepley PetscFunctionBegin; 836608c71bfSMatthew G. Knepley *logging = (PetscBool)(PetscLogMallocTrace >= 0); 8373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 838608c71bfSMatthew G. Knepley } 839608c71bfSMatthew G. Knepley 840e5c89e4eSSatish Balay /*@C 8412d853995SBarry Smith PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()` 842e5c89e4eSSatish Balay 84392f119d6SBarry Smith Not Collective 844e5c89e4eSSatish Balay 845e5c89e4eSSatish Balay Input Parameter: 8460ed210f4SBarry Smith . fp - file pointer; or `NULL` 847e5c89e4eSSatish Balay 848e5c89e4eSSatish Balay Options Database Key: 849811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 850e5c89e4eSSatish Balay 851e5c89e4eSSatish Balay Level: advanced 852e5c89e4eSSatish Balay 85392f119d6SBarry Smith Notes: 854811af0c4SBarry Smith `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated 85592f119d6SBarry Smith 856811af0c4SBarry Smith `PetscMemoryView()` gives a brief summary of current memory usage 85792f119d6SBarry Smith 85820f4b53cSBarry Smith Fortran Notes: 8590ed210f4SBarry Smith The calling sequence in Fortran is `PetscMallocView`(integer ierr) 86020f4b53cSBarry Smith 8610ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()` 862e5c89e4eSSatish Balay @*/ 863d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp) 864d71ae5a4SJacob Faibussowitsch { 8652d853995SBarry Smith PetscInt n, *perm; 866e5c89e4eSSatish Balay size_t *shortlength; 867c69effb2SJacob Faibussowitsch int *shortcount; 86892f119d6SBarry Smith PetscMPIInt rank; 869ace3abfcSBarry Smith PetscBool match; 870e5c89e4eSSatish Balay const char **shortfunction; 871e5c89e4eSSatish Balay PetscLogDouble rss; 872e5c89e4eSSatish Balay 873e5c89e4eSSatish Balay PetscFunctionBegin; 8749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 875c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp)); 876f56c2debSBarry Smith 87700045ab3SPierre 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()"); 878768aa557SSatish Balay 879da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 8809566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&rss)); 881e5c89e4eSSatish Balay if (rss) { 88292f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 883e5c89e4eSSatish Balay } else { 88492f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 885e5c89e4eSSatish Balay } 886b13f2904SStefano Zampini if (PetscLogMalloc > 0) { 8879371c9d4SSatish Balay shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 8889371c9d4SSatish Balay PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8899371c9d4SSatish Balay shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 8909371c9d4SSatish Balay PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8919371c9d4SSatish Balay shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 8929371c9d4SSatish Balay PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8932d853995SBarry Smith n = 0; 8942d853995SBarry Smith for (PetscInt i = 0; i < PetscLogMalloc; i++) { 8952d853995SBarry Smith for (PetscInt j = 0; j < n; j++) { 8969566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 897e5c89e4eSSatish Balay if (match) { 898e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 89959ffdab8SBarry Smith shortcount[j]++; 900e5c89e4eSSatish Balay goto foundit; 901e5c89e4eSSatish Balay } 902e5c89e4eSSatish Balay } 903e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 904e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 90559ffdab8SBarry Smith shortcount[n] = 1; 906e5c89e4eSSatish Balay n++; 907e5c89e4eSSatish Balay foundit:; 908e5c89e4eSSatish Balay } 909e5c89e4eSSatish Balay 9109371c9d4SSatish Balay perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 9119371c9d4SSatish Balay PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 9122d853995SBarry Smith for (PetscInt i = 0; i < n; i++) perm[i] = i; 9139566063dSJacob Faibussowitsch PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 914e5c89e4eSSatish Balay 91592f119d6SBarry Smith (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 9162d853995SBarry 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]]); 917e5c89e4eSSatish Balay free(perm); 918e5c89e4eSSatish Balay free(shortlength); 91959ffdab8SBarry Smith free(shortcount); 920e5c89e4eSSatish Balay free((char **)shortfunction); 921b13f2904SStefano Zampini } 922c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp)); 9233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 924e5c89e4eSSatish Balay } 925e5c89e4eSSatish Balay 926dc37d89fSBarry Smith /*@ 92792f119d6SBarry Smith PetscMallocSetDebug - Set's PETSc memory debugging 928e5c89e4eSSatish Balay 929e5c89e4eSSatish Balay Not Collective 930e5c89e4eSSatish Balay 931d8d19677SJose E. Roman Input Parameters: 932811af0c4SBarry Smith + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow 9330ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays 934e5c89e4eSSatish Balay 935811af0c4SBarry Smith Options Database Keys: 93679dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging 9370ed210f4SBarry Smith . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored 93879dccf82SBarry Smith . -malloc_view_threshold t - log only allocations larger than t 93910450e9eSJacob Faibussowitsch - -malloc_dump <filename> - print a list of all memory that has not been freed, in `PetscFinalize()` 940e5c89e4eSSatish Balay 94192f119d6SBarry Smith Level: developer 94292f119d6SBarry Smith 943811af0c4SBarry Smith Note: 944811af0c4SBarry Smith This is called in `PetscInitialize()` and should not be called elsewhere 94592f119d6SBarry Smith 9462d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()` 947e5c89e4eSSatish Balay @*/ 948d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) 949d71ae5a4SJacob Faibussowitsch { 950e5c89e4eSSatish Balay PetscFunctionBegin; 95108401ef6SPierre 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()"); 9529566063dSJacob Faibussowitsch PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 95392f119d6SBarry Smith 95492f119d6SBarry Smith TRallocated = 0; 95592f119d6SBarry Smith TRfrags = 0; 95692f119d6SBarry Smith TRhead = NULL; 95792f119d6SBarry Smith TRid = 0; 9582d853995SBarry Smith TRdebug = eachcall; 95992f119d6SBarry Smith TRMaxMem = 0; 96092f119d6SBarry Smith PetscLogMallocMax = 10000; 96192f119d6SBarry Smith PetscLogMalloc = -1; 9622d4ee042Sprj- TRdebugIinitializenan = initializenan; 9633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 964e5c89e4eSSatish Balay } 9650acecf5bSBarry Smith 966dc37d89fSBarry Smith /*@ 96792f119d6SBarry Smith PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 9680acecf5bSBarry Smith 9690acecf5bSBarry Smith Not Collective 9700acecf5bSBarry Smith 97192f119d6SBarry Smith Output Parameters: 97292f119d6SBarry Smith + basic - doing basic debugging 973811af0c4SBarry Smith . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()` 9740ed210f4SBarry Smith - initializenan - initializes memory with `NaN` 9750acecf5bSBarry Smith 9760acecf5bSBarry Smith Level: intermediate 9770acecf5bSBarry Smith 978811af0c4SBarry Smith Note: 9792d853995SBarry Smith By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no` 9800acecf5bSBarry Smith 9812d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()` 9820acecf5bSBarry Smith @*/ 983d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) 984d71ae5a4SJacob Faibussowitsch { 9850acecf5bSBarry Smith PetscFunctionBegin; 98679dccf82SBarry Smith if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 9872d853995SBarry Smith if (eachcall) *eachcall = TRdebug; 9882d4ee042Sprj- if (initializenan) *initializenan = TRdebugIinitializenan; 9893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9900acecf5bSBarry Smith } 991608c71bfSMatthew G. Knepley 992608c71bfSMatthew G. Knepley /*@ 993608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 994608c71bfSMatthew G. Knepley 995608c71bfSMatthew G. Knepley Not Collective 996608c71bfSMatthew G. Knepley 997608c71bfSMatthew G. Knepley Input Parameter: 998811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size 999608c71bfSMatthew G. Knepley 1000811af0c4SBarry Smith Options Database Key: 1001608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag 1002608c71bfSMatthew G. Knepley 1003608c71bfSMatthew G. Knepley Level: developer 1004608c71bfSMatthew G. Knepley 10050ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1006608c71bfSMatthew G. Knepley @*/ 1007d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) 1008d71ae5a4SJacob Faibussowitsch { 1009608c71bfSMatthew G. Knepley PetscFunctionBegin; 1010608c71bfSMatthew G. Knepley TRrequestedSize = flg; 10113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1012608c71bfSMatthew G. Knepley } 1013608c71bfSMatthew G. Knepley 1014608c71bfSMatthew G. Knepley /*@ 1015608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1016608c71bfSMatthew G. Knepley 1017608c71bfSMatthew G. Knepley Not Collective 1018608c71bfSMatthew G. Knepley 1019608c71bfSMatthew G. Knepley Output Parameter: 1020811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size 1021608c71bfSMatthew G. Knepley 1022608c71bfSMatthew G. Knepley Level: developer 1023608c71bfSMatthew G. Knepley 10240ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1025608c71bfSMatthew G. Knepley @*/ 1026d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) 1027d71ae5a4SJacob Faibussowitsch { 1028608c71bfSMatthew G. Knepley PetscFunctionBegin; 1029608c71bfSMatthew G. Knepley *flg = TRrequestedSize; 10303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1031608c71bfSMatthew G. Knepley } 1032