1 2 /* 3 Interface to malloc() and free(). This code allows for 4 logging of memory usage and some error checking 5 */ 6 #include <petscsys.h> /*I "petscsys.h" I*/ 7 #include <petscviewer.h> 8 #if defined(PETSC_HAVE_MALLOC_H) 9 #include <malloc.h> 10 #endif 11 12 13 /* 14 These are defined in mal.c and ensure that malloced space is PetscScalar aligned 15 */ 16 extern PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**); 17 extern PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]); 18 extern PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**); 19 extern PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]); 20 21 22 #define CLASSID_VALUE ((PetscClassId) 0xf0e0d0c9) 23 #define ALREADY_FREED ((PetscClassId) 0x0f0e0d9c) 24 25 typedef struct _trSPACE { 26 size_t size; 27 int id; 28 int lineno; 29 const char *filename; 30 const char *functionname; 31 PetscClassId classid; 32 #if defined(PETSC_USE_DEBUG) 33 PetscStack stack; 34 #endif 35 struct _trSPACE *next,*prev; 36 } TRSPACE; 37 38 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 39 It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN. 40 */ 41 42 #define HEADER_BYTES ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1)) 43 44 45 /* This union is used to insure that the block passed to the user retains 46 a minimum alignment of PETSC_MEMALIGN. 47 */ 48 typedef union { 49 TRSPACE sp; 50 char v[HEADER_BYTES]; 51 } TrSPACE; 52 53 54 static size_t TRallocated = 0; 55 static int TRfrags = 0; 56 static TRSPACE *TRhead = NULL; 57 static int TRid = 0; 58 static PetscBool TRdebugLevel = PETSC_FALSE; 59 static size_t TRMaxMem = 0; 60 /* 61 Arrays to log information on all Mallocs 62 */ 63 static int PetscLogMallocMax = 10000; 64 static int PetscLogMalloc = -1; 65 static size_t PetscLogMallocThreshold = 0; 66 static size_t *PetscLogMallocLength; 67 static const char **PetscLogMallocFile,**PetscLogMallocFunction; 68 69 #undef __FUNCT__ 70 #define __FUNCT__ "PetscSetUseTrMalloc_Private" 71 PetscErrorCode PetscSetUseTrMalloc_Private(void) 72 { 73 PetscErrorCode ierr; 74 75 PetscFunctionBegin; 76 ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr); 77 78 TRallocated = 0; 79 TRfrags = 0; 80 TRhead = NULL; 81 TRid = 0; 82 TRdebugLevel = PETSC_FALSE; 83 TRMaxMem = 0; 84 PetscLogMallocMax = 10000; 85 PetscLogMalloc = -1; 86 PetscFunctionReturn(0); 87 } 88 89 #undef __FUNCT__ 90 #define __FUNCT__ "PetscMallocValidate" 91 /*@C 92 PetscMallocValidate - Test the memory for corruption. This can be used to 93 check for memory overwrites. 94 95 Input Parameter: 96 + line - line number where call originated. 97 . function - name of function calling 98 - file - file where function is 99 100 Return value: 101 The number of errors detected. 102 103 Output Effect: 104 Error messages are written to stdout. 105 106 Level: advanced 107 108 Notes: 109 You should generally use CHKMEMQ as a short cut for calling this 110 routine. 111 112 The line, function, file are given by the C preprocessor as 113 __LINE__, __FUNCT__, __FILE__ 114 115 The Fortran calling sequence is simply PetscMallocValidate(ierr) 116 117 No output is generated if there are no problems detected. 118 119 .seealso: CHKMEMQ 120 121 @*/ 122 PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[]) 123 { 124 TRSPACE *head,*lasthead; 125 char *a; 126 PetscClassId *nend; 127 128 PetscFunctionBegin; 129 head = TRhead; lasthead = NULL; 130 while (head) { 131 if (head->classid != CLASSID_VALUE) { 132 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 133 (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head); 134 (*PetscErrorPrintf)("Probably write past beginning or end of array\n"); 135 if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename); 136 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 137 } 138 a = (char*)(((TrSPACE*)head) + 1); 139 nend = (PetscClassId*)(a + head->size); 140 if (*nend != CLASSID_VALUE) { 141 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 142 if (*nend == ALREADY_FREED) { 143 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a); 144 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 145 } else { 146 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 147 (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 148 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 149 } 150 } 151 lasthead = head; 152 head = head->next; 153 } 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "PetscTrMallocDefault" 159 /* 160 PetscTrMallocDefault - Malloc with tracing. 161 162 Input Parameters: 163 + a - number of bytes to allocate 164 . lineno - line number where used. Use __LINE__ for this 165 . function - function calling routine. Use __FUNCT__ for this 166 - filename - file name where used. Use __FILE__ for this 167 168 Returns: 169 double aligned pointer to requested storage, or null if not 170 available. 171 */ 172 PetscErrorCode PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result) 173 { 174 TRSPACE *head; 175 char *inew; 176 size_t nsize; 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 /* Do not try to handle empty blocks */ 181 if (!a) { *result = NULL; PetscFunctionReturn(0); } 182 183 if (TRdebugLevel) { 184 ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr); 185 } 186 187 nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 188 ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 189 190 head = (TRSPACE*)inew; 191 inew += sizeof(TrSPACE); 192 193 if (TRhead) TRhead->prev = head; 194 head->next = TRhead; 195 TRhead = head; 196 head->prev = NULL; 197 head->size = nsize; 198 head->id = TRid; 199 head->lineno = lineno; 200 201 head->filename = filename; 202 head->functionname = function; 203 head->classid = CLASSID_VALUE; 204 *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 205 206 TRallocated += nsize; 207 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 208 TRfrags++; 209 210 #if defined(PETSC_USE_DEBUG) 211 if (PetscStackActive()) { 212 ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 213 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 214 head->stack.line[head->stack.currentsize-2] = lineno; 215 } 216 #endif 217 218 /* 219 Allow logging of all mallocs made 220 */ 221 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 222 if (!PetscLogMalloc) { 223 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 224 if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 225 226 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 227 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 228 229 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 230 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 231 } 232 PetscLogMallocLength[PetscLogMalloc] = nsize; 233 PetscLogMallocFile[PetscLogMalloc] = filename; 234 PetscLogMallocFunction[PetscLogMalloc++] = function; 235 } 236 *result = (void*)inew; 237 PetscFunctionReturn(0); 238 } 239 240 241 #undef __FUNCT__ 242 #define __FUNCT__ "PetscTrFreeDefault" 243 /* 244 PetscTrFreeDefault - Free with tracing. 245 246 Input Parameters: 247 . a - pointer to a block allocated with PetscTrMalloc 248 . lineno - line number where used. Use __LINE__ for this 249 . function - function calling routine. Use __FUNCT__ for this 250 . file - file name where used. Use __FILE__ for this 251 */ 252 PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[]) 253 { 254 char *a = (char*)aa; 255 TRSPACE *head; 256 char *ahead; 257 PetscErrorCode ierr; 258 PetscClassId *nend; 259 260 PetscFunctionBegin; 261 /* Do not try to handle empty blocks */ 262 if (!a) PetscFunctionReturn(0); 263 264 if (TRdebugLevel) { 265 ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr); 266 } 267 268 ahead = a; 269 a = a - sizeof(TrSPACE); 270 head = (TRSPACE*)a; 271 272 if (head->classid != CLASSID_VALUE) { 273 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 274 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 275 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 276 } 277 nend = (PetscClassId*)(ahead + head->size); 278 if (*nend != CLASSID_VALUE) { 279 if (*nend == ALREADY_FREED) { 280 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 281 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 282 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 283 (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 284 } else { 285 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 286 } 287 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 288 } else { 289 /* Damaged tail */ 290 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 291 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 292 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 293 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 294 } 295 } 296 /* Mark the location freed */ 297 *nend = ALREADY_FREED; 298 /* Save location where freed. If we suspect the line number, mark as allocated location */ 299 if (line > 0 && line < 50000) { 300 head->lineno = line; 301 head->filename = file; 302 head->functionname = function; 303 } else { 304 head->lineno = -head->lineno; 305 } 306 /* zero out memory - helps to find some reuse of already freed memory */ 307 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 308 309 TRallocated -= head->size; 310 TRfrags--; 311 if (head->prev) head->prev->next = head->next; 312 else TRhead = head->next; 313 314 if (head->next) head->next->prev = head->prev; 315 ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr); 316 PetscFunctionReturn(0); 317 } 318 319 320 #undef __FUNCT__ 321 #define __FUNCT__ "PetscMemoryShowUsage" 322 /*@C 323 PetscMemoryShowUsage - Shows the amount of memory currently being used 324 in a communicator. 325 326 Collective on PetscViewer 327 328 Input Parameter: 329 + viewer - the viewer that defines the communicator 330 - message - string printed before values 331 332 Level: intermediate 333 334 Concepts: memory usage 335 336 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage() 337 @*/ 338 PetscErrorCode PetscMemoryShowUsage(PetscViewer viewer,const char message[]) 339 { 340 PetscLogDouble allocated,maximum,resident,residentmax; 341 PetscErrorCode ierr; 342 PetscMPIInt rank; 343 MPI_Comm comm; 344 345 PetscFunctionBegin; 346 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 347 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 348 ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr); 349 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 350 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 351 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 352 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 353 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 354 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 355 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 356 if (resident && residentmax && allocated) { 357 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);CHKERRQ(ierr); 358 } else if (resident && residentmax) { 359 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);CHKERRQ(ierr); 360 } else if (resident && allocated) { 361 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);CHKERRQ(ierr); 362 } else if (allocated) { 363 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);CHKERRQ(ierr); 364 } else { 365 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 366 } 367 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 368 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 369 PetscFunctionReturn(0); 370 } 371 372 #undef __FUNCT__ 373 #define __FUNCT__ "PetscMallocGetCurrentUsage" 374 /*@C 375 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 376 377 Not Collective 378 379 Output Parameters: 380 . space - number of bytes currently allocated 381 382 Level: intermediate 383 384 Concepts: memory usage 385 386 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 387 PetscMemoryGetMaximumUsage() 388 @*/ 389 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 390 { 391 PetscFunctionBegin; 392 *space = (PetscLogDouble) TRallocated; 393 PetscFunctionReturn(0); 394 } 395 396 #undef __FUNCT__ 397 #define __FUNCT__ "PetscMallocGetMaximumUsage" 398 /*@C 399 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 400 during this run. 401 402 Not Collective 403 404 Output Parameters: 405 . space - maximum number of bytes ever allocated at one time 406 407 Level: intermediate 408 409 Concepts: memory usage 410 411 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 412 PetscMemoryGetCurrentUsage() 413 @*/ 414 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 415 { 416 PetscFunctionBegin; 417 *space = (PetscLogDouble) TRMaxMem; 418 PetscFunctionReturn(0); 419 } 420 421 #if defined(PETSC_USE_DEBUG) 422 #undef __FUNCT__ 423 #define __FUNCT__ "PetscMallocGetStack" 424 /*@C 425 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 426 427 Collective on PETSC_COMM_WORLD 428 429 Input Parameter: 430 . ptr - the memory location 431 432 Output Paramter: 433 . stack - the stack indicating where the program allocated this memory 434 435 Level: intermediate 436 437 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 438 @*/ 439 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 440 { 441 TRSPACE *head; 442 443 PetscFunctionBegin; 444 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 445 *stack = &head->stack; 446 PetscFunctionReturn(0); 447 } 448 #else 449 #undef __FUNCT__ 450 #define __FUNCT__ "PetscMallocGetStack" 451 PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 452 { 453 PetscFunctionBegin; 454 *stack = NULL; 455 PetscFunctionReturn(0); 456 } 457 #endif 458 459 #undef __FUNCT__ 460 #define __FUNCT__ "PetscMallocDump" 461 /*@C 462 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 463 printed is: size of space (in bytes), address of space, id of space, 464 file in which space was allocated, and line number at which it was 465 allocated. 466 467 Collective on PETSC_COMM_WORLD 468 469 Input Parameter: 470 . fp - file pointer. If fp is NULL, stdout is assumed. 471 472 Options Database Key: 473 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 474 475 Level: intermediate 476 477 Fortran Note: 478 The calling sequence in Fortran is PetscMallocDump(integer ierr) 479 The fp defaults to stdout. 480 481 Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 482 has been freed. 483 484 Concepts: memory usage 485 Concepts: memory bleeding 486 Concepts: bleeding memory 487 488 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 489 @*/ 490 PetscErrorCode PetscMallocDump(FILE *fp) 491 { 492 TRSPACE *head; 493 PetscErrorCode ierr; 494 PetscMPIInt rank; 495 496 PetscFunctionBegin; 497 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 498 if (!fp) fp = PETSC_STDOUT; 499 if (TRallocated > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 500 head = TRhead; 501 while (head) { 502 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 503 #if defined(PETSC_USE_DEBUG) 504 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 505 #endif 506 head = head->next; 507 } 508 PetscFunctionReturn(0); 509 } 510 511 /* ---------------------------------------------------------------------------- */ 512 513 #undef __FUNCT__ 514 #define __FUNCT__ "PetscMallocSetDumpLog" 515 /*@C 516 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 517 518 Not Collective 519 520 Options Database Key: 521 + -malloc_log <filename> - Activates PetscMallocDumpLog() 522 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 523 524 Level: advanced 525 526 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 527 @*/ 528 PetscErrorCode PetscMallocSetDumpLog(void) 529 { 530 PetscErrorCode ierr; 531 532 PetscFunctionBegin; 533 PetscLogMalloc = 0; 534 535 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 536 PetscFunctionReturn(0); 537 } 538 539 #undef __FUNCT__ 540 #define __FUNCT__ "PetscMallocSetDumpLogThreshold" 541 /*@C 542 PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 543 544 Not Collective 545 546 Input Arguments: 547 . logmin - minimum allocation size to log, or PETSC_DEFAULT 548 549 Options Database Key: 550 + -malloc_log <filename> - Activates PetscMallocDumpLog() 551 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 552 553 Level: advanced 554 555 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 556 @*/ 557 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 558 { 559 PetscErrorCode ierr; 560 561 PetscFunctionBegin; 562 ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 563 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 564 PetscLogMallocThreshold = (size_t)logmin; 565 PetscFunctionReturn(0); 566 } 567 568 #undef __FUNCT__ 569 #define __FUNCT__ "PetscMallocGetDumpLog" 570 /*@C 571 PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 572 573 Not Collective 574 575 Output Arguments 576 . logging - PETSC_TRUE if logging is active 577 578 Options Database Key: 579 . -malloc_log - Activates PetscMallocDumpLog() 580 581 Level: advanced 582 583 .seealso: PetscMallocDump(), PetscMallocDumpLog() 584 @*/ 585 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 586 { 587 588 PetscFunctionBegin; 589 *logging = (PetscBool)(PetscLogMalloc >= 0); 590 PetscFunctionReturn(0); 591 } 592 593 #undef __FUNCT__ 594 #define __FUNCT__ "PetscMallocDumpLog" 595 /*@C 596 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 597 PetscMemoryGetMaximumUsage() 598 599 Collective on PETSC_COMM_WORLD 600 601 Input Parameter: 602 . fp - file pointer; or NULL 603 604 Options Database Key: 605 . -malloc_log - Activates PetscMallocDumpLog() 606 607 Level: advanced 608 609 Fortran Note: 610 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 611 The fp defaults to stdout. 612 613 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 614 @*/ 615 PetscErrorCode PetscMallocDumpLog(FILE *fp) 616 { 617 PetscInt i,j,n,dummy,*perm; 618 size_t *shortlength; 619 int *shortcount,err; 620 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 621 PetscBool match; 622 const char **shortfunction; 623 PetscLogDouble rss; 624 MPI_Status status; 625 PetscErrorCode ierr; 626 627 PetscFunctionBegin; 628 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 629 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 630 /* 631 Try to get the data printed in order by processor. This will only sometimes work 632 */ 633 err = fflush(fp); 634 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 635 636 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 637 if (rank) { 638 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 639 } 640 641 if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 642 643 if (!fp) fp = PETSC_STDOUT; 644 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 645 if (rss) { 646 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr); 647 } else { 648 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr); 649 } 650 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 651 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 652 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 653 for (i=0,n=0; i<PetscLogMalloc; i++) { 654 for (j=0; j<n; j++) { 655 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 656 if (match) { 657 shortlength[j] += PetscLogMallocLength[i]; 658 shortcount[j]++; 659 goto foundit; 660 } 661 } 662 shortfunction[n] = PetscLogMallocFunction[i]; 663 shortlength[n] = PetscLogMallocLength[i]; 664 shortcount[n] = 1; 665 n++; 666 foundit:; 667 } 668 669 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 670 for (i=0; i<n; i++) perm[i] = i; 671 ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 672 673 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 674 for (i=0; i<n; i++) { 675 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 676 } 677 free(perm); 678 free(shortlength); 679 free(shortcount); 680 free((char**)shortfunction); 681 err = fflush(fp); 682 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 683 if (rank != size-1) { 684 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 685 } 686 PetscFunctionReturn(0); 687 } 688 689 /* ---------------------------------------------------------------------------- */ 690 691 #undef __FUNCT__ 692 #define __FUNCT__ "PetscMallocDebug" 693 /*@C 694 PetscMallocDebug - Turns on/off debugging for the memory management routines. 695 696 Not Collective 697 698 Input Parameter: 699 . level - PETSC_TRUE or PETSC_FALSE 700 701 Level: intermediate 702 703 .seealso: CHKMEMQ(), PetscMallocValidate() 704 @*/ 705 PetscErrorCode PetscMallocDebug(PetscBool level) 706 { 707 PetscFunctionBegin; 708 TRdebugLevel = level; 709 PetscFunctionReturn(0); 710 } 711 712 #undef __FUNCT__ 713 #define __FUNCT__ "PetscMallocGetDebug" 714 /*@C 715 PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 716 717 Not Collective 718 719 Output Parameter: 720 . flg - PETSC_TRUE if any debugger 721 722 Level: intermediate 723 724 Note that by default, the debug version always does some debugging unless you run with -malloc no 725 726 727 .seealso: CHKMEMQ(), PetscMallocValidate() 728 @*/ 729 PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 730 { 731 PetscFunctionBegin; 732 if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 733 else *flg = PETSC_FALSE; 734 PetscFunctionReturn(0); 735 } 736