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 80e5c89e4eSSatish Balay Return value: 81e5c89e4eSSatish Balay The number of errors detected. 82e5c89e4eSSatish Balay 83811af0c4SBarry Smith Options Database Keys:. 840ed210f4SBarry Smith + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0` 8592f119d6SBarry Smith - -malloc_debug - turns this feature on anytime 8692f119d6SBarry Smith 87e5c89e4eSSatish Balay Level: advanced 88e5c89e4eSSatish Balay 89e5c89e4eSSatish Balay Notes: 902d853995SBarry Smith You should generally use `CHKMEMQ` as a short cut for calling this routine. 912d853995SBarry Smith 920ed210f4SBarry Smith Error messages are written to `stdout`. 930ed210f4SBarry Smith 940ed210f4SBarry 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) 9538548759SBarry Smith 96e5c89e4eSSatish Balay No output is generated if there are no problems detected. 97e5c89e4eSSatish Balay 98*aec76313SJacob Faibussowitsch Fortran Notes: 9920f4b53cSBarry Smith The Fortran calling sequence is simply `PetscMallocValidate(ierr)` 10020f4b53cSBarry Smith 1010ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()` 102e5c89e4eSSatish Balay @*/ 103d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) 104d71ae5a4SJacob Faibussowitsch { 1056c093d5bSvictor TRSPACE *head, *lasthead; 106e5c89e4eSSatish Balay char *a; 1070700a824SBarry Smith PetscClassId *nend; 108e5c89e4eSSatish Balay 1092d853995SBarry Smith if (!TRdebug) return PETSC_SUCCESS; 1109371c9d4SSatish Balay head = TRhead; 1119371c9d4SSatish Balay lasthead = NULL; 1122cba8197SMatthew G. Knepley if (head && head->prev) { 1132d853995SBarry Smith TRdebug = PETSC_FALSE; 1143ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 1153ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev)); 1164ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 1172cba8197SMatthew G. Knepley } 118e5c89e4eSSatish Balay while (head) { 1190700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 1202d853995SBarry Smith TRdebug = PETSC_FALSE; 1213ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 1223ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head)); 1233ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n")); 124e269983cSBarry Smith if (lasthead) { 125e269983cSBarry Smith a = (char *)(((TrSPACE *)head) + 1); 1263ba16761SJacob 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)); 127e269983cSBarry Smith } 128e269983cSBarry Smith abort(); 1294ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 130e5c89e4eSSatish Balay } 131e5c89e4eSSatish Balay a = (char *)(((TrSPACE *)head) + 1); 1320700a824SBarry Smith nend = (PetscClassId *)(a + head->size); 1330700a824SBarry Smith if (*nend != CLASSID_VALUE) { 1342d853995SBarry Smith TRdebug = PETSC_FALSE; 1353ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 136e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 1373ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a)); 1384ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 139e5c89e4eSSatish Balay } else { 1403ba16761SJacob 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)); 1413ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 1424ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 143e5c89e4eSSatish Balay } 144e5c89e4eSSatish Balay } 1452cba8197SMatthew G. Knepley if (head->prev && head->prev != lasthead) { 1462d853995SBarry Smith TRdebug = PETSC_FALSE; 1473ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 1483ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead)); 1493ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno)); 1503ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 1514ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 1522cba8197SMatthew G. Knepley } 1536c093d5bSvictor lasthead = head; 154e5c89e4eSSatish Balay head = head->next; 155e5c89e4eSSatish Balay } 1563ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 157e5c89e4eSSatish Balay } 158e5c89e4eSSatish Balay 159e5c89e4eSSatish Balay /* 1602d853995SBarry Smith PetscTrMallocDefault - Malloc with logging and error checking 161e5c89e4eSSatish Balay 162e5c89e4eSSatish Balay */ 163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) 164d71ae5a4SJacob Faibussowitsch { 165e5c89e4eSSatish Balay TRSPACE *head; 166e5c89e4eSSatish Balay char *inew; 167e5c89e4eSSatish Balay size_t nsize; 168e5c89e4eSSatish Balay 169e5c89e4eSSatish Balay PetscFunctionBegin; 1709371c9d4SSatish Balay if (!a) { 1719371c9d4SSatish Balay *result = NULL; 1723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1739371c9d4SSatish Balay } 174f0ba7cfcSLisandro Dalcin 17511cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename)); 176e5c89e4eSSatish Balay 17725b53cc9SJed Brown nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 1789566063dSJacob Faibussowitsch PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew)); 179e3ed9ee7SBarry Smith 180e5c89e4eSSatish Balay head = (TRSPACE *)inew; 181e5c89e4eSSatish Balay inew += sizeof(TrSPACE); 182e5c89e4eSSatish Balay 183e5c89e4eSSatish Balay if (TRhead) TRhead->prev = head; 184e5c89e4eSSatish Balay head->next = TRhead; 185e5c89e4eSSatish Balay TRhead = head; 186f0ba7cfcSLisandro Dalcin head->prev = NULL; 187e5c89e4eSSatish Balay head->size = nsize; 188608c71bfSMatthew G. Knepley head->rsize = a; 189e269983cSBarry Smith head->id = TRid++; 190e5c89e4eSSatish Balay head->lineno = lineno; 191e5c89e4eSSatish Balay 192e5c89e4eSSatish Balay head->filename = filename; 193e5c89e4eSSatish Balay head->functionname = function; 1940700a824SBarry Smith head->classid = CLASSID_VALUE; 1950700a824SBarry Smith *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 196e5c89e4eSSatish Balay 197608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 198a297a907SKarl Rupp if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 199e3ed9ee7SBarry Smith if (PetscLogMemory) { 2002d853995SBarry Smith for (PetscInt i = 0; i < NumTRMaxMems; i++) { 201e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 202e3ed9ee7SBarry Smith } 203e3ed9ee7SBarry Smith } 204e5c89e4eSSatish Balay TRfrags++; 205e5c89e4eSSatish Balay 206dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 2079566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 2082d853995SBarry Smith /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */ 2092c9581d2SBarry Smith head->stack.line[head->stack.currentsize - 2] = lineno; 2102d853995SBarry Smith head->stack.currentsize--; 21192f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE) 2122d4ee042Sprj- if (!clear && TRdebugIinitializenan) { 2132d853995SBarry Smith size_t n = a / sizeof(PetscReal); 21492f119d6SBarry Smith PetscReal *s = (PetscReal *)inew; 21592f119d6SBarry Smith /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */ 21692f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) 217df282883SBarry Smith int nas = 0x7F800002; 21892f119d6SBarry Smith #else 21992f119d6SBarry Smith PetscInt64 nas = 0x7FF0000000000002; 22092f119d6SBarry Smith #endif 2212d853995SBarry Smith for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal)); 22292f119d6SBarry Smith } 22392f119d6SBarry Smith #endif 224e5c89e4eSSatish Balay #endif 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay /* 22792f119d6SBarry Smith Allow logging of all mallocs made. 22892f119d6SBarry Smith TODO: Currently this memory is never freed, it should be freed during PetscFinalize() 229e5c89e4eSSatish Balay */ 230574034a9SJed Brown if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 231e5c89e4eSSatish Balay if (!PetscLogMalloc) { 232e5c89e4eSSatish Balay PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 23328b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 234a297a907SKarl Rupp 235a2ea699eSBarry Smith PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 23628b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 237a297a907SKarl Rupp 238a2ea699eSBarry Smith PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 23928b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 240e5c89e4eSSatish Balay } 241e5c89e4eSSatish Balay PetscLogMallocLength[PetscLogMalloc] = nsize; 242e5c89e4eSSatish Balay PetscLogMallocFile[PetscLogMalloc] = filename; 243e5c89e4eSSatish Balay PetscLogMallocFunction[PetscLogMalloc++] = function; 244e5c89e4eSSatish Balay } 24548a46eb9SPierre Jolivet if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); 246e5c89e4eSSatish Balay *result = (void *)inew; 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 248e5c89e4eSSatish Balay } 249e5c89e4eSSatish Balay 250e5c89e4eSSatish Balay /* 2512d853995SBarry Smith PetscTrFreeDefault - Free with logging and error checking 252e5c89e4eSSatish Balay 253e5c89e4eSSatish Balay */ 254d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) 255d71ae5a4SJacob Faibussowitsch { 256e5c89e4eSSatish Balay char *a = (char *)aa; 257e5c89e4eSSatish Balay TRSPACE *head; 258e5c89e4eSSatish Balay char *ahead; 259608c71bfSMatthew G. Knepley size_t asize; 2600700a824SBarry Smith PetscClassId *nend; 261e5c89e4eSSatish Balay 262e5c89e4eSSatish Balay PetscFunctionBegin; 2633ba16761SJacob Faibussowitsch if (!a) PetscFunctionReturn(PETSC_SUCCESS); 264e5c89e4eSSatish Balay 2659566063dSJacob Faibussowitsch PetscCall(PetscMallocValidate(lineno, function, filename)); 266e5c89e4eSSatish Balay 267e5c89e4eSSatish Balay ahead = a; 268e5c89e4eSSatish Balay a = a - sizeof(TrSPACE); 269e5c89e4eSSatish Balay head = (TRSPACE *)a; 270e5c89e4eSSatish Balay 2710700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 2722d853995SBarry Smith TRdebug = PETSC_FALSE; 2733ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 2743ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a)); 275e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 276e5c89e4eSSatish Balay } 2770700a824SBarry Smith nend = (PetscClassId *)(ahead + head->size); 2780700a824SBarry Smith if (*nend != CLASSID_VALUE) { 2792d853995SBarry Smith TRdebug = PETSC_FALSE; 280e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 2813ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 2823ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE))); 283e5c89e4eSSatish Balay if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 2843ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 285e5c89e4eSSatish Balay } else { 2863ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno)); 287e5c89e4eSSatish Balay } 288e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 289e5c89e4eSSatish Balay } else { 290e5c89e4eSSatish Balay /* Damaged tail */ 2913ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 2923ba16761SJacob 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)); 2933ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 294e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 295e5c89e4eSSatish Balay } 296e5c89e4eSSatish Balay } 297608c71bfSMatthew G. Knepley if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 2989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 299608c71bfSMatthew G. Knepley } 300e5c89e4eSSatish Balay *nend = ALREADY_FREED; 301e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */ 302608c71bfSMatthew G. Knepley if (lineno > 0 && lineno < 50000) { 303608c71bfSMatthew G. Knepley head->lineno = lineno; 304608c71bfSMatthew G. Knepley head->filename = filename; 305e5c89e4eSSatish Balay head->functionname = function; 306e5c89e4eSSatish Balay } else { 307e5c89e4eSSatish Balay head->lineno = -head->lineno; 308e5c89e4eSSatish Balay } 309608c71bfSMatthew G. Knepley asize = TRrequestedSize ? head->rsize : head->size; 31008401ef6SPierre Jolivet PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 311608c71bfSMatthew G. Knepley TRallocated -= asize; 312e5c89e4eSSatish Balay TRfrags--; 313e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next; 314e5c89e4eSSatish Balay else TRhead = head->next; 315e5c89e4eSSatish Balay 316e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev; 3179566063dSJacob Faibussowitsch PetscCall(PetscFreeAlign(a, lineno, function, filename)); 3183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 319e5c89e4eSSatish Balay } 320e5c89e4eSSatish Balay 3213221ece2SMatthew G. Knepley /* 3222d853995SBarry Smith PetscTrReallocDefault - Realloc with logging and error checking 3233221ece2SMatthew G. Knepley 3243221ece2SMatthew G. Knepley */ 325d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) 326d71ae5a4SJacob Faibussowitsch { 3273221ece2SMatthew G. Knepley char *a = (char *)*result; 3283221ece2SMatthew G. Knepley TRSPACE *head; 3293221ece2SMatthew G. Knepley char *ahead, *inew; 3303221ece2SMatthew G. Knepley PetscClassId *nend; 3313221ece2SMatthew G. Knepley size_t nsize; 3323221ece2SMatthew G. Knepley 3333221ece2SMatthew G. Knepley PetscFunctionBegin; 33492f119d6SBarry Smith /* Realloc requests zero space so just free the current space */ 335c22f1541SToby Isaac if (!len) { 3369566063dSJacob Faibussowitsch PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 337c22f1541SToby Isaac *result = NULL; 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 339c22f1541SToby Isaac } 340da81f932SPierre Jolivet /* If the original space was NULL just use the regular malloc() */ 341f590eff4SLisandro Dalcin if (!*result) { 3429566063dSJacob Faibussowitsch PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344f590eff4SLisandro Dalcin } 3453221ece2SMatthew G. Knepley 34611cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename)); 3473221ece2SMatthew G. Knepley 3483221ece2SMatthew G. Knepley ahead = a; 3493221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3503221ece2SMatthew G. Knepley head = (TRSPACE *)a; 3513221ece2SMatthew G. Knepley inew = a; 3523221ece2SMatthew G. Knepley 3533221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 3542d853995SBarry Smith TRdebug = PETSC_FALSE; 3553ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3563ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a)); 3573221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 3583221ece2SMatthew G. Knepley } 3593221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3603221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3612d853995SBarry Smith TRdebug = PETSC_FALSE; 3623221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 3633ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3643ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE))); 3653221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 3663ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 3673221ece2SMatthew G. Knepley } else { 3683ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno)); 3693221ece2SMatthew G. Knepley } 3703221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 3713221ece2SMatthew G. Knepley } else { 3723221ece2SMatthew G. Knepley /* Damaged tail */ 3733ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3743ba16761SJacob 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)); 3753ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 3763221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 3773221ece2SMatthew G. Knepley } 3783221ece2SMatthew G. Knepley } 3793221ece2SMatthew G. Knepley 38092f119d6SBarry Smith /* remove original reference to the memory allocated from the PETSc debugging heap */ 381608c71bfSMatthew G. Knepley TRallocated -= TRrequestedSize ? head->rsize : head->size; 3823221ece2SMatthew G. Knepley TRfrags--; 3833221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 3843221ece2SMatthew G. Knepley else TRhead = head->next; 3853221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 3863221ece2SMatthew G. Knepley 3873221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 3889566063dSJacob Faibussowitsch PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 3893221ece2SMatthew G. Knepley 3903221ece2SMatthew G. Knepley head = (TRSPACE *)inew; 3913221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 3923221ece2SMatthew G. Knepley 3933221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 3943221ece2SMatthew G. Knepley head->next = TRhead; 3953221ece2SMatthew G. Knepley TRhead = head; 3963221ece2SMatthew G. Knepley head->prev = NULL; 3973221ece2SMatthew G. Knepley head->size = nsize; 398608c71bfSMatthew G. Knepley head->rsize = len; 399e269983cSBarry Smith head->id = TRid++; 4003221ece2SMatthew G. Knepley head->lineno = lineno; 4013221ece2SMatthew G. Knepley 4023221ece2SMatthew G. Knepley head->filename = filename; 4033221ece2SMatthew G. Knepley head->functionname = function; 4043221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4053221ece2SMatthew G. Knepley *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 4063221ece2SMatthew G. Knepley 407608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 4083221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 409e3ed9ee7SBarry Smith if (PetscLogMemory) { 4102d853995SBarry Smith for (PetscInt i = 0; i < NumTRMaxMems; i++) { 411e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 412e3ed9ee7SBarry Smith } 413e3ed9ee7SBarry Smith } 4143221ece2SMatthew G. Knepley TRfrags++; 4153221ece2SMatthew G. Knepley 416dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 4179566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 4183221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 4193221ece2SMatthew G. Knepley head->stack.line[head->stack.currentsize - 2] = lineno; 4203221ece2SMatthew G. Knepley #endif 4213221ece2SMatthew G. Knepley 4223221ece2SMatthew G. Knepley /* 42392f119d6SBarry Smith Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 42492f119d6SBarry Smith and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 4253221ece2SMatthew G. Knepley */ 4263221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4273221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4283221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 42928b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4303221ece2SMatthew G. Knepley 4313221ece2SMatthew G. Knepley PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 43228b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4333221ece2SMatthew G. Knepley 4343221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 43528b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4363221ece2SMatthew G. Knepley } 4373221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4383221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4393221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4403221ece2SMatthew G. Knepley } 4413221ece2SMatthew G. Knepley *result = (void *)inew; 4423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4433221ece2SMatthew G. Knepley } 4443221ece2SMatthew G. Knepley 445fe7fb379SMatthew Knepley /*@C 44692f119d6SBarry Smith PetscMemoryView - Shows the amount of memory currently being used in a communicator. 447e5c89e4eSSatish Balay 448c3339decSBarry Smith Collective 449e5c89e4eSSatish Balay 450d8d19677SJose E. Roman Input Parameters: 4510ed210f4SBarry Smith + viewer - the viewer to output the information on 452e5c89e4eSSatish Balay - message - string printed before values 453e5c89e4eSSatish Balay 454811af0c4SBarry Smith Options Database Keys: 45592f119d6SBarry Smith + -malloc_debug - have PETSc track how much memory it has allocated 4560ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used 4570ed210f4SBarry Smith - -memory_view - during `PetscFinalize()` have this routine called 4580841954dSBarry Smith 459e5c89e4eSSatish Balay Level: intermediate 460e5c89e4eSSatish Balay 4610ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 462e5c89e4eSSatish Balay @*/ 463d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) 464d71ae5a4SJacob Faibussowitsch { 4652d853995SBarry Smith PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax; 4662d853995SBarry Smith PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax; 467e5c89e4eSSatish Balay MPI_Comm comm; 468e5c89e4eSSatish Balay 469e5c89e4eSSatish Balay PetscFunctionBegin; 470e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 4719566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&allocated)); 4729566063dSJacob Faibussowitsch PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 4739566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&resident)); 4749566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 475e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 4769566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 4779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 478e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 4799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 4839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 4879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 4919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 495e5c89e4eSSatish Balay } else if (resident && residentmax) { 4969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 4979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 4989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 4999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 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)); 504e5c89e4eSSatish Balay } else if (resident && allocated) { 5059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 514e5c89e4eSSatish Balay } else if (allocated) { 5159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 5209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 521e5c89e4eSSatish Balay } else { 5229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 523e5c89e4eSSatish Balay } 5249566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 526e5c89e4eSSatish Balay } 527e5c89e4eSSatish Balay 52846eb3923SBarry Smith /*@ 529811af0c4SBarry Smith PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()` 530e5c89e4eSSatish Balay 531e5c89e4eSSatish Balay Not Collective 532e5c89e4eSSatish Balay 5332fe279fdSBarry Smith Output Parameter: 534e5c89e4eSSatish Balay . space - number of bytes currently allocated 535e5c89e4eSSatish Balay 536e5c89e4eSSatish Balay Level: intermediate 537e5c89e4eSSatish Balay 5382d853995SBarry Smith Note: 5392d853995SBarry Smith This only works if `-memory_view` or `-log_view_memory` have been used 5402d853995SBarry Smith 5410ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 542db781477SPatrick Sanan `PetscMemoryGetMaximumUsage()` 543e5c89e4eSSatish Balay @*/ 544d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 545d71ae5a4SJacob Faibussowitsch { 546e5c89e4eSSatish Balay PetscFunctionBegin; 547e5c89e4eSSatish Balay *space = (PetscLogDouble)TRallocated; 5483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 549e5c89e4eSSatish Balay } 550e5c89e4eSSatish Balay 551dc37d89fSBarry Smith /*@ 552811af0c4SBarry Smith PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time 553811af0c4SBarry Smith during this run, the high water mark. 554e5c89e4eSSatish Balay 555e5c89e4eSSatish Balay Not Collective 556e5c89e4eSSatish Balay 5572fe279fdSBarry Smith Output Parameter: 558e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 559e5c89e4eSSatish Balay 560e5c89e4eSSatish Balay Level: intermediate 561e5c89e4eSSatish Balay 5622d853995SBarry Smith Note: 5632d853995SBarry Smith This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 5642d853995SBarry Smith 5650ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 566db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 567e5c89e4eSSatish Balay @*/ 568d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 569d71ae5a4SJacob Faibussowitsch { 570e5c89e4eSSatish Balay PetscFunctionBegin; 571e5c89e4eSSatish Balay *space = (PetscLogDouble)TRMaxMem; 5723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 573e5c89e4eSSatish Balay } 574e5c89e4eSSatish Balay 575e3ed9ee7SBarry Smith /*@ 576e3ed9ee7SBarry Smith PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 577e3ed9ee7SBarry Smith 578e3ed9ee7SBarry Smith Not Collective 579e3ed9ee7SBarry Smith 580e3ed9ee7SBarry Smith Input Parameter: 581e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 582e3ed9ee7SBarry Smith 583e3ed9ee7SBarry Smith Level: developer 584e3ed9ee7SBarry Smith 5852d853995SBarry Smith Note: 5862d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 5872d853995SBarry Smith 5880ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 589db781477SPatrick Sanan `PetscMallocPopMaximumUsage()` 590e3ed9ee7SBarry Smith @*/ 591d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event) 592d71ae5a4SJacob Faibussowitsch { 593e3ed9ee7SBarry Smith PetscFunctionBegin; 5943ba16761SJacob Faibussowitsch if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 595e3ed9ee7SBarry Smith TRMaxMems[NumTRMaxMems - 1] = TRallocated; 596e3ed9ee7SBarry Smith TRMaxMemsEvents[NumTRMaxMems - 1] = event; 5973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 598e3ed9ee7SBarry Smith } 599e3ed9ee7SBarry Smith 600e3ed9ee7SBarry Smith /*@ 601e3ed9ee7SBarry Smith PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 602e3ed9ee7SBarry Smith 603e3ed9ee7SBarry Smith Not Collective 604e3ed9ee7SBarry Smith 605e3ed9ee7SBarry Smith Input Parameter: 606e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 607e3ed9ee7SBarry Smith 608e3ed9ee7SBarry Smith Output Parameter: 609e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 610e3ed9ee7SBarry Smith 611e3ed9ee7SBarry Smith Level: developer 612e3ed9ee7SBarry Smith 6132d853995SBarry Smith Note: 6142d853995SBarry Smith This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used 6152d853995SBarry Smith 6160ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 617db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 618e3ed9ee7SBarry Smith @*/ 619d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) 620d71ae5a4SJacob Faibussowitsch { 621e3ed9ee7SBarry Smith PetscFunctionBegin; 622e3ed9ee7SBarry Smith *mu = 0; 6233ba16761SJacob Faibussowitsch if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 62408401ef6SPierre Jolivet PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 625e3ed9ee7SBarry Smith *mu = TRMaxMems[NumTRMaxMems]; 6263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 627e3ed9ee7SBarry Smith } 628e3ed9ee7SBarry Smith 629a64a8e02SBarry Smith /*@C 630811af0c4SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory 631a64a8e02SBarry Smith 6320ed210f4SBarry Smith Not Collective 633a64a8e02SBarry Smith 634a64a8e02SBarry Smith Input Parameter: 635a64a8e02SBarry Smith . ptr - the memory location 636a64a8e02SBarry Smith 637fd292e60Sprj- Output Parameter: 638a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 639a64a8e02SBarry Smith 640a64a8e02SBarry Smith Level: intermediate 641a64a8e02SBarry Smith 6422d853995SBarry Smith Note: 6432d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 6442d853995SBarry Smith 6450ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 646a64a8e02SBarry Smith @*/ 647d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) 648d71ae5a4SJacob Faibussowitsch { 649dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 650a64a8e02SBarry Smith TRSPACE *head; 651a64a8e02SBarry Smith 652a64a8e02SBarry Smith PetscFunctionBegin; 653a64a8e02SBarry Smith head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 654a64a8e02SBarry Smith *stack = &head->stack; 6553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65676386721SLisandro Dalcin #else 657f0ba7cfcSLisandro Dalcin *stack = NULL; 6583ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 659a64a8e02SBarry Smith #endif 660dfb7d7afSStefano Zampini } 661a64a8e02SBarry Smith 662e5c89e4eSSatish Balay /*@C 66392f119d6SBarry Smith PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 664e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 665e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 666e5c89e4eSSatish Balay allocated. 667e5c89e4eSSatish Balay 66892f119d6SBarry Smith Not Collective 669e5c89e4eSSatish Balay 670e5c89e4eSSatish Balay Input Parameter: 6710ed210f4SBarry Smith . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed. 672e5c89e4eSSatish Balay 673e5c89e4eSSatish Balay Options Database Key: 6740ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given 675e5c89e4eSSatish Balay 676e5c89e4eSSatish Balay Level: intermediate 677e5c89e4eSSatish Balay 67895452b02SPatrick Sanan Notes: 679811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed. 680e5c89e4eSSatish Balay 681811af0c4SBarry Smith When called in `PetscFinalize()` dumps only the allocations that have not been properly freed 68292f119d6SBarry Smith 683811af0c4SBarry Smith `PetscMallocView()` prints a list of all memory ever allocated 68492f119d6SBarry Smith 6852d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 6862d853995SBarry Smith 687*aec76313SJacob Faibussowitsch Fortran Notes: 6880ed210f4SBarry Smith The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported. 68920f4b53cSBarry Smith 690*aec76313SJacob Faibussowitsch Developer Notes: 6912d853995SBarry Smith This should be absorbed into `PetscMallocView()` 6922d853995SBarry Smith 6930ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 694e5c89e4eSSatish Balay @*/ 695d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp) 696d71ae5a4SJacob Faibussowitsch { 697e5c89e4eSSatish Balay TRSPACE *head; 698e3ed9ee7SBarry Smith size_t libAlloc = 0; 699e5c89e4eSSatish Balay PetscMPIInt rank; 700e5c89e4eSSatish Balay 701e5c89e4eSSatish Balay PetscFunctionBegin; 7029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 703da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 704e5c89e4eSSatish Balay head = TRhead; 705e5c89e4eSSatish Balay while (head) { 706608c71bfSMatthew G. Knepley libAlloc += TRrequestedSize ? head->rsize : head->size; 7075486ca60SMatthew G. Knepley head = head->next; 7085486ca60SMatthew G. Knepley } 7095486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 7105486ca60SMatthew G. Knepley head = TRhead; 7115486ca60SMatthew G. Knepley while (head) { 7125486ca60SMatthew G. Knepley PetscBool isLib; 7135486ca60SMatthew G. Knepley 7149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 7155486ca60SMatthew G. Knepley if (!isLib) { 716dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 7172d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size)); 7189566063dSJacob Faibussowitsch PetscCall(PetscStackPrint(&head->stack, fp)); 7192d853995SBarry Smith #else 7202d853995SBarry Smith fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 721e5c89e4eSSatish Balay #endif 7225486ca60SMatthew G. Knepley } 723e5c89e4eSSatish Balay head = head->next; 724e5c89e4eSSatish Balay } 7253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 726e5c89e4eSSatish Balay } 727e5c89e4eSSatish Balay 728dc37d89fSBarry Smith /*@ 729811af0c4SBarry Smith PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view 730574034a9SJed Brown 731574034a9SJed Brown Not Collective 732574034a9SJed Brown 7334165533cSJose E. Roman Input Parameter: 7340ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations 735574034a9SJed Brown 7360ed210f4SBarry Smith Options Database Keys: 737811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 7382d853995SBarry Smith . -malloc_view_threshold <min> - Sets a minimum size if `-malloc_view` is used 7398b254c29SBarry Smith - -log_view_memory - view the memory usage also with the -log_view option 740574034a9SJed Brown 741574034a9SJed Brown Level: advanced 742574034a9SJed Brown 7430ed210f4SBarry Smith Note: 744811af0c4SBarry Smith Must be called after `PetscMallocSetDebug()` 74592f119d6SBarry Smith 746*aec76313SJacob Faibussowitsch Developer Notes: 747811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available 74892f119d6SBarry Smith 7490ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 750574034a9SJed Brown @*/ 751d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) 752d71ae5a4SJacob Faibussowitsch { 753574034a9SJed Brown PetscFunctionBegin; 75492f119d6SBarry Smith PetscLogMalloc = 0; 7559566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 756574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 757574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 7583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 759574034a9SJed Brown } 760574034a9SJed Brown 761dc37d89fSBarry Smith /*@ 762811af0c4SBarry Smith PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged 76318a2528dSJed Brown 76418a2528dSJed Brown Not Collective 76518a2528dSJed Brown 7664165533cSJose E. Roman Output Parameter 767811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 76818a2528dSJed Brown 76918a2528dSJed Brown Options Database Key: 770811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 77118a2528dSJed Brown 77218a2528dSJed Brown Level: advanced 77318a2528dSJed Brown 7740ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()` 77518a2528dSJed Brown @*/ 776d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging) 777d71ae5a4SJacob Faibussowitsch { 77818a2528dSJed Brown PetscFunctionBegin; 77918a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 7803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78118a2528dSJed Brown } 78218a2528dSJed Brown 783608c71bfSMatthew G. Knepley /*@ 7842d853995SBarry Smith PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer. 785608c71bfSMatthew G. Knepley 786608c71bfSMatthew G. Knepley Not Collective 787608c71bfSMatthew G. Knepley 7884165533cSJose E. Roman Input Parameters: 7890ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF` 790608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing 791608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged 792608c71bfSMatthew G. Knepley 7930ed210f4SBarry Smith Level: advanced 7940ed210f4SBarry Smith 795608c71bfSMatthew G. Knepley Note: 796608c71bfSMatthew G. Knepley The viewer should not be collective. 797608c71bfSMatthew G. Knepley 7982d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 7992d853995SBarry Smith 8000ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 801608c71bfSMatthew G. Knepley @*/ 802d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) 803d71ae5a4SJacob Faibussowitsch { 804608c71bfSMatthew G. Knepley PetscFunctionBegin; 8059371c9d4SSatish Balay if (!active) { 8069371c9d4SSatish Balay PetscLogMallocTrace = -1; 8073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8089371c9d4SSatish Balay } 8090ed210f4SBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 8100ed210f4SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 8110ed210f4SBarry Smith PetscLogMallocTraceViewer = viewer; 812608c71bfSMatthew G. Knepley PetscLogMallocTrace = 0; 8139566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 814608c71bfSMatthew G. Knepley if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 815608c71bfSMatthew G. Knepley PetscLogMallocTraceThreshold = (size_t)logmin; 8163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 817608c71bfSMatthew G. Knepley } 818608c71bfSMatthew G. Knepley 819608c71bfSMatthew G. Knepley /*@ 820811af0c4SBarry Smith PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced 821608c71bfSMatthew G. Knepley 822608c71bfSMatthew G. Knepley Not Collective 823608c71bfSMatthew G. Knepley 8244165533cSJose E. Roman Output Parameter: 825811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 826608c71bfSMatthew G. Knepley 827608c71bfSMatthew G. Knepley Options Database Key: 8280ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 829608c71bfSMatthew G. Knepley 830608c71bfSMatthew G. Knepley Level: advanced 831608c71bfSMatthew G. Knepley 8322d853995SBarry Smith This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used 8332d853995SBarry Smith 8340ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 835608c71bfSMatthew G. Knepley @*/ 836d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging) 837d71ae5a4SJacob Faibussowitsch { 838608c71bfSMatthew G. Knepley PetscFunctionBegin; 839608c71bfSMatthew G. Knepley *logging = (PetscBool)(PetscLogMallocTrace >= 0); 8403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 841608c71bfSMatthew G. Knepley } 842608c71bfSMatthew G. Knepley 843e5c89e4eSSatish Balay /*@C 8442d853995SBarry Smith PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()` 845e5c89e4eSSatish Balay 84692f119d6SBarry Smith Not Collective 847e5c89e4eSSatish Balay 848e5c89e4eSSatish Balay Input Parameter: 8490ed210f4SBarry Smith . fp - file pointer; or `NULL` 850e5c89e4eSSatish Balay 851e5c89e4eSSatish Balay Options Database Key: 852811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 853e5c89e4eSSatish Balay 854e5c89e4eSSatish Balay Level: advanced 855e5c89e4eSSatish Balay 85692f119d6SBarry Smith Notes: 857811af0c4SBarry Smith `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated 85892f119d6SBarry Smith 859811af0c4SBarry Smith `PetscMemoryView()` gives a brief summary of current memory usage 86092f119d6SBarry Smith 86120f4b53cSBarry Smith Fortran Notes: 8620ed210f4SBarry Smith The calling sequence in Fortran is `PetscMallocView`(integer ierr) 86320f4b53cSBarry Smith 8640ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()` 865e5c89e4eSSatish Balay @*/ 866d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp) 867d71ae5a4SJacob Faibussowitsch { 8682d853995SBarry Smith PetscInt n, *perm; 869e5c89e4eSSatish Balay size_t *shortlength; 870c69effb2SJacob Faibussowitsch int *shortcount; 87192f119d6SBarry Smith PetscMPIInt rank; 872ace3abfcSBarry Smith PetscBool match; 873e5c89e4eSSatish Balay const char **shortfunction; 874e5c89e4eSSatish Balay PetscLogDouble rss; 875e5c89e4eSSatish Balay 876e5c89e4eSSatish Balay PetscFunctionBegin; 8779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 878c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp)); 879f56c2debSBarry Smith 88008401ef6SPierre Jolivet PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 881768aa557SSatish Balay 882da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 8839566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&rss)); 884e5c89e4eSSatish Balay if (rss) { 88592f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 886e5c89e4eSSatish Balay } else { 88792f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 888e5c89e4eSSatish Balay } 889b13f2904SStefano Zampini if (PetscLogMalloc > 0) { 8909371c9d4SSatish Balay shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 8919371c9d4SSatish Balay PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8929371c9d4SSatish Balay shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 8939371c9d4SSatish Balay PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8949371c9d4SSatish Balay shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 8959371c9d4SSatish Balay PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8962d853995SBarry Smith n = 0; 8972d853995SBarry Smith for (PetscInt i = 0; i < PetscLogMalloc; i++) { 8982d853995SBarry Smith for (PetscInt j = 0; j < n; j++) { 8999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 900e5c89e4eSSatish Balay if (match) { 901e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 90259ffdab8SBarry Smith shortcount[j]++; 903e5c89e4eSSatish Balay goto foundit; 904e5c89e4eSSatish Balay } 905e5c89e4eSSatish Balay } 906e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 907e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 90859ffdab8SBarry Smith shortcount[n] = 1; 909e5c89e4eSSatish Balay n++; 910e5c89e4eSSatish Balay foundit:; 911e5c89e4eSSatish Balay } 912e5c89e4eSSatish Balay 9139371c9d4SSatish Balay perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 9149371c9d4SSatish Balay PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 9152d853995SBarry Smith for (PetscInt i = 0; i < n; i++) perm[i] = i; 9169566063dSJacob Faibussowitsch PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 917e5c89e4eSSatish Balay 91892f119d6SBarry Smith (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 9192d853995SBarry 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]]); 920e5c89e4eSSatish Balay free(perm); 921e5c89e4eSSatish Balay free(shortlength); 92259ffdab8SBarry Smith free(shortcount); 923e5c89e4eSSatish Balay free((char **)shortfunction); 924b13f2904SStefano Zampini } 925c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp)); 9263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 927e5c89e4eSSatish Balay } 928e5c89e4eSSatish Balay 929dc37d89fSBarry Smith /*@ 93092f119d6SBarry Smith PetscMallocSetDebug - Set's PETSc memory debugging 931e5c89e4eSSatish Balay 932e5c89e4eSSatish Balay Not Collective 933e5c89e4eSSatish Balay 934d8d19677SJose E. Roman Input Parameters: 935811af0c4SBarry Smith + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow 9360ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays 937e5c89e4eSSatish Balay 938811af0c4SBarry Smith Options Database Keys: 93979dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging 9400ed210f4SBarry Smith . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored 94179dccf82SBarry Smith . -malloc_view_threshold t - log only allocations larger than t 9422d853995SBarry Smith . -malloc_dump <filename> - print a list of all memory that has not been freed, in `PetscFinalize()` 943e5c89e4eSSatish Balay 94492f119d6SBarry Smith Level: developer 94592f119d6SBarry Smith 946811af0c4SBarry Smith Note: 947811af0c4SBarry Smith This is called in `PetscInitialize()` and should not be called elsewhere 94892f119d6SBarry Smith 9492d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()` 950e5c89e4eSSatish Balay @*/ 951d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) 952d71ae5a4SJacob Faibussowitsch { 953e5c89e4eSSatish Balay PetscFunctionBegin; 95408401ef6SPierre 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()"); 9559566063dSJacob Faibussowitsch PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 95692f119d6SBarry Smith 95792f119d6SBarry Smith TRallocated = 0; 95892f119d6SBarry Smith TRfrags = 0; 95992f119d6SBarry Smith TRhead = NULL; 96092f119d6SBarry Smith TRid = 0; 9612d853995SBarry Smith TRdebug = eachcall; 96292f119d6SBarry Smith TRMaxMem = 0; 96392f119d6SBarry Smith PetscLogMallocMax = 10000; 96492f119d6SBarry Smith PetscLogMalloc = -1; 9652d4ee042Sprj- TRdebugIinitializenan = initializenan; 9663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 967e5c89e4eSSatish Balay } 9680acecf5bSBarry Smith 969dc37d89fSBarry Smith /*@ 97092f119d6SBarry Smith PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 9710acecf5bSBarry Smith 9720acecf5bSBarry Smith Not Collective 9730acecf5bSBarry Smith 97492f119d6SBarry Smith Output Parameters: 97592f119d6SBarry Smith + basic - doing basic debugging 976811af0c4SBarry Smith . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()` 9770ed210f4SBarry Smith - initializenan - initializes memory with `NaN` 9780acecf5bSBarry Smith 9790acecf5bSBarry Smith Level: intermediate 9800acecf5bSBarry Smith 981811af0c4SBarry Smith Note: 9822d853995SBarry Smith By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no` 9830acecf5bSBarry Smith 9842d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()` 9850acecf5bSBarry Smith @*/ 986d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) 987d71ae5a4SJacob Faibussowitsch { 9880acecf5bSBarry Smith PetscFunctionBegin; 98979dccf82SBarry Smith if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 9902d853995SBarry Smith if (eachcall) *eachcall = TRdebug; 9912d4ee042Sprj- if (initializenan) *initializenan = TRdebugIinitializenan; 9923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9930acecf5bSBarry Smith } 994608c71bfSMatthew G. Knepley 995608c71bfSMatthew G. Knepley /*@ 996608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 997608c71bfSMatthew G. Knepley 998608c71bfSMatthew G. Knepley Not Collective 999608c71bfSMatthew G. Knepley 1000608c71bfSMatthew G. Knepley Input Parameter: 1001811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size 1002608c71bfSMatthew G. Knepley 1003811af0c4SBarry Smith Options Database Key: 1004608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag 1005608c71bfSMatthew G. Knepley 1006608c71bfSMatthew G. Knepley Level: developer 1007608c71bfSMatthew G. Knepley 10080ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1009608c71bfSMatthew G. Knepley @*/ 1010d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) 1011d71ae5a4SJacob Faibussowitsch { 1012608c71bfSMatthew G. Knepley PetscFunctionBegin; 1013608c71bfSMatthew G. Knepley TRrequestedSize = flg; 10143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1015608c71bfSMatthew G. Knepley } 1016608c71bfSMatthew G. Knepley 1017608c71bfSMatthew G. Knepley /*@ 1018608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1019608c71bfSMatthew G. Knepley 1020608c71bfSMatthew G. Knepley Not Collective 1021608c71bfSMatthew G. Knepley 1022608c71bfSMatthew G. Knepley Output Parameter: 1023811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size 1024608c71bfSMatthew G. Knepley 1025608c71bfSMatthew G. Knepley Level: developer 1026608c71bfSMatthew G. Knepley 10270ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1028608c71bfSMatthew G. Knepley @*/ 1029d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) 1030d71ae5a4SJacob Faibussowitsch { 1031608c71bfSMatthew G. Knepley PetscFunctionBegin; 1032608c71bfSMatthew G. Knepley *flg = TRrequestedSize; 10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1034608c71bfSMatthew G. Knepley } 1035