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