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