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 TRallocated = 0; 80 TRfrags = 0; 81 TRhead = 0; 82 TRid = 0; 83 TRdebugLevel = PETSC_FALSE; 84 TRMaxMem = 0; 85 PetscLogMallocMax = 10000; 86 PetscLogMalloc = -1; 87 PetscFunctionReturn(0); 88 } 89 90 #undef __FUNCT__ 91 #define __FUNCT__ "PetscMallocValidate" 92 /*@C 93 PetscMallocValidate - Test the memory for corruption. This can be used to 94 check for memory overwrites. 95 96 Input Parameter: 97 + line - line number where call originated. 98 . function - name of function calling 99 . file - file where function is 100 - dir - directory where function is 101 102 Return value: 103 The number of errors detected. 104 105 Output Effect: 106 Error messages are written to stdout. 107 108 Level: advanced 109 110 Notes: 111 You should generally use CHKMEMQ as a short cut for calling this 112 routine. 113 114 The line, function, file and dir are given by the C preprocessor as 115 __LINE__, __FUNCT__, __FILE__, and __DIR__ 116 117 The Fortran calling sequence is simply PetscMallocValidate(ierr) 118 119 No output is generated if there are no problems detected. 120 121 .seealso: CHKMEMQ 122 123 @*/ 124 PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[],const char dir[]) 125 { 126 TRSPACE *head,*lasthead; 127 char *a; 128 PetscClassId *nend; 129 130 PetscFunctionBegin; 131 head = TRhead; lasthead = NULL; 132 while (head) { 133 if (head->classid != CLASSID_VALUE) { 134 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s%s\n",function,line,dir,file); 135 (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head); 136 (*PetscErrorPrintf)("Probably write past beginning or end of array\n"); 137 if (lasthead) 138 (*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) { 212 TRMaxMem = TRallocated; 213 } 214 TRfrags++; 215 216 #if defined(PETSC_USE_DEBUG) 217 ierr = PetscStackCopy((PetscStack*)PetscThreadLocalGetValue(petscstack),&head->stack);CHKERRQ(ierr); 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 PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char**)); 228 if (!PetscLogMallocDirectory) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 229 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char**)); 230 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 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) { 499 fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 500 } 501 head = TRhead; 502 while (head) { 503 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,head->filename); 504 #if defined(PETSC_USE_DEBUG) 505 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 506 #endif 507 head = head->next; 508 } 509 PetscFunctionReturn(0); 510 } 511 512 /* ---------------------------------------------------------------------------- */ 513 514 #undef __FUNCT__ 515 #define __FUNCT__ "PetscMallocSetDumpLog" 516 /*@C 517 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 518 519 Not Collective 520 521 Options Database Key: 522 + -malloc_log <filename> - Activates PetscMallocDumpLog() 523 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 524 525 Level: advanced 526 527 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 528 @*/ 529 PetscErrorCode PetscMallocSetDumpLog(void) 530 { 531 PetscErrorCode ierr; 532 533 PetscFunctionBegin; 534 PetscLogMalloc = 0; 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 PETSC_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