1 2 /* 3 Interface to malloc() and free(). This code allows for logging of memory usage and some error checking 4 */ 5 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6 #include <petscviewer.h> 7 #if defined(PETSC_HAVE_MALLOC_H) 8 #include <malloc.h> 9 #endif 10 11 /* 12 These are defined in mal.c and ensure that malloced space is PetscScalar aligned 13 */ 14 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **); 15 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]); 16 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **); 17 18 #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9) 19 #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c) 20 21 /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */ 22 typedef struct _trSPACE { 23 size_t size, rsize; /* Aligned size and requested size */ 24 int id; 25 int lineno; 26 const char *filename; 27 const char *functionname; 28 PetscClassId classid; 29 #if defined(PETSC_USE_DEBUG) 30 PetscStack stack; 31 #endif 32 struct _trSPACE *next, *prev; 33 } TRSPACE; 34 35 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 36 It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN. 37 */ 38 #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1)) 39 40 /* This union is used to insure that the block passed to the user retains 41 a minimum alignment of PETSC_MEMALIGN. 42 */ 43 typedef union 44 { 45 TRSPACE sp; 46 char v[HEADER_BYTES]; 47 } TrSPACE; 48 49 #define MAXTRMAXMEMS 50 50 static size_t TRallocated = 0; 51 static int TRfrags = 0; 52 static TRSPACE *TRhead = NULL; 53 static int TRid = 0; 54 static PetscBool TRdebugLevel = PETSC_FALSE; 55 static PetscBool TRdebugIinitializenan = PETSC_FALSE; 56 static PetscBool TRrequestedSize = PETSC_FALSE; 57 static size_t TRMaxMem = 0; 58 static int NumTRMaxMems = 0; 59 static size_t TRMaxMems[MAXTRMAXMEMS]; 60 static int TRMaxMemsEvents[MAXTRMAXMEMS]; 61 /* 62 Arrays to log information on mallocs for PetscMallocView() 63 */ 64 static int PetscLogMallocMax = 10000; 65 static int PetscLogMalloc = -1; 66 static size_t PetscLogMallocThreshold = 0; 67 static size_t *PetscLogMallocLength; 68 static const char **PetscLogMallocFile, **PetscLogMallocFunction; 69 static int PetscLogMallocTrace = -1; 70 static size_t PetscLogMallocTraceThreshold = 0; 71 static PetscViewer PetscLogMallocTraceViewer = NULL; 72 73 /*@C 74 PetscMallocValidate - Test the memory for corruption. This can be called at any time between `PetscInitialize()` and `PetscFinalize()` 75 76 Input Parameters: 77 + line - line number where call originated. 78 . function - name of function calling 79 - file - file where function is 80 81 Return value: 82 The number of errors detected. 83 84 Options Database Keys:. 85 + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0 86 - -malloc_debug - turns this feature on anytime 87 88 Output Effect: 89 Error messages are written to stdout. 90 91 Level: advanced 92 93 Notes: 94 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) 95 96 You should generally use `CHKMEMQ` as a short cut for calling this routine. 97 98 The Fortran calling sequence is simply `PetscMallocValidate(ierr)` 99 100 No output is generated if there are no problems detected. 101 102 Developers Note: 103 Uses the flg TRdebugLevel (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run 104 105 .seealso: `CHKMEMQ` 106 @*/ 107 PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) { 108 TRSPACE *head, *lasthead; 109 char *a; 110 PetscClassId *nend; 111 112 if (!TRdebugLevel) return 0; 113 head = TRhead; 114 lasthead = NULL; 115 if (head && head->prev) { 116 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 117 (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev); 118 return PETSC_ERR_MEMC; 119 } 120 while (head) { 121 if (head->classid != CLASSID_VALUE) { 122 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 123 (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head); 124 (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"); 125 if (lasthead) { 126 a = (char *)(((TrSPACE *)head) + 1); 127 (*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); 128 } 129 abort(); 130 return PETSC_ERR_MEMC; 131 } 132 a = (char *)(((TrSPACE *)head) + 1); 133 nend = (PetscClassId *)(a + head->size); 134 if (*nend != CLASSID_VALUE) { 135 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 136 if (*nend == ALREADY_FREED) { 137 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a); 138 return PETSC_ERR_MEMC; 139 } else { 140 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 141 (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 142 return PETSC_ERR_MEMC; 143 } 144 } 145 if (head->prev && head->prev != lasthead) { 146 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 147 (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead); 148 (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno); 149 (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 150 return PETSC_ERR_MEMC; 151 } 152 lasthead = head; 153 head = head->next; 154 } 155 return 0; 156 } 157 158 /* 159 PetscTrMallocDefault - Malloc with tracing. 160 161 Input Parameters: 162 + a - number of bytes to allocate 163 . lineno - line number where used. Use __LINE__ for this 164 - filename - file name where used. Use __FILE__ for this 165 166 Returns: 167 double aligned pointer to requested storage, or null if not available. 168 */ 169 PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) { 170 TRSPACE *head; 171 char *inew; 172 size_t nsize; 173 174 PetscFunctionBegin; 175 /* Do not try to handle empty blocks */ 176 if (!a) { 177 *result = NULL; 178 PetscFunctionReturn(0); 179 } 180 181 PetscCall(PetscMallocValidate(lineno, function, filename)); 182 183 nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 184 PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew)); 185 186 head = (TRSPACE *)inew; 187 inew += sizeof(TrSPACE); 188 189 if (TRhead) TRhead->prev = head; 190 head->next = TRhead; 191 TRhead = head; 192 head->prev = NULL; 193 head->size = nsize; 194 head->rsize = a; 195 head->id = TRid++; 196 head->lineno = lineno; 197 198 head->filename = filename; 199 head->functionname = function; 200 head->classid = CLASSID_VALUE; 201 *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 202 203 TRallocated += TRrequestedSize ? head->rsize : head->size; 204 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 205 if (PetscLogMemory) { 206 PetscInt i; 207 for (i = 0; i < NumTRMaxMems; i++) { 208 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 209 } 210 } 211 TRfrags++; 212 213 #if defined(PETSC_USE_DEBUG) 214 PetscCall(PetscStackCopy(&petscstack, &head->stack)); 215 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 216 head->stack.line[head->stack.currentsize - 2] = lineno; 217 #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE) 218 if (!clear && TRdebugIinitializenan) { 219 size_t i, n = a / sizeof(PetscReal); 220 PetscReal *s = (PetscReal *)inew; 221 /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */ 222 #if defined(PETSC_USE_REAL_SINGLE) 223 int nas = 0x7F800002; 224 #else 225 PetscInt64 nas = 0x7FF0000000000002; 226 #endif 227 for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal)); 228 } 229 #endif 230 #endif 231 232 /* 233 Allow logging of all mallocs made. 234 TODO: Currently this memory is never freed, it should be freed during PetscFinalize() 235 */ 236 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 237 if (!PetscLogMalloc) { 238 PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 239 PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 240 241 PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 242 PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 243 244 PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 245 PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 246 } 247 PetscLogMallocLength[PetscLogMalloc] = nsize; 248 PetscLogMallocFile[PetscLogMalloc] = filename; 249 PetscLogMallocFunction[PetscLogMalloc++] = function; 250 } 251 if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); 252 *result = (void *)inew; 253 PetscFunctionReturn(0); 254 } 255 256 /* 257 PetscTrFreeDefault - Free with tracing. 258 259 Input Parameters: 260 . a - pointer to a block allocated with PetscTrMalloc 261 . lineno - line number where used. Use __LINE__ for this 262 . filename - file name where used. Use __FILE__ for this 263 */ 264 PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) { 265 char *a = (char *)aa; 266 TRSPACE *head; 267 char *ahead; 268 size_t asize; 269 PetscClassId *nend; 270 271 PetscFunctionBegin; 272 /* Do not try to handle empty blocks */ 273 if (!a) PetscFunctionReturn(0); 274 275 PetscCall(PetscMallocValidate(lineno, function, filename)); 276 277 ahead = a; 278 a = a - sizeof(TrSPACE); 279 head = (TRSPACE *)a; 280 281 if (head->classid != CLASSID_VALUE) { 282 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 283 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a); 284 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 285 } 286 nend = (PetscClassId *)(ahead + head->size); 287 if (*nend != CLASSID_VALUE) { 288 if (*nend == ALREADY_FREED) { 289 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 290 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)); 291 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 292 (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 293 } else { 294 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 295 } 296 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 297 } else { 298 /* Damaged tail */ 299 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 300 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 301 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 302 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 303 } 304 } 305 if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 306 PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 307 } 308 /* Mark the location freed */ 309 *nend = ALREADY_FREED; 310 /* Save location where freed. If we suspect the line number, mark as allocated location */ 311 if (lineno > 0 && lineno < 50000) { 312 head->lineno = lineno; 313 head->filename = filename; 314 head->functionname = function; 315 } else { 316 head->lineno = -head->lineno; 317 } 318 asize = TRrequestedSize ? head->rsize : head->size; 319 PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 320 TRallocated -= asize; 321 TRfrags--; 322 if (head->prev) head->prev->next = head->next; 323 else TRhead = head->next; 324 325 if (head->next) head->next->prev = head->prev; 326 PetscCall(PetscFreeAlign(a, lineno, function, filename)); 327 PetscFunctionReturn(0); 328 } 329 330 /* 331 PetscTrReallocDefault - Realloc with tracing. 332 333 Input Parameters: 334 + len - number of bytes to allocate 335 . lineno - line number where used. Use __LINE__ for this 336 . filename - file name where used. Use __FILE__ for this 337 - result - original memory 338 339 Output Parameter: 340 . result - double aligned pointer to requested storage, or null if not available. 341 342 Level: developer 343 344 .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()` 345 */ 346 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) { 347 char *a = (char *)*result; 348 TRSPACE *head; 349 char *ahead, *inew; 350 PetscClassId *nend; 351 size_t nsize; 352 353 PetscFunctionBegin; 354 /* Realloc requests zero space so just free the current space */ 355 if (!len) { 356 PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 357 *result = NULL; 358 PetscFunctionReturn(0); 359 } 360 /* If the orginal space was NULL just use the regular malloc() */ 361 if (!*result) { 362 PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 363 PetscFunctionReturn(0); 364 } 365 366 PetscCall(PetscMallocValidate(lineno, function, filename)); 367 368 ahead = a; 369 a = a - sizeof(TrSPACE); 370 head = (TRSPACE *)a; 371 inew = a; 372 373 if (head->classid != CLASSID_VALUE) { 374 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 375 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a); 376 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 377 } 378 nend = (PetscClassId *)(ahead + head->size); 379 if (*nend != CLASSID_VALUE) { 380 if (*nend == ALREADY_FREED) { 381 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 382 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)); 383 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 384 (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 385 } else { 386 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 387 } 388 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 389 } else { 390 /* Damaged tail */ 391 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 392 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 393 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 394 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 395 } 396 } 397 398 /* remove original reference to the memory allocated from the PETSc debugging heap */ 399 TRallocated -= TRrequestedSize ? head->rsize : head->size; 400 TRfrags--; 401 if (head->prev) head->prev->next = head->next; 402 else TRhead = head->next; 403 if (head->next) head->next->prev = head->prev; 404 405 nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 406 PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 407 408 head = (TRSPACE *)inew; 409 inew += sizeof(TrSPACE); 410 411 if (TRhead) TRhead->prev = head; 412 head->next = TRhead; 413 TRhead = head; 414 head->prev = NULL; 415 head->size = nsize; 416 head->rsize = len; 417 head->id = TRid++; 418 head->lineno = lineno; 419 420 head->filename = filename; 421 head->functionname = function; 422 head->classid = CLASSID_VALUE; 423 *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 424 425 TRallocated += TRrequestedSize ? head->rsize : head->size; 426 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 427 if (PetscLogMemory) { 428 PetscInt i; 429 for (i = 0; i < NumTRMaxMems; i++) { 430 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 431 } 432 } 433 TRfrags++; 434 435 #if defined(PETSC_USE_DEBUG) 436 PetscCall(PetscStackCopy(&petscstack, &head->stack)); 437 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 438 head->stack.line[head->stack.currentsize - 2] = lineno; 439 #endif 440 441 /* 442 Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 443 and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 444 */ 445 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 446 if (!PetscLogMalloc) { 447 PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 448 PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 449 450 PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 451 PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 452 453 PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 454 PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 455 } 456 PetscLogMallocLength[PetscLogMalloc] = nsize; 457 PetscLogMallocFile[PetscLogMalloc] = filename; 458 PetscLogMallocFunction[PetscLogMalloc++] = function; 459 } 460 *result = (void *)inew; 461 PetscFunctionReturn(0); 462 } 463 464 /*@C 465 PetscMemoryView - Shows the amount of memory currently being used in a communicator. 466 467 Collective on viewer 468 469 Input Parameters: 470 + viewer - the viewer that defines the communicator 471 - message - string printed before values 472 473 Options Database Keys: 474 + -malloc_debug - have PETSc track how much memory it has allocated 475 . -log_view_memory - print memory usage per event 476 - -memory_view - during PetscFinalize() have this routine called 477 478 Level: intermediate 479 480 .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()` 481 @*/ 482 PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) { 483 PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax; 484 PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax; 485 MPI_Comm comm; 486 487 PetscFunctionBegin; 488 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 489 PetscCall(PetscMallocGetCurrentUsage(&allocated)); 490 PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 491 PetscCall(PetscMemoryGetCurrentUsage(&resident)); 492 PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 493 if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 494 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 495 PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 496 if (resident && residentmax && allocated) { 497 PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 498 PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 499 PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 500 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 501 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 502 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 503 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 504 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 505 PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 506 PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 507 PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 508 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 509 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 510 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 511 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 512 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 513 } else if (resident && residentmax) { 514 PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 515 PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 516 PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 517 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 518 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 519 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 520 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 521 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 522 } else if (resident && allocated) { 523 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 524 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 525 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 526 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 527 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 528 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 529 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 530 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 531 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 532 } else if (allocated) { 533 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 534 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 535 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 536 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 537 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 538 PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 539 } else { 540 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 541 } 542 PetscCall(PetscViewerFlush(viewer)); 543 PetscFunctionReturn(0); 544 } 545 546 /*@ 547 PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()` 548 549 Not Collective 550 551 Output Parameters: 552 . space - number of bytes currently allocated 553 554 Level: intermediate 555 556 .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 557 `PetscMemoryGetMaximumUsage()` 558 @*/ 559 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) { 560 PetscFunctionBegin; 561 *space = (PetscLogDouble)TRallocated; 562 PetscFunctionReturn(0); 563 } 564 565 /*@ 566 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time 567 during this run, the high water mark. 568 569 Not Collective 570 571 Output Parameters: 572 . space - maximum number of bytes ever allocated at one time 573 574 Level: intermediate 575 576 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 577 `PetscMallocPushMaximumUsage()` 578 @*/ 579 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) { 580 PetscFunctionBegin; 581 *space = (PetscLogDouble)TRMaxMem; 582 PetscFunctionReturn(0); 583 } 584 585 /*@ 586 PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 587 588 Not Collective 589 590 Input Parameter: 591 . event - an event id; this is just for error checking 592 593 Level: developer 594 595 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 596 `PetscMallocPopMaximumUsage()` 597 @*/ 598 PetscErrorCode PetscMallocPushMaximumUsage(int event) { 599 PetscFunctionBegin; 600 if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0); 601 TRMaxMems[NumTRMaxMems - 1] = TRallocated; 602 TRMaxMemsEvents[NumTRMaxMems - 1] = event; 603 PetscFunctionReturn(0); 604 } 605 606 /*@ 607 PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 608 609 Not Collective 610 611 Input Parameter: 612 . event - an event id; this is just for error checking 613 614 Output Parameter: 615 . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 616 617 Level: developer 618 619 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 620 `PetscMallocPushMaximumUsage()` 621 @*/ 622 PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) { 623 PetscFunctionBegin; 624 *mu = 0; 625 if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0); 626 PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 627 *mu = TRMaxMems[NumTRMaxMems]; 628 PetscFunctionReturn(0); 629 } 630 631 #if defined(PETSC_USE_DEBUG) 632 /*@C 633 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory 634 635 Collective on `PETSC_COMM_WORLD` 636 637 Input Parameter: 638 . ptr - the memory location 639 640 Output Parameter: 641 . stack - the stack indicating where the program allocated this memory 642 643 Level: intermediate 644 645 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()` 646 @*/ 647 PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) { 648 TRSPACE *head; 649 650 PetscFunctionBegin; 651 head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 652 *stack = &head->stack; 653 PetscFunctionReturn(0); 654 } 655 #else 656 PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) { 657 PetscFunctionBegin; 658 *stack = NULL; 659 PetscFunctionReturn(0); 660 } 661 #endif 662 663 /*@C 664 PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 665 printed is: size of space (in bytes), address of space, id of space, 666 file in which space was allocated, and line number at which it was 667 allocated. 668 669 Not Collective 670 671 Input Parameter: 672 . fp - file pointer. If fp is NULL, stdout is assumed. 673 674 Options Database Key: 675 . -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()` 676 677 Level: intermediate 678 679 Fortran Note: 680 The calling sequence in Fortran is PetscMallocDump(integer ierr) 681 The fp defaults to stdout. 682 683 Notes: 684 Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed. 685 686 When called in `PetscFinalize()` dumps only the allocations that have not been properly freed 687 688 `PetscMallocView()` prints a list of all memory ever allocated 689 690 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()` 691 @*/ 692 PetscErrorCode PetscMallocDump(FILE *fp) { 693 TRSPACE *head; 694 size_t libAlloc = 0; 695 PetscMPIInt rank; 696 697 PetscFunctionBegin; 698 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 699 if (!fp) fp = PETSC_STDOUT; 700 head = TRhead; 701 while (head) { 702 libAlloc += TRrequestedSize ? head->rsize : head->size; 703 head = head->next; 704 } 705 if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 706 head = TRhead; 707 while (head) { 708 PetscBool isLib; 709 710 PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 711 if (!isLib) { 712 fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 713 #if defined(PETSC_USE_DEBUG) 714 PetscCall(PetscStackPrint(&head->stack, fp)); 715 #endif 716 } 717 head = head->next; 718 } 719 PetscFunctionReturn(0); 720 } 721 722 /*@ 723 PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view 724 725 Not Collective 726 727 Input Parameter: 728 . logmin - minimum allocation size to log, or `PETSC_DEFAULT` 729 730 Options Database Key: 731 + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 732 . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used 733 - -log_view_memory - view the memory usage also with the -log_view option 734 735 Level: advanced 736 737 Notes: 738 Must be called after `PetscMallocSetDebug()` 739 740 Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available 741 742 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()` 743 @*/ 744 PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) { 745 PetscFunctionBegin; 746 PetscLogMalloc = 0; 747 PetscCall(PetscMemorySetGetMaximumUsage()); 748 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 749 PetscLogMallocThreshold = (size_t)logmin; 750 PetscFunctionReturn(0); 751 } 752 753 /*@ 754 PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged 755 756 Not Collective 757 758 Output Parameter 759 . logging - `PETSC_TRUE` if logging is active 760 761 Options Database Key: 762 . -malloc_view <optional filename> - Activates `PetscMallocView()` 763 764 Level: advanced 765 766 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()` 767 @*/ 768 PetscErrorCode PetscMallocViewGet(PetscBool *logging) { 769 PetscFunctionBegin; 770 *logging = (PetscBool)(PetscLogMalloc >= 0); 771 PetscFunctionReturn(0); 772 } 773 774 /*@ 775 PetscMallocTraceSet - Trace all calls to `PetscMalloc()` 776 777 Not Collective 778 779 Input Parameters: 780 + viewer - The viewer to use for tracing, or NULL to use stdout 781 . active - Flag to activate or deactivate tracing 782 - logmin - The smallest memory size that will be logged 783 784 Note: 785 The viewer should not be collective. 786 787 Level: advanced 788 789 .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 790 @*/ 791 PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) { 792 PetscFunctionBegin; 793 if (!active) { 794 PetscLogMallocTrace = -1; 795 PetscFunctionReturn(0); 796 } 797 PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer; 798 PetscLogMallocTrace = 0; 799 PetscCall(PetscMemorySetGetMaximumUsage()); 800 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 801 PetscLogMallocTraceThreshold = (size_t)logmin; 802 PetscFunctionReturn(0); 803 } 804 805 /*@ 806 PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced 807 808 Not Collective 809 810 Output Parameter: 811 . logging - `PETSC_TRUE` if logging is active 812 813 Options Database Key: 814 . -malloc_view <optional filename> - Activates PetscMallocView() 815 816 Level: advanced 817 818 .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 819 @*/ 820 PetscErrorCode PetscMallocTraceGet(PetscBool *logging) { 821 PetscFunctionBegin; 822 *logging = (PetscBool)(PetscLogMallocTrace >= 0); 823 PetscFunctionReturn(0); 824 } 825 826 /*@C 827 PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls 828 `PetscMemoryGetMaximumUsage()` 829 830 Not Collective 831 832 Input Parameter: 833 . fp - file pointer; or NULL 834 835 Options Database Key: 836 . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 837 838 Level: advanced 839 840 Fortran Note: 841 The calling sequence in Fortran is PetscMallocView(integer ierr) 842 The fp defaults to stdout. 843 844 Notes: 845 `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated 846 847 `PetscMemoryView()` gives a brief summary of current memory usage 848 849 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()` 850 @*/ 851 PetscErrorCode PetscMallocView(FILE *fp) { 852 PetscInt i, j, n, *perm; 853 size_t *shortlength; 854 int *shortcount, err; 855 PetscMPIInt rank; 856 PetscBool match; 857 const char **shortfunction; 858 PetscLogDouble rss; 859 860 PetscFunctionBegin; 861 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 862 err = fflush(fp); 863 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 864 865 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()"); 866 867 if (!fp) fp = PETSC_STDOUT; 868 PetscCall(PetscMemoryGetMaximumUsage(&rss)); 869 if (rss) { 870 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 871 } else { 872 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 873 } 874 shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 875 PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 876 shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 877 PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 878 shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 879 PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 880 for (i = 0, n = 0; i < PetscLogMalloc; i++) { 881 for (j = 0; j < n; j++) { 882 PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 883 if (match) { 884 shortlength[j] += PetscLogMallocLength[i]; 885 shortcount[j]++; 886 goto foundit; 887 } 888 } 889 shortfunction[n] = PetscLogMallocFunction[i]; 890 shortlength[n] = PetscLogMallocLength[i]; 891 shortcount[n] = 1; 892 n++; 893 foundit:; 894 } 895 896 perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 897 PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 898 for (i = 0; i < n; i++) perm[i] = i; 899 PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 900 901 (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 902 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]]); 903 free(perm); 904 free(shortlength); 905 free(shortcount); 906 free((char **)shortfunction); 907 err = fflush(fp); 908 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 909 PetscFunctionReturn(0); 910 } 911 912 /* ---------------------------------------------------------------------------- */ 913 914 /*@ 915 PetscMallocSetDebug - Set's PETSc memory debugging 916 917 Not Collective 918 919 Input Parameters: 920 + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow 921 - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays 922 923 Options Database Keys: 924 + -malloc_debug <true or false> - turns on or off debugging 925 . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored 926 . -malloc_view_threshold t - log only allocations larger than t 927 . -malloc_dump <filename> - print a list of all memory that has not been freed 928 . -malloc no - (deprecated) same as -malloc_debug no 929 - -malloc_log - (deprecated) same as -malloc_view 930 931 Level: developer 932 933 Note: 934 This is called in `PetscInitialize()` and should not be called elsewhere 935 936 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()` 937 @*/ 938 PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) { 939 PetscFunctionBegin; 940 PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()"); 941 PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 942 943 TRallocated = 0; 944 TRfrags = 0; 945 TRhead = NULL; 946 TRid = 0; 947 TRdebugLevel = eachcall; 948 TRMaxMem = 0; 949 PetscLogMallocMax = 10000; 950 PetscLogMalloc = -1; 951 TRdebugIinitializenan = initializenan; 952 PetscFunctionReturn(0); 953 } 954 955 /*@ 956 PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 957 958 Not Collective 959 960 Output Parameters: 961 + basic - doing basic debugging 962 . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()` 963 - initializenan - initializes memory with NaN 964 965 Level: intermediate 966 967 Note: 968 By default, the debug version always does some debugging unless you run with -malloc_debug no 969 970 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()` 971 @*/ 972 PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) { 973 PetscFunctionBegin; 974 if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 975 if (eachcall) *eachcall = TRdebugLevel; 976 if (initializenan) *initializenan = TRdebugIinitializenan; 977 PetscFunctionReturn(0); 978 } 979 980 /*@ 981 PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 982 983 Not Collective 984 985 Input Parameter: 986 . flg - `PETSC_TRUE` to log the requested memory size 987 988 Options Database Key: 989 . -malloc_requested_size <bool> - Sets this flag 990 991 Level: developer 992 993 .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()` 994 @*/ 995 PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) { 996 PetscFunctionBegin; 997 TRrequestedSize = flg; 998 PetscFunctionReturn(0); 999 } 1000 1001 /*@ 1002 PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1003 1004 Not Collective 1005 1006 Output Parameter: 1007 . flg - `PETSC_TRUE` if we log the requested memory size 1008 1009 Level: developer 1010 1011 .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()` 1012 @*/ 1013 PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) { 1014 PetscFunctionBegin; 1015 *flg = TRrequestedSize; 1016 PetscFunctionReturn(0); 1017 } 1018