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