17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 392f119d6SBarry Smith Interface to malloc() and free(). This code allows for logging of memory usage and some error checking 4e5c89e4eSSatish Balay */ 527104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6665c2dedSJed Brown #include <petscviewer.h> 7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 8e5c89e4eSSatish Balay #include <malloc.h> 9e5c89e4eSSatish Balay #endif 10e5c89e4eSSatish Balay 11e5c89e4eSSatish Balay /* 12e5c89e4eSSatish Balay These are defined in mal.c and ensure that malloced space is PetscScalar aligned 13e5c89e4eSSatish Balay */ 14071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **); 1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]); 1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **); 17e5c89e4eSSatish Balay 180700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9) 190700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c) 20e5c89e4eSSatish Balay 2192f119d6SBarry Smith /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */ 22e5c89e4eSSatish Balay typedef struct _trSPACE { 23608c71bfSMatthew G. Knepley size_t size, rsize; /* Aligned size and requested size */ 24e5c89e4eSSatish Balay int id; 25e5c89e4eSSatish Balay int lineno; 26e5c89e4eSSatish Balay const char *filename; 27e5c89e4eSSatish Balay const char *functionname; 280700a824SBarry Smith PetscClassId classid; 29dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 30e5c89e4eSSatish Balay PetscStack stack; 31e5c89e4eSSatish Balay #endif 32e5c89e4eSSatish Balay struct _trSPACE *next, *prev; 33e5c89e4eSSatish Balay } TRSPACE; 34e5c89e4eSSatish Balay 3525b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 3692f119d6SBarry Smith It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN. 3725b53cc9SJed Brown */ 38a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1)) 39e5c89e4eSSatish Balay 4025b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains 4125b53cc9SJed Brown a minimum alignment of PETSC_MEMALIGN. 4225b53cc9SJed Brown */ 439371c9d4SSatish Balay typedef union 449371c9d4SSatish Balay { 45e5c89e4eSSatish Balay TRSPACE sp; 4625b53cc9SJed Brown char v[HEADER_BYTES]; 47e5c89e4eSSatish Balay } TrSPACE; 48e5c89e4eSSatish Balay 49e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50 50e5c89e4eSSatish Balay static size_t TRallocated = 0; 51e5c89e4eSSatish Balay static int TRfrags = 0; 52f0ba7cfcSLisandro Dalcin static TRSPACE *TRhead = NULL; 53e5c89e4eSSatish Balay static int TRid = 0; 54ace3abfcSBarry Smith static PetscBool TRdebugLevel = PETSC_FALSE; 552d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE; 56608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize = PETSC_FALSE; 57e5c89e4eSSatish Balay static size_t TRMaxMem = 0; 58e3ed9ee7SBarry Smith static int NumTRMaxMems = 0; 59e3ed9ee7SBarry Smith static size_t TRMaxMems[MAXTRMAXMEMS]; 60e3ed9ee7SBarry Smith static int TRMaxMemsEvents[MAXTRMAXMEMS]; 61e5c89e4eSSatish Balay /* 6292f119d6SBarry Smith Arrays to log information on mallocs for PetscMallocView() 63e5c89e4eSSatish Balay */ 64f0ba7cfcSLisandro Dalcin static int PetscLogMallocMax = 10000; 65f0ba7cfcSLisandro Dalcin static int PetscLogMalloc = -1; 66574034a9SJed Brown static size_t PetscLogMallocThreshold = 0; 67e5c89e4eSSatish Balay static size_t *PetscLogMallocLength; 68efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction; 69608c71bfSMatthew G. Knepley static int PetscLogMallocTrace = -1; 70608c71bfSMatthew G. Knepley static size_t PetscLogMallocTraceThreshold = 0; 71608c71bfSMatthew G. Knepley static PetscViewer PetscLogMallocTraceViewer = NULL; 72b022a5c1SBarry Smith 73e5c89e4eSSatish Balay /*@C 74811af0c4SBarry Smith PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()` 75e5c89e4eSSatish Balay 7692f119d6SBarry Smith Input Parameters: 77e5c89e4eSSatish Balay + line - line number where call originated. 78e5c89e4eSSatish Balay . function - name of function calling 79efca3c55SSatish Balay - file - file where function is 80e5c89e4eSSatish Balay 81e5c89e4eSSatish Balay Return value: 82e5c89e4eSSatish Balay The number of errors detected. 83e5c89e4eSSatish Balay 84811af0c4SBarry Smith Options Database Keys:. 85*0ed210f4SBarry Smith + -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0` 8692f119d6SBarry Smith - -malloc_debug - turns this feature on anytime 8792f119d6SBarry Smith 88e5c89e4eSSatish Balay Level: advanced 89e5c89e4eSSatish Balay 90e5c89e4eSSatish Balay Notes: 91*0ed210f4SBarry Smith Error messages are written to `stdout`. 92*0ed210f4SBarry Smith 93*0ed210f4SBarry 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) 9438548759SBarry Smith 95811af0c4SBarry Smith You should generally use `CHKMEMQ` as a short cut for calling this routine. 96e5c89e4eSSatish Balay 97e5c89e4eSSatish Balay No output is generated if there are no problems detected. 98e5c89e4eSSatish Balay 9920f4b53cSBarry Smith Fortran Note: 10020f4b53cSBarry Smith The Fortran calling sequence is simply `PetscMallocValidate(ierr)` 10120f4b53cSBarry Smith 10292f119d6SBarry Smith Developers Note: 10320f4b53cSBarry Smith Uses the flg `TRdebugLevel` (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run 10492f119d6SBarry Smith 105*0ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()` 106e5c89e4eSSatish Balay @*/ 107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) 108d71ae5a4SJacob Faibussowitsch { 1096c093d5bSvictor TRSPACE *head, *lasthead; 110e5c89e4eSSatish Balay char *a; 1110700a824SBarry Smith PetscClassId *nend; 112e5c89e4eSSatish Balay 1133ba16761SJacob Faibussowitsch if (!TRdebugLevel) return PETSC_SUCCESS; 1149371c9d4SSatish Balay head = TRhead; 1159371c9d4SSatish Balay lasthead = NULL; 1162cba8197SMatthew G. Knepley if (head && head->prev) { 1173ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 1183ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev)); 1194ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 1202cba8197SMatthew G. Knepley } 121e5c89e4eSSatish Balay while (head) { 1220700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 1233ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 1243ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head)); 1253ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n")); 126e269983cSBarry Smith if (lasthead) { 127e269983cSBarry Smith a = (char *)(((TrSPACE *)head) + 1); 1283ba16761SJacob 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)); 129e269983cSBarry Smith } 130e269983cSBarry Smith abort(); 1314ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 132e5c89e4eSSatish Balay } 133e5c89e4eSSatish Balay a = (char *)(((TrSPACE *)head) + 1); 1340700a824SBarry Smith nend = (PetscClassId *)(a + head->size); 1350700a824SBarry Smith if (*nend != CLASSID_VALUE) { 1363ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 137e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 1383ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a)); 1394ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 140e5c89e4eSSatish Balay } else { 1413ba16761SJacob 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)); 1423ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 1434ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 144e5c89e4eSSatish Balay } 145e5c89e4eSSatish Balay } 1462cba8197SMatthew G. Knepley if (head->prev && head->prev != lasthead) { 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 /* 160e5c89e4eSSatish Balay PetscTrMallocDefault - Malloc with tracing. 161e5c89e4eSSatish Balay 162e5c89e4eSSatish Balay Input Parameters: 163e5c89e4eSSatish Balay + a - number of bytes to allocate 164*0ed210f4SBarry Smith . lineno - line number where used. Use `__LINE__` for this 165*0ed210f4SBarry Smith - filename - file name where used. Use `__FILE__` for this 166e5c89e4eSSatish Balay 167*0ed210f4SBarry Smith Output Parameter: 168*0ed210f4SBarry Smith double aligned pointer to requested storage 169e5c89e4eSSatish Balay */ 170d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) 171d71ae5a4SJacob Faibussowitsch { 172e5c89e4eSSatish Balay TRSPACE *head; 173e5c89e4eSSatish Balay char *inew; 174e5c89e4eSSatish Balay size_t nsize; 175e5c89e4eSSatish Balay 176e5c89e4eSSatish Balay PetscFunctionBegin; 177f0ba7cfcSLisandro Dalcin /* Do not try to handle empty blocks */ 1789371c9d4SSatish Balay if (!a) { 1799371c9d4SSatish Balay *result = NULL; 1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1819371c9d4SSatish Balay } 182f0ba7cfcSLisandro Dalcin 18311cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename)); 184e5c89e4eSSatish Balay 18525b53cc9SJed Brown nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 1869566063dSJacob Faibussowitsch PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew)); 187e3ed9ee7SBarry Smith 188e5c89e4eSSatish Balay head = (TRSPACE *)inew; 189e5c89e4eSSatish Balay inew += sizeof(TrSPACE); 190e5c89e4eSSatish Balay 191e5c89e4eSSatish Balay if (TRhead) TRhead->prev = head; 192e5c89e4eSSatish Balay head->next = TRhead; 193e5c89e4eSSatish Balay TRhead = head; 194f0ba7cfcSLisandro Dalcin head->prev = NULL; 195e5c89e4eSSatish Balay head->size = nsize; 196608c71bfSMatthew G. Knepley head->rsize = a; 197e269983cSBarry Smith head->id = TRid++; 198e5c89e4eSSatish Balay head->lineno = lineno; 199e5c89e4eSSatish Balay 200e5c89e4eSSatish Balay head->filename = filename; 201e5c89e4eSSatish Balay head->functionname = function; 2020700a824SBarry Smith head->classid = CLASSID_VALUE; 2030700a824SBarry Smith *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 204e5c89e4eSSatish Balay 205608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 206a297a907SKarl Rupp if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 207e3ed9ee7SBarry Smith if (PetscLogMemory) { 208e3ed9ee7SBarry Smith PetscInt i; 209e3ed9ee7SBarry Smith for (i = 0; i < NumTRMaxMems; i++) { 210e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 211e3ed9ee7SBarry Smith } 212e3ed9ee7SBarry Smith } 213e5c89e4eSSatish Balay TRfrags++; 214e5c89e4eSSatish Balay 215dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 2169566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 2172c9581d2SBarry Smith /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 2182c9581d2SBarry Smith head->stack.line[head->stack.currentsize - 2] = lineno; 21992f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE) 2202d4ee042Sprj- if (!clear && TRdebugIinitializenan) { 22192f119d6SBarry Smith size_t i, n = a / sizeof(PetscReal); 22292f119d6SBarry Smith PetscReal *s = (PetscReal *)inew; 22392f119d6SBarry Smith /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */ 22492f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) 225df282883SBarry Smith int nas = 0x7F800002; 22692f119d6SBarry Smith #else 22792f119d6SBarry Smith PetscInt64 nas = 0x7FF0000000000002; 22892f119d6SBarry Smith #endif 229ad540459SPierre Jolivet for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal)); 23092f119d6SBarry Smith } 23192f119d6SBarry Smith #endif 232e5c89e4eSSatish Balay #endif 233e5c89e4eSSatish Balay 234e5c89e4eSSatish Balay /* 23592f119d6SBarry Smith Allow logging of all mallocs made. 23692f119d6SBarry Smith TODO: Currently this memory is never freed, it should be freed during PetscFinalize() 237e5c89e4eSSatish Balay */ 238574034a9SJed Brown if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 239e5c89e4eSSatish Balay if (!PetscLogMalloc) { 240e5c89e4eSSatish Balay PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 24128b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 242a297a907SKarl Rupp 243a2ea699eSBarry Smith PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 24428b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 245a297a907SKarl Rupp 246a2ea699eSBarry Smith PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 24728b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 248e5c89e4eSSatish Balay } 249e5c89e4eSSatish Balay PetscLogMallocLength[PetscLogMalloc] = nsize; 250e5c89e4eSSatish Balay PetscLogMallocFile[PetscLogMalloc] = filename; 251e5c89e4eSSatish Balay PetscLogMallocFunction[PetscLogMalloc++] = function; 252e5c89e4eSSatish Balay } 25348a46eb9SPierre Jolivet if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); 254e5c89e4eSSatish Balay *result = (void *)inew; 2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 256e5c89e4eSSatish Balay } 257e5c89e4eSSatish Balay 258e5c89e4eSSatish Balay /* 259e5c89e4eSSatish Balay PetscTrFreeDefault - Free with tracing. 260e5c89e4eSSatish Balay 261e5c89e4eSSatish Balay Input Parameters: 262*0ed210f4SBarry Smith + a - pointer to a block allocated with `PetscTrMallocDefault()` 263*0ed210f4SBarry Smith . lineno - line number where used. Use `__LINE__` for this 264*0ed210f4SBarry Smith - filename - file name where used. Use `__FILE__` for this 265*0ed210f4SBarry Smith 266*0ed210f4SBarry Smith Level: developer 267e5c89e4eSSatish Balay */ 268d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) 269d71ae5a4SJacob Faibussowitsch { 270e5c89e4eSSatish Balay char *a = (char *)aa; 271e5c89e4eSSatish Balay TRSPACE *head; 272e5c89e4eSSatish Balay char *ahead; 273608c71bfSMatthew G. Knepley size_t asize; 2740700a824SBarry Smith PetscClassId *nend; 275e5c89e4eSSatish Balay 276e5c89e4eSSatish Balay PetscFunctionBegin; 277e5c89e4eSSatish Balay /* Do not try to handle empty blocks */ 2783ba16761SJacob Faibussowitsch if (!a) PetscFunctionReturn(PETSC_SUCCESS); 279e5c89e4eSSatish Balay 2809566063dSJacob Faibussowitsch PetscCall(PetscMallocValidate(lineno, function, filename)); 281e5c89e4eSSatish Balay 282e5c89e4eSSatish Balay ahead = a; 283e5c89e4eSSatish Balay a = a - sizeof(TrSPACE); 284e5c89e4eSSatish Balay head = (TRSPACE *)a; 285e5c89e4eSSatish Balay 2860700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 2873ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 2883ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a)); 289e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 290e5c89e4eSSatish Balay } 2910700a824SBarry Smith nend = (PetscClassId *)(ahead + head->size); 2920700a824SBarry Smith if (*nend != CLASSID_VALUE) { 293e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 2943ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 2953ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE))); 296e5c89e4eSSatish Balay if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 2973ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 298e5c89e4eSSatish Balay } else { 2993ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno)); 300e5c89e4eSSatish Balay } 301e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 302e5c89e4eSSatish Balay } else { 303e5c89e4eSSatish Balay /* Damaged tail */ 3043ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3053ba16761SJacob 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)); 3063ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 307e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 308e5c89e4eSSatish Balay } 309e5c89e4eSSatish Balay } 310608c71bfSMatthew G. Knepley if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 3119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 312608c71bfSMatthew G. Knepley } 313e5c89e4eSSatish Balay /* Mark the location freed */ 314e5c89e4eSSatish Balay *nend = ALREADY_FREED; 315e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */ 316608c71bfSMatthew G. Knepley if (lineno > 0 && lineno < 50000) { 317608c71bfSMatthew G. Knepley head->lineno = lineno; 318608c71bfSMatthew G. Knepley head->filename = filename; 319e5c89e4eSSatish Balay head->functionname = function; 320e5c89e4eSSatish Balay } else { 321e5c89e4eSSatish Balay head->lineno = -head->lineno; 322e5c89e4eSSatish Balay } 323608c71bfSMatthew G. Knepley asize = TRrequestedSize ? head->rsize : head->size; 32408401ef6SPierre Jolivet PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 325608c71bfSMatthew G. Knepley TRallocated -= asize; 326e5c89e4eSSatish Balay TRfrags--; 327e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next; 328e5c89e4eSSatish Balay else TRhead = head->next; 329e5c89e4eSSatish Balay 330e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev; 3319566063dSJacob Faibussowitsch PetscCall(PetscFreeAlign(a, lineno, function, filename)); 3323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 333e5c89e4eSSatish Balay } 334e5c89e4eSSatish Balay 3353221ece2SMatthew G. Knepley /* 3363221ece2SMatthew G. Knepley PetscTrReallocDefault - Realloc with tracing. 3373221ece2SMatthew G. Knepley 3383221ece2SMatthew G. Knepley Input Parameters: 3393221ece2SMatthew G. Knepley + len - number of bytes to allocate 340*0ed210f4SBarry Smith . lineno - line number where used. Use `__LINE__` for this 341*0ed210f4SBarry Smith . filename - file name where used. Use `__FILE__` for this 34292f119d6SBarry Smith - result - original memory 3433221ece2SMatthew G. Knepley 3443221ece2SMatthew G. Knepley Output Parameter: 345*0ed210f4SBarry Smith . result - double aligned pointer to requested storage 3463221ece2SMatthew G. Knepley 3473221ece2SMatthew G. Knepley Level: developer 3483221ece2SMatthew G. Knepley 349db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()` 3503221ece2SMatthew G. Knepley */ 351d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) 352d71ae5a4SJacob Faibussowitsch { 3533221ece2SMatthew G. Knepley char *a = (char *)*result; 3543221ece2SMatthew G. Knepley TRSPACE *head; 3553221ece2SMatthew G. Knepley char *ahead, *inew; 3563221ece2SMatthew G. Knepley PetscClassId *nend; 3573221ece2SMatthew G. Knepley size_t nsize; 3583221ece2SMatthew G. Knepley 3593221ece2SMatthew G. Knepley PetscFunctionBegin; 36092f119d6SBarry Smith /* Realloc requests zero space so just free the current space */ 361c22f1541SToby Isaac if (!len) { 3629566063dSJacob Faibussowitsch PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 363c22f1541SToby Isaac *result = NULL; 3643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 365c22f1541SToby Isaac } 366da81f932SPierre Jolivet /* If the original space was NULL just use the regular malloc() */ 367f590eff4SLisandro Dalcin if (!*result) { 3689566063dSJacob Faibussowitsch PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 3693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 370f590eff4SLisandro Dalcin } 3713221ece2SMatthew G. Knepley 37211cc89d2SBarry Smith PetscCall(PetscMallocValidate(lineno, function, filename)); 3733221ece2SMatthew G. Knepley 3743221ece2SMatthew G. Knepley ahead = a; 3753221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3763221ece2SMatthew G. Knepley head = (TRSPACE *)a; 3773221ece2SMatthew G. Knepley inew = a; 3783221ece2SMatthew G. Knepley 3793221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 3803ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3813ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a)); 3823221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 3833221ece2SMatthew G. Knepley } 3843221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3853221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3863221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 3873ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3883ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE))); 3893221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 3903ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 3913221ece2SMatthew G. Knepley } else { 3923ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno)); 3933221ece2SMatthew G. Knepley } 3943221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 3953221ece2SMatthew G. Knepley } else { 3963221ece2SMatthew G. Knepley /* Damaged tail */ 3973ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 3983ba16761SJacob 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)); 3993ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 4003221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 4013221ece2SMatthew G. Knepley } 4023221ece2SMatthew G. Knepley } 4033221ece2SMatthew G. Knepley 40492f119d6SBarry Smith /* remove original reference to the memory allocated from the PETSc debugging heap */ 405608c71bfSMatthew G. Knepley TRallocated -= TRrequestedSize ? head->rsize : head->size; 4063221ece2SMatthew G. Knepley TRfrags--; 4073221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 4083221ece2SMatthew G. Knepley else TRhead = head->next; 4093221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 4103221ece2SMatthew G. Knepley 4113221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 4129566063dSJacob Faibussowitsch PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 4133221ece2SMatthew G. Knepley 4143221ece2SMatthew G. Knepley head = (TRSPACE *)inew; 4153221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 4163221ece2SMatthew G. Knepley 4173221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 4183221ece2SMatthew G. Knepley head->next = TRhead; 4193221ece2SMatthew G. Knepley TRhead = head; 4203221ece2SMatthew G. Knepley head->prev = NULL; 4213221ece2SMatthew G. Knepley head->size = nsize; 422608c71bfSMatthew G. Knepley head->rsize = len; 423e269983cSBarry Smith head->id = TRid++; 4243221ece2SMatthew G. Knepley head->lineno = lineno; 4253221ece2SMatthew G. Knepley 4263221ece2SMatthew G. Knepley head->filename = filename; 4273221ece2SMatthew G. Knepley head->functionname = function; 4283221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4293221ece2SMatthew G. Knepley *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 4303221ece2SMatthew G. Knepley 431608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 4323221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 433e3ed9ee7SBarry Smith if (PetscLogMemory) { 434e3ed9ee7SBarry Smith PetscInt i; 435e3ed9ee7SBarry Smith for (i = 0; i < NumTRMaxMems; i++) { 436e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 437e3ed9ee7SBarry Smith } 438e3ed9ee7SBarry Smith } 4393221ece2SMatthew G. Knepley TRfrags++; 4403221ece2SMatthew G. Knepley 441dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 4429566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 4433221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 4443221ece2SMatthew G. Knepley head->stack.line[head->stack.currentsize - 2] = lineno; 4453221ece2SMatthew G. Knepley #endif 4463221ece2SMatthew G. Knepley 4473221ece2SMatthew G. Knepley /* 44892f119d6SBarry Smith Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 44992f119d6SBarry Smith and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 4503221ece2SMatthew G. Knepley */ 4513221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4523221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4533221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 45428b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4553221ece2SMatthew G. Knepley 4563221ece2SMatthew G. Knepley PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 45728b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4583221ece2SMatthew G. Knepley 4593221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 46028b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4613221ece2SMatthew G. Knepley } 4623221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4633221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4643221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4653221ece2SMatthew G. Knepley } 4663221ece2SMatthew G. Knepley *result = (void *)inew; 4673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4683221ece2SMatthew G. Knepley } 4693221ece2SMatthew G. Knepley 470fe7fb379SMatthew Knepley /*@C 47192f119d6SBarry Smith PetscMemoryView - Shows the amount of memory currently being used in a communicator. 472e5c89e4eSSatish Balay 473c3339decSBarry Smith Collective 474e5c89e4eSSatish Balay 475d8d19677SJose E. Roman Input Parameters: 476*0ed210f4SBarry Smith + viewer - the viewer to output the information on 477e5c89e4eSSatish Balay - message - string printed before values 478e5c89e4eSSatish Balay 479811af0c4SBarry Smith Options Database Keys: 48092f119d6SBarry Smith + -malloc_debug - have PETSc track how much memory it has allocated 481*0ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used 482*0ed210f4SBarry Smith - -memory_view - during `PetscFinalize()` have this routine called 4830841954dSBarry Smith 484e5c89e4eSSatish Balay Level: intermediate 485e5c89e4eSSatish Balay 486*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 487e5c89e4eSSatish Balay @*/ 488d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) 489d71ae5a4SJacob Faibussowitsch { 4900841954dSBarry Smith PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax; 4910841954dSBarry Smith PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax; 492e5c89e4eSSatish Balay MPI_Comm comm; 493e5c89e4eSSatish Balay 494e5c89e4eSSatish Balay PetscFunctionBegin; 495e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 4969566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&allocated)); 4979566063dSJacob Faibussowitsch PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 4989566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&resident)); 4999566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 500e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 5019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 5029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 503e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 5089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 5169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 520e5c89e4eSSatish Balay } else if (resident && residentmax) { 5219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 5259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 529e5c89e4eSSatish Balay } else if (resident && allocated) { 5309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 539e5c89e4eSSatish Balay } else if (allocated) { 5409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 5459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 546e5c89e4eSSatish Balay } else { 5479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 548e5c89e4eSSatish Balay } 5499566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 5503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 551e5c89e4eSSatish Balay } 552e5c89e4eSSatish Balay 55346eb3923SBarry Smith /*@ 554811af0c4SBarry Smith PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()` 555e5c89e4eSSatish Balay 556e5c89e4eSSatish Balay Not Collective 557e5c89e4eSSatish Balay 5582fe279fdSBarry Smith Output Parameter: 559e5c89e4eSSatish Balay . space - number of bytes currently allocated 560e5c89e4eSSatish Balay 561e5c89e4eSSatish Balay Level: intermediate 562e5c89e4eSSatish Balay 563*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 564db781477SPatrick Sanan `PetscMemoryGetMaximumUsage()` 565e5c89e4eSSatish Balay @*/ 566d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 567d71ae5a4SJacob Faibussowitsch { 568e5c89e4eSSatish Balay PetscFunctionBegin; 569e5c89e4eSSatish Balay *space = (PetscLogDouble)TRallocated; 5703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 571e5c89e4eSSatish Balay } 572e5c89e4eSSatish Balay 573dc37d89fSBarry Smith /*@ 574811af0c4SBarry Smith PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time 575811af0c4SBarry Smith during this run, the high water mark. 576e5c89e4eSSatish Balay 577e5c89e4eSSatish Balay Not Collective 578e5c89e4eSSatish Balay 5792fe279fdSBarry Smith Output Parameter: 580e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 581e5c89e4eSSatish Balay 582e5c89e4eSSatish Balay Level: intermediate 583e5c89e4eSSatish Balay 584*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 585db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 586e5c89e4eSSatish Balay @*/ 587d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 588d71ae5a4SJacob Faibussowitsch { 589e5c89e4eSSatish Balay PetscFunctionBegin; 590e5c89e4eSSatish Balay *space = (PetscLogDouble)TRMaxMem; 5913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 592e5c89e4eSSatish Balay } 593e5c89e4eSSatish Balay 594e3ed9ee7SBarry Smith /*@ 595e3ed9ee7SBarry Smith PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 596e3ed9ee7SBarry Smith 597e3ed9ee7SBarry Smith Not Collective 598e3ed9ee7SBarry Smith 599e3ed9ee7SBarry Smith Input Parameter: 600e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 601e3ed9ee7SBarry Smith 602e3ed9ee7SBarry Smith Level: developer 603e3ed9ee7SBarry Smith 604*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 605db781477SPatrick Sanan `PetscMallocPopMaximumUsage()` 606e3ed9ee7SBarry Smith @*/ 607d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event) 608d71ae5a4SJacob Faibussowitsch { 609e3ed9ee7SBarry Smith PetscFunctionBegin; 6103ba16761SJacob Faibussowitsch if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 611e3ed9ee7SBarry Smith TRMaxMems[NumTRMaxMems - 1] = TRallocated; 612e3ed9ee7SBarry Smith TRMaxMemsEvents[NumTRMaxMems - 1] = event; 6133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 614e3ed9ee7SBarry Smith } 615e3ed9ee7SBarry Smith 616e3ed9ee7SBarry Smith /*@ 617e3ed9ee7SBarry Smith PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 618e3ed9ee7SBarry Smith 619e3ed9ee7SBarry Smith Not Collective 620e3ed9ee7SBarry Smith 621e3ed9ee7SBarry Smith Input Parameter: 622e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 623e3ed9ee7SBarry Smith 624e3ed9ee7SBarry Smith Output Parameter: 625e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 626e3ed9ee7SBarry Smith 627e3ed9ee7SBarry Smith Level: developer 628e3ed9ee7SBarry Smith 629*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`, 630db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 631e3ed9ee7SBarry Smith @*/ 632d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) 633d71ae5a4SJacob Faibussowitsch { 634e3ed9ee7SBarry Smith PetscFunctionBegin; 635e3ed9ee7SBarry Smith *mu = 0; 6363ba16761SJacob Faibussowitsch if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS); 63708401ef6SPierre Jolivet PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 638e3ed9ee7SBarry Smith *mu = TRMaxMems[NumTRMaxMems]; 6393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 640e3ed9ee7SBarry Smith } 641e3ed9ee7SBarry Smith 642a64a8e02SBarry Smith /*@C 643811af0c4SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory 644a64a8e02SBarry Smith 645*0ed210f4SBarry Smith Not Collective 646a64a8e02SBarry Smith 647a64a8e02SBarry Smith Input Parameter: 648a64a8e02SBarry Smith . ptr - the memory location 649a64a8e02SBarry Smith 650fd292e60Sprj- Output Parameter: 651a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 652a64a8e02SBarry Smith 653a64a8e02SBarry Smith Level: intermediate 654a64a8e02SBarry Smith 655*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 656a64a8e02SBarry Smith @*/ 657d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) 658d71ae5a4SJacob Faibussowitsch { 659dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 660a64a8e02SBarry Smith TRSPACE *head; 661a64a8e02SBarry Smith 662a64a8e02SBarry Smith PetscFunctionBegin; 663a64a8e02SBarry Smith head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 664a64a8e02SBarry Smith *stack = &head->stack; 6653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66676386721SLisandro Dalcin #else 667f0ba7cfcSLisandro Dalcin *stack = NULL; 6683ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 669a64a8e02SBarry Smith #endif 670dfb7d7afSStefano Zampini } 671a64a8e02SBarry Smith 672e5c89e4eSSatish Balay /*@C 67392f119d6SBarry Smith PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 674e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 675e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 676e5c89e4eSSatish Balay allocated. 677e5c89e4eSSatish Balay 67892f119d6SBarry Smith Not Collective 679e5c89e4eSSatish Balay 680e5c89e4eSSatish Balay Input Parameter: 681*0ed210f4SBarry Smith . fp - file pointer. If `fp` is `NULL`, `stdout` is assumed. 682e5c89e4eSSatish Balay 683e5c89e4eSSatish Balay Options Database Key: 684*0ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given 685e5c89e4eSSatish Balay 686e5c89e4eSSatish Balay Level: intermediate 687e5c89e4eSSatish Balay 68895452b02SPatrick Sanan Notes: 689811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed. 690e5c89e4eSSatish Balay 691811af0c4SBarry Smith When called in `PetscFinalize()` dumps only the allocations that have not been properly freed 69292f119d6SBarry Smith 693811af0c4SBarry Smith `PetscMallocView()` prints a list of all memory ever allocated 69492f119d6SBarry Smith 695*0ed210f4SBarry Smith Fortran Note: 696*0ed210f4SBarry Smith The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported. 69720f4b53cSBarry Smith 698*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 699e5c89e4eSSatish Balay @*/ 700d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp) 701d71ae5a4SJacob Faibussowitsch { 702e5c89e4eSSatish Balay TRSPACE *head; 703e3ed9ee7SBarry Smith size_t libAlloc = 0; 704e5c89e4eSSatish Balay PetscMPIInt rank; 705e5c89e4eSSatish Balay 706e5c89e4eSSatish Balay PetscFunctionBegin; 7079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 708da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 709e5c89e4eSSatish Balay head = TRhead; 710e5c89e4eSSatish Balay while (head) { 711608c71bfSMatthew G. Knepley libAlloc += TRrequestedSize ? head->rsize : head->size; 7125486ca60SMatthew G. Knepley head = head->next; 7135486ca60SMatthew G. Knepley } 7145486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 7155486ca60SMatthew G. Knepley head = TRhead; 7165486ca60SMatthew G. Knepley while (head) { 7175486ca60SMatthew G. Knepley PetscBool isLib; 7185486ca60SMatthew G. Knepley 7199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 7205486ca60SMatthew G. Knepley if (!isLib) { 721ccd65f63SJunchao Zhang fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 722dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 7239566063dSJacob Faibussowitsch PetscCall(PetscStackPrint(&head->stack, fp)); 724e5c89e4eSSatish Balay #endif 7255486ca60SMatthew G. Knepley } 726e5c89e4eSSatish Balay head = head->next; 727e5c89e4eSSatish Balay } 7283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 729e5c89e4eSSatish Balay } 730e5c89e4eSSatish Balay 731dc37d89fSBarry Smith /*@ 732811af0c4SBarry Smith PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view 733574034a9SJed Brown 734574034a9SJed Brown Not Collective 735574034a9SJed Brown 7364165533cSJose E. Roman Input Parameter: 737*0ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations 738574034a9SJed Brown 739*0ed210f4SBarry Smith Options Database Keys: 740811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 7418b254c29SBarry Smith . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used 7428b254c29SBarry Smith - -log_view_memory - view the memory usage also with the -log_view option 743574034a9SJed Brown 744574034a9SJed Brown Level: advanced 745574034a9SJed Brown 746*0ed210f4SBarry Smith Note: 747811af0c4SBarry Smith Must be called after `PetscMallocSetDebug()` 74892f119d6SBarry Smith 749*0ed210f4SBarry Smith Developer Note: 750811af0c4SBarry Smith Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available 75192f119d6SBarry Smith 752*0ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()` 753574034a9SJed Brown @*/ 754d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) 755d71ae5a4SJacob Faibussowitsch { 756574034a9SJed Brown PetscFunctionBegin; 75792f119d6SBarry Smith PetscLogMalloc = 0; 7589566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 759574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 760574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 7613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 762574034a9SJed Brown } 763574034a9SJed Brown 764dc37d89fSBarry Smith /*@ 765811af0c4SBarry Smith PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged 76618a2528dSJed Brown 76718a2528dSJed Brown Not Collective 76818a2528dSJed Brown 7694165533cSJose E. Roman Output Parameter 770811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 77118a2528dSJed Brown 77218a2528dSJed Brown Options Database Key: 773811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 77418a2528dSJed Brown 77518a2528dSJed Brown Level: advanced 77618a2528dSJed Brown 777*0ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()` 77818a2528dSJed Brown @*/ 779d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging) 780d71ae5a4SJacob Faibussowitsch { 78118a2528dSJed Brown PetscFunctionBegin; 78218a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 7833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78418a2528dSJed Brown } 78518a2528dSJed Brown 786608c71bfSMatthew G. Knepley /*@ 787811af0c4SBarry Smith PetscMallocTraceSet - Trace all calls to `PetscMalloc()` 788608c71bfSMatthew G. Knepley 789608c71bfSMatthew G. Knepley Not Collective 790608c71bfSMatthew G. Knepley 7914165533cSJose E. Roman Input Parameters: 792*0ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF` 793608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing 794608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged 795608c71bfSMatthew G. Knepley 796*0ed210f4SBarry Smith Level: advanced 797*0ed210f4SBarry Smith 798608c71bfSMatthew G. Knepley Note: 799608c71bfSMatthew G. Knepley The viewer should not be collective. 800608c71bfSMatthew G. Knepley 801*0ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 802608c71bfSMatthew G. Knepley @*/ 803d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) 804d71ae5a4SJacob Faibussowitsch { 805608c71bfSMatthew G. Knepley PetscFunctionBegin; 8069371c9d4SSatish Balay if (!active) { 8079371c9d4SSatish Balay PetscLogMallocTrace = -1; 8083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8099371c9d4SSatish Balay } 810*0ed210f4SBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 811*0ed210f4SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 812*0ed210f4SBarry Smith PetscLogMallocTraceViewer = viewer; 813608c71bfSMatthew G. Knepley PetscLogMallocTrace = 0; 8149566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 815608c71bfSMatthew G. Knepley if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 816608c71bfSMatthew G. Knepley PetscLogMallocTraceThreshold = (size_t)logmin; 8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 818608c71bfSMatthew G. Knepley } 819608c71bfSMatthew G. Knepley 820608c71bfSMatthew G. Knepley /*@ 821811af0c4SBarry Smith PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced 822608c71bfSMatthew G. Knepley 823608c71bfSMatthew G. Knepley Not Collective 824608c71bfSMatthew G. Knepley 8254165533cSJose E. Roman Output Parameter: 826811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active 827608c71bfSMatthew G. Knepley 828608c71bfSMatthew G. Knepley Options Database Key: 829*0ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` 830608c71bfSMatthew G. Knepley 831608c71bfSMatthew G. Knepley Level: advanced 832608c71bfSMatthew G. Knepley 833*0ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()` 834608c71bfSMatthew G. Knepley @*/ 835d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging) 836d71ae5a4SJacob Faibussowitsch { 837608c71bfSMatthew G. Knepley PetscFunctionBegin; 838608c71bfSMatthew G. Knepley *logging = (PetscBool)(PetscLogMallocTrace >= 0); 8393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 840608c71bfSMatthew G. Knepley } 841608c71bfSMatthew G. Knepley 842e5c89e4eSSatish Balay /*@C 843811af0c4SBarry Smith PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls 844811af0c4SBarry Smith `PetscMemoryGetMaximumUsage()` 845e5c89e4eSSatish Balay 84692f119d6SBarry Smith Not Collective 847e5c89e4eSSatish Balay 848e5c89e4eSSatish Balay Input Parameter: 849*0ed210f4SBarry 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: 862*0ed210f4SBarry Smith The calling sequence in Fortran is `PetscMallocView`(integer ierr) 86320f4b53cSBarry Smith 864*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()` 865e5c89e4eSSatish Balay @*/ 866d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp) 867d71ae5a4SJacob Faibussowitsch { 86892f119d6SBarry Smith PetscInt i, j, 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"); 89697b9d747SJed Brown for (i = 0, n = 0; i < PetscLogMalloc; i++) { 897e5c89e4eSSatish Balay for (j = 0; j < n; j++) { 8989566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 899e5c89e4eSSatish Balay if (match) { 900e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 90159ffdab8SBarry Smith shortcount[j]++; 902e5c89e4eSSatish Balay goto foundit; 903e5c89e4eSSatish Balay } 904e5c89e4eSSatish Balay } 905e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 906e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 90759ffdab8SBarry Smith shortcount[n] = 1; 908e5c89e4eSSatish Balay n++; 909e5c89e4eSSatish Balay foundit:; 910e5c89e4eSSatish Balay } 911e5c89e4eSSatish Balay 9129371c9d4SSatish Balay perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 9139371c9d4SSatish Balay PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 914e5c89e4eSSatish Balay for (i = 0; i < n; i++) perm[i] = i; 9159566063dSJacob Faibussowitsch PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 916e5c89e4eSSatish Balay 91792f119d6SBarry Smith (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 918ad540459SPierre Jolivet for (i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]); 919e5c89e4eSSatish Balay free(perm); 920e5c89e4eSSatish Balay free(shortlength); 92159ffdab8SBarry Smith free(shortcount); 922e5c89e4eSSatish Balay free((char **)shortfunction); 923b13f2904SStefano Zampini } 924c69effb2SJacob Faibussowitsch PetscCall(PetscFFlush(fp)); 9253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 926e5c89e4eSSatish Balay } 927e5c89e4eSSatish Balay 928dc37d89fSBarry Smith /*@ 92992f119d6SBarry Smith PetscMallocSetDebug - Set's PETSc memory debugging 930e5c89e4eSSatish Balay 931e5c89e4eSSatish Balay Not Collective 932e5c89e4eSSatish Balay 933d8d19677SJose E. Roman Input Parameters: 934811af0c4SBarry Smith + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow 935*0ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays 936e5c89e4eSSatish Balay 937811af0c4SBarry Smith Options Database Keys: 93879dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging 939*0ed210f4SBarry Smith . -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored 94079dccf82SBarry Smith . -malloc_view_threshold t - log only allocations larger than t 94192f119d6SBarry Smith . -malloc_dump <filename> - print a list of all memory that has not been freed 942*0ed210f4SBarry Smith . -malloc no - (deprecated) same as `-malloc_debug no` 943*0ed210f4SBarry Smith - -malloc_log - (deprecated) same as `-malloc_view` 944e5c89e4eSSatish Balay 94592f119d6SBarry Smith Level: developer 94692f119d6SBarry Smith 947811af0c4SBarry Smith Note: 948811af0c4SBarry Smith This is called in `PetscInitialize()` and should not be called elsewhere 94992f119d6SBarry Smith 950*0ed210f4SBarry Smith .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()` 951e5c89e4eSSatish Balay @*/ 952d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) 953d71ae5a4SJacob Faibussowitsch { 954e5c89e4eSSatish Balay PetscFunctionBegin; 95508401ef6SPierre 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()"); 9569566063dSJacob Faibussowitsch PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 95792f119d6SBarry Smith 95892f119d6SBarry Smith TRallocated = 0; 95992f119d6SBarry Smith TRfrags = 0; 96092f119d6SBarry Smith TRhead = NULL; 96192f119d6SBarry Smith TRid = 0; 96292f119d6SBarry Smith TRdebugLevel = eachcall; 96392f119d6SBarry Smith TRMaxMem = 0; 96492f119d6SBarry Smith PetscLogMallocMax = 10000; 96592f119d6SBarry Smith PetscLogMalloc = -1; 9662d4ee042Sprj- TRdebugIinitializenan = initializenan; 9673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 968e5c89e4eSSatish Balay } 9690acecf5bSBarry Smith 970dc37d89fSBarry Smith /*@ 97192f119d6SBarry Smith PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 9720acecf5bSBarry Smith 9730acecf5bSBarry Smith Not Collective 9740acecf5bSBarry Smith 97592f119d6SBarry Smith Output Parameters: 97692f119d6SBarry Smith + basic - doing basic debugging 977811af0c4SBarry Smith . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()` 978*0ed210f4SBarry Smith - initializenan - initializes memory with `NaN` 9790acecf5bSBarry Smith 9800acecf5bSBarry Smith Level: intermediate 9810acecf5bSBarry Smith 982811af0c4SBarry Smith Note: 983*0ed210f4SBarry Smith By default, the debug version always does some debugging unless you run with `-malloc_debug no` 9840acecf5bSBarry Smith 985*0ed210f4SBarry Smith .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()` 9860acecf5bSBarry Smith @*/ 987d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) 988d71ae5a4SJacob Faibussowitsch { 9890acecf5bSBarry Smith PetscFunctionBegin; 99079dccf82SBarry Smith if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 99179dccf82SBarry Smith if (eachcall) *eachcall = TRdebugLevel; 9922d4ee042Sprj- if (initializenan) *initializenan = TRdebugIinitializenan; 9933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9940acecf5bSBarry Smith } 995608c71bfSMatthew G. Knepley 996608c71bfSMatthew G. Knepley /*@ 997608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 998608c71bfSMatthew G. Knepley 999608c71bfSMatthew G. Knepley Not Collective 1000608c71bfSMatthew G. Knepley 1001608c71bfSMatthew G. Knepley Input Parameter: 1002811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size 1003608c71bfSMatthew G. Knepley 1004811af0c4SBarry Smith Options Database Key: 1005608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag 1006608c71bfSMatthew G. Knepley 1007608c71bfSMatthew G. Knepley Level: developer 1008608c71bfSMatthew G. Knepley 1009*0ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1010608c71bfSMatthew G. Knepley @*/ 1011d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) 1012d71ae5a4SJacob Faibussowitsch { 1013608c71bfSMatthew G. Knepley PetscFunctionBegin; 1014608c71bfSMatthew G. Knepley TRrequestedSize = flg; 10153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1016608c71bfSMatthew G. Knepley } 1017608c71bfSMatthew G. Knepley 1018608c71bfSMatthew G. Knepley /*@ 1019608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1020608c71bfSMatthew G. Knepley 1021608c71bfSMatthew G. Knepley Not Collective 1022608c71bfSMatthew G. Knepley 1023608c71bfSMatthew G. Knepley Output Parameter: 1024811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size 1025608c71bfSMatthew G. Knepley 1026608c71bfSMatthew G. Knepley Level: developer 1027608c71bfSMatthew G. Knepley 1028*0ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()` 1029608c71bfSMatthew G. Knepley @*/ 1030d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) 1031d71ae5a4SJacob Faibussowitsch { 1032608c71bfSMatthew G. Knepley PetscFunctionBegin; 1033608c71bfSMatthew G. Knepley *flg = TRrequestedSize; 10343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1035608c71bfSMatthew G. Knepley } 1036