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