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