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