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[],const char[],void**); 17 extern PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[],const char[]); 18 extern PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],const char[],void**); 19 extern PetscErrorCode PetscTrFreeDefault(void*,int,const char[],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 const char *dirname; 32 PetscClassId classid; 33 #if defined(PETSC_USE_DEBUG) 34 PetscStack stack; 35 #endif 36 struct _trSPACE *next,*prev; 37 } TRSPACE; 38 39 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 40 It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN. 41 */ 42 43 #define HEADER_BYTES ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1)) 44 45 46 /* This union is used to insure that the block passed to the user retains 47 a minimum alignment of PETSC_MEMALIGN. 48 */ 49 typedef union { 50 TRSPACE sp; 51 char v[HEADER_BYTES]; 52 } TrSPACE; 53 54 55 static size_t TRallocated = 0; 56 static int TRfrags = 0; 57 static TRSPACE *TRhead = 0; 58 static int TRid = 0; 59 static PetscBool TRdebugLevel = PETSC_FALSE; 60 static size_t TRMaxMem = 0; 61 /* 62 Arrays to log information on all Mallocs 63 */ 64 static int PetscLogMallocMax = 10000,PetscLogMalloc = -1; 65 static size_t PetscLogMallocThreshold = 0; 66 static size_t *PetscLogMallocLength; 67 static const char **PetscLogMallocDirectory,**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 = 0; 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 - dir - directory where function is 100 101 Return value: 102 The number of errors detected. 103 104 Output Effect: 105 Error messages are written to stdout. 106 107 Level: advanced 108 109 Notes: 110 You should generally use CHKMEMQ as a short cut for calling this 111 routine. 112 113 The line, function, file and dir are given by the C preprocessor as 114 __LINE__, __FUNCT__, __FILE__, and __DIR__ 115 116 The Fortran calling sequence is simply PetscMallocValidate(ierr) 117 118 No output is generated if there are no problems detected. 119 120 .seealso: CHKMEMQ 121 122 @*/ 123 PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[],const char dir[]) 124 { 125 TRSPACE *head,*lasthead; 126 char *a; 127 PetscClassId *nend; 128 129 PetscFunctionBegin; 130 head = TRhead; lasthead = NULL; 131 while (head) { 132 if (head->classid != CLASSID_VALUE) { 133 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s%s\n",function,line,dir,file); 134 (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head); 135 (*PetscErrorPrintf)("Probably write past beginning or end of array\n"); 136 if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s%s\n",lasthead->functionname,lasthead->lineno,lasthead->dirname,lasthead->filename); 137 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 138 } 139 a = (char*)(((TrSPACE*)head) + 1); 140 nend = (PetscClassId*)(a + head->size); 141 if (*nend != CLASSID_VALUE) { 142 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s%s\n",function,line,dir,file); 143 if (*nend == ALREADY_FREED) { 144 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a); 145 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 146 } else { 147 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 148 (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 149 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 150 } 151 } 152 lasthead = head; 153 head = head->next; 154 } 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "PetscTrMallocDefault" 160 /* 161 PetscTrMallocDefault - Malloc with tracing. 162 163 Input Parameters: 164 + a - number of bytes to allocate 165 . lineno - line number where used. Use __LINE__ for this 166 . function - function calling routine. Use __FUNCT__ for this 167 . filename - file name where used. Use __FILE__ for this 168 - dir - directory where file is. Use __SDIR__ for this 169 170 Returns: 171 double aligned pointer to requested storage, or null if not 172 available. 173 */ 174 PetscErrorCode PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],const char dir[],void **result) 175 { 176 TRSPACE *head; 177 char *inew; 178 size_t nsize; 179 PetscErrorCode ierr; 180 181 PetscFunctionBegin; 182 if (!a) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to malloc zero size array"); 183 184 if (TRdebugLevel) { 185 ierr = PetscMallocValidate(lineno,function,filename,dir); if (ierr) PetscFunctionReturn(ierr); 186 } 187 188 nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 189 ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,dir,(void**)&inew);CHKERRQ(ierr); 190 191 head = (TRSPACE*)inew; 192 inew += sizeof(TrSPACE); 193 194 if (TRhead) TRhead->prev = head; 195 head->next = TRhead; 196 TRhead = head; 197 head->prev = 0; 198 head->size = nsize; 199 head->id = TRid; 200 head->lineno = lineno; 201 202 head->filename = filename; 203 head->functionname = function; 204 head->dirname = dir; 205 head->classid = CLASSID_VALUE; 206 *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 207 208 TRallocated += nsize; 209 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 210 TRfrags++; 211 212 #if defined(PETSC_USE_DEBUG) 213 ierr = PetscStackCopy((PetscStack*)PetscThreadLocalGetValue(petscstack),&head->stack);CHKERRQ(ierr); 214 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 215 head->stack.line[head->stack.currentsize-2] = lineno; 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 PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 227 if (!PetscLogMallocDirectory) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 228 229 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 230 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 231 232 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 233 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 234 } 235 PetscLogMallocLength[PetscLogMalloc] = nsize; 236 PetscLogMallocDirectory[PetscLogMalloc] = dir; 237 PetscLogMallocFile[PetscLogMalloc] = filename; 238 PetscLogMallocFunction[PetscLogMalloc++] = function; 239 } 240 *result = (void*)inew; 241 PetscFunctionReturn(0); 242 } 243 244 245 #undef __FUNCT__ 246 #define __FUNCT__ "PetscTrFreeDefault" 247 /* 248 PetscTrFreeDefault - Free with tracing. 249 250 Input Parameters: 251 . a - pointer to a block allocated with PetscTrMalloc 252 . lineno - line number where used. Use __LINE__ for this 253 . function - function calling routine. Use __FUNCT__ for this 254 . file - file name where used. Use __FILE__ for this 255 . dir - directory where file is. Use __SDIR__ for this 256 */ 257 PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[],const char dir[]) 258 { 259 char *a = (char*)aa; 260 TRSPACE *head; 261 char *ahead; 262 PetscErrorCode ierr; 263 PetscClassId *nend; 264 265 PetscFunctionBegin; 266 /* Do not try to handle empty blocks */ 267 if (!a) { 268 (*PetscErrorPrintf)("PetscTrFreeDefault called from %s() line %d in %s%s\n",function,line,dir,file); 269 SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to free null block: Free called from %s() line %d in %s%s\n",function,line,dir,file); 270 } 271 272 if (TRdebugLevel) { 273 ierr = PetscMallocValidate(line,function,file,dir);CHKERRQ(ierr); 274 } 275 276 ahead = a; 277 a = a - sizeof(TrSPACE); 278 head = (TRSPACE*)a; 279 280 if (head->classid != CLASSID_VALUE) { 281 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 282 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 283 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 284 } 285 nend = (PetscClassId*)(ahead + head->size); 286 if (*nend != CLASSID_VALUE) { 287 if (*nend == ALREADY_FREED) { 288 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 289 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 290 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 291 (*PetscErrorPrintf)("Block freed in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 292 } else { 293 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,-head->lineno,head->dirname,head->filename); 294 } 295 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 296 } else { 297 /* Damaged tail */ 298 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 299 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 300 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 301 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 302 } 303 } 304 /* Mark the location freed */ 305 *nend = ALREADY_FREED; 306 /* Save location where freed. If we suspect the line number, mark as allocated location */ 307 if (line > 0 && line < 50000) { 308 head->lineno = line; 309 head->filename = file; 310 head->functionname = function; 311 head->dirname = dir; 312 } else { 313 head->lineno = -head->lineno; 314 } 315 /* zero out memory - helps to find some reuse of already freed memory */ 316 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 317 318 TRallocated -= head->size; 319 TRfrags--; 320 if (head->prev) head->prev->next = head->next; 321 else TRhead = head->next; 322 323 if (head->next) head->next->prev = head->prev; 324 ierr = PetscFreeAlign(a,line,function,file,dir);CHKERRQ(ierr); 325 PetscFunctionReturn(0); 326 } 327 328 329 #undef __FUNCT__ 330 #define __FUNCT__ "PetscMemoryShowUsage" 331 /*@C 332 PetscMemoryShowUsage - Shows the amount of memory currently being used 333 in a communicator. 334 335 Collective on PetscViewer 336 337 Input Parameter: 338 + viewer - the viewer that defines the communicator 339 - message - string printed before values 340 341 Level: intermediate 342 343 Concepts: memory usage 344 345 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage() 346 @*/ 347 PetscErrorCode PetscMemoryShowUsage(PetscViewer viewer,const char message[]) 348 { 349 PetscLogDouble allocated,maximum,resident,residentmax; 350 PetscErrorCode ierr; 351 PetscMPIInt rank; 352 MPI_Comm comm; 353 354 PetscFunctionBegin; 355 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 356 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 357 ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr); 358 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 359 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 360 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 361 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 362 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 363 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 364 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 365 if (resident && residentmax && allocated) { 366 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); 367 } else if (resident && residentmax) { 368 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); 369 } else if (resident && allocated) { 370 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); 371 } else if (allocated) { 372 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); 373 } else { 374 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 375 } 376 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 377 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 378 PetscFunctionReturn(0); 379 } 380 381 #undef __FUNCT__ 382 #define __FUNCT__ "PetscMallocGetCurrentUsage" 383 /*@C 384 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 385 386 Not Collective 387 388 Output Parameters: 389 . space - number of bytes currently allocated 390 391 Level: intermediate 392 393 Concepts: memory usage 394 395 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 396 PetscMemoryGetMaximumUsage() 397 @*/ 398 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 399 { 400 PetscFunctionBegin; 401 *space = (PetscLogDouble) TRallocated; 402 PetscFunctionReturn(0); 403 } 404 405 #undef __FUNCT__ 406 #define __FUNCT__ "PetscMallocGetMaximumUsage" 407 /*@C 408 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 409 during this run. 410 411 Not Collective 412 413 Output Parameters: 414 . space - maximum number of bytes ever allocated at one time 415 416 Level: intermediate 417 418 Concepts: memory usage 419 420 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 421 PetscMemoryGetCurrentUsage() 422 @*/ 423 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 424 { 425 PetscFunctionBegin; 426 *space = (PetscLogDouble) TRMaxMem; 427 PetscFunctionReturn(0); 428 } 429 430 #if defined(PETSC_USE_DEBUG) 431 #undef __FUNCT__ 432 #define __FUNCT__ "PetscMallocGetStack" 433 /*@C 434 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 435 436 Collective on PETSC_COMM_WORLD 437 438 Input Parameter: 439 . ptr - the memory location 440 441 Output Paramter: 442 . stack - the stack indicating where the program allocated this memory 443 444 Level: intermediate 445 446 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 447 @*/ 448 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 449 { 450 TRSPACE *head; 451 452 PetscFunctionBegin; 453 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 454 *stack = &head->stack; 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%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,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