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 "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 PETSC_DLLEXPORT PetscMallocAlign(size_t,int,const char[],const char[],const char[],void**); 19 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscFreeAlign(void*,int,const char[],const char[],const char[]); 20 EXTERN PetscErrorCode PETSC_DLLEXPORT PetscTrMallocDefault(size_t,int,const char[],const char[],const char[],void**); 21 EXTERN PetscErrorCode PETSC_DLLEXPORT 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 PetscTruth 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 PETSC_DLLEXPORT 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_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_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_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 PETSC_DLLEXPORT 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) { 184 SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Trying to malloc zero size array"); 185 } 186 187 if (TRdebugLevel) { 188 ierr = PetscMallocValidate(lineno,function,filename,dir); if (ierr) PetscFunctionReturn(ierr); 189 } 190 191 nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 192 ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,dir,(void**)&inew);CHKERRQ(ierr); 193 194 head = (TRSPACE *)inew; 195 inew += sizeof(TrSPACE); 196 197 if (TRhead) TRhead->prev = head; 198 head->next = TRhead; 199 TRhead = head; 200 head->prev = 0; 201 head->size = nsize; 202 head->id = TRid; 203 head->lineno = lineno; 204 205 head->filename = filename; 206 head->functionname = function; 207 head->dirname = dir; 208 head->classid = CLASSID_VALUE; 209 *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 210 211 TRallocated += nsize; 212 if (TRallocated > TRMaxMem) { 213 TRMaxMem = TRallocated; 214 } 215 TRfrags++; 216 217 #if defined(PETSC_USE_DEBUG) 218 ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 219 #endif 220 221 /* 222 Allow logging of all mallocs made 223 */ 224 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax) { 225 if (!PetscLogMalloc) { 226 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 227 if (!PetscLogMallocLength) SETERRQ(PETSC_ERR_MEM," "); 228 PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char**)); 229 if (!PetscLogMallocDirectory) SETERRQ(PETSC_ERR_MEM," "); 230 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char**)); 231 if (!PetscLogMallocFile) SETERRQ(PETSC_ERR_MEM," "); 232 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char**)); 233 if (!PetscLogMallocFunction) SETERRQ(PETSC_ERR_MEM," "); 234 } 235 PetscLogMallocLength[PetscLogMalloc] = nsize; 236 PetscLogMallocDirectory[PetscLogMalloc] = dir; 237 PetscLogMallocFile[PetscLogMalloc] = filename; 238 PetscLogMallocFunction[PetscLogMalloc++] = function; 239 } 240 *result = (void*)inew; 241 PetscFunctionReturn(0); 242 } 243 244 245 #undef __FUNCT__ 246 #define __FUNCT__ "PetscTrFreeDefault" 247 /* 248 PetscTrFreeDefault - Free with tracing. 249 250 Input Parameters: 251 . a - pointer to a block allocated with PetscTrMalloc 252 . lineno - line number where used. Use __LINE__ for this 253 . function - function calling routine. Use __FUNCT__ for this 254 . file - file name where used. Use __FILE__ for this 255 . dir - directory where file is. Use __SDIR__ for this 256 */ 257 PetscErrorCode PETSC_DLLEXPORT PetscTrFreeDefault(void *aa,int line,const char function[],const char file[],const char dir[]) 258 { 259 char *a = (char*)aa; 260 TRSPACE *head; 261 char *ahead; 262 PetscErrorCode ierr; 263 PetscClassId *nend; 264 265 PetscFunctionBegin; 266 /* Do not try to handle empty blocks */ 267 if (!a) { 268 (*PetscErrorPrintf)("PetscTrFreeDefault called from %s() line %d in %s%s\n",function,line,dir,file); 269 SETERRQ4(PETSC_ERR_ARG_OUTOFRANGE,"Trying to free null block: Free called from %s() line %d in %s%s\n",function,line,dir,file); 270 } 271 272 if (TRdebugLevel) { 273 ierr = PetscMallocValidate(line,function,file,dir);CHKERRQ(ierr); 274 } 275 276 ahead = a; 277 a = a - sizeof(TrSPACE); 278 head = (TRSPACE *)a; 279 280 if (head->classid != CLASSID_VALUE) { 281 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 282 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 283 SETERRQ(PETSC_ERR_MEMC,"Bad location or corrupted memory"); 284 } 285 nend = (PetscClassId *)(ahead + head->size); 286 if (*nend != CLASSID_VALUE) { 287 if (*nend == ALREADY_FREED) { 288 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 289 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 290 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 291 (*PetscErrorPrintf)("Block freed in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 292 } else { 293 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,-head->lineno,head->dirname,head->filename); 294 } 295 SETERRQ(PETSC_ERR_ARG_WRONG,"Memory already freed"); 296 } else { 297 /* Damaged tail */ 298 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 299 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 300 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 301 SETERRQ(PETSC_ERR_MEMC,"Corrupted memory"); 302 } 303 } 304 /* Mark the location freed */ 305 *nend = ALREADY_FREED; 306 /* Save location where freed. If we suspect the line number, mark as allocated location */ 307 if (line > 0 && line < 50000) { 308 head->lineno = line; 309 head->filename = file; 310 head->functionname = function; 311 head->dirname = dir; 312 } else { 313 head->lineno = - head->lineno; 314 } 315 /* zero out memory - helps to find some reuse of already freed memory */ 316 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 317 318 TRallocated -= head->size; 319 TRfrags --; 320 if (head->prev) head->prev->next = head->next; 321 else TRhead = head->next; 322 323 if (head->next) head->next->prev = head->prev; 324 ierr = PetscFreeAlign(a,line,function,file,dir);CHKERRQ(ierr); 325 PetscFunctionReturn(0); 326 } 327 328 329 #undef __FUNCT__ 330 #define __FUNCT__ "PetscMemoryShowUsage" 331 /*@C 332 PetscMemoryShowUsage - Shows the amount of memory currently being used 333 in a communicator. 334 335 Collective on PetscViewer 336 337 Input Parameter: 338 + viewer - the viewer that defines the communicator 339 - message - string printed before values 340 341 Level: intermediate 342 343 Concepts: memory usage 344 345 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage() 346 @*/ 347 PetscErrorCode PETSC_DLLEXPORT PetscMemoryShowUsage(PetscViewer viewer,const char message[]) 348 { 349 PetscLogDouble allocated,maximum,resident,residentmax; 350 PetscErrorCode ierr; 351 PetscMPIInt rank; 352 MPI_Comm comm; 353 354 PetscFunctionBegin; 355 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 356 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 357 ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr); 358 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 359 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 360 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 361 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 362 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 363 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 364 if (resident && residentmax && allocated) { 365 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);CHKERRQ(ierr); 366 } else if (resident && residentmax) { 367 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);CHKERRQ(ierr); 368 } else if (resident && allocated) { 369 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);CHKERRQ(ierr); 370 } else if (allocated) { 371 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);CHKERRQ(ierr); 372 } else { 373 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 374 } 375 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 376 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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__ "PetscMallocDumpLog" 510 /*@C 511 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 512 PetscMemoryGetMaximumUsage() 513 514 Collective on PETSC_COMM_WORLD 515 516 Input Parameter: 517 . fp - file pointer; or PETSC_NULL 518 519 Options Database Key: 520 . -malloc_log - Activates PetscMallocDumpLog() 521 522 Level: advanced 523 524 Fortran Note: 525 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 526 The fp defaults to stdout. 527 528 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 529 @*/ 530 PetscErrorCode PETSC_DLLEXPORT PetscMallocDumpLog(FILE *fp) 531 { 532 PetscInt i,j,n,dummy,*perm; 533 size_t *shortlength; 534 int *shortcount,err; 535 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 536 PetscTruth match; 537 const char **shortfunction; 538 PetscLogDouble rss; 539 MPI_Status status; 540 PetscErrorCode ierr; 541 542 PetscFunctionBegin; 543 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 544 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 545 /* 546 Try to get the data printed in order by processor. This will only sometimes work 547 */ 548 err = fflush(fp); 549 if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on file"); 550 551 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 552 if (rank) { 553 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 554 } 555 556 if (!fp) fp = PETSC_STDOUT; 557 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 558 if (rss) { 559 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); 560 } else { 561 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); 562 } 563 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()"); 564 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 565 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 566 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char *));if (!shortfunction) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 567 shortfunction[0] = PetscLogMallocFunction[0]; 568 shortlength[0] = PetscLogMallocLength[0]; 569 shortcount[0] = 0; 570 n = 1; 571 for (i=1; i<PetscLogMalloc; i++) { 572 for (j=0; j<n; j++) { 573 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 574 if (match) { 575 shortlength[j] += PetscLogMallocLength[i]; 576 shortcount[j]++; 577 goto foundit; 578 } 579 } 580 shortfunction[n] = PetscLogMallocFunction[i]; 581 shortlength[n] = PetscLogMallocLength[i]; 582 shortcount[n] = 1; 583 n++; 584 foundit:; 585 } 586 587 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 588 for (i=0; i<n; i++) perm[i] = i; 589 ierr = PetscSortStrWithPermutation(n,(const char **)shortfunction,perm);CHKERRQ(ierr); 590 591 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 592 for (i=0; i<n; i++) { 593 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 594 } 595 free(perm); 596 free(shortlength); 597 free(shortcount); 598 free((char **)shortfunction); 599 err = fflush(fp); 600 if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on file"); 601 if (rank != size-1) { 602 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 603 } 604 PetscFunctionReturn(0); 605 } 606 607 /* ---------------------------------------------------------------------------- */ 608 609 #undef __FUNCT__ 610 #define __FUNCT__ "PetscMallocDebug" 611 /*@C 612 PetscMallocDebug - Turns on/off debugging for the memory management routines. 613 614 Not Collective 615 616 Input Parameter: 617 . level - PETSC_TRUE or PETSC_FALSE 618 619 Level: intermediate 620 621 .seealso: CHKMEMQ(), PetscMallocValidate() 622 @*/ 623 PetscErrorCode PETSC_DLLEXPORT PetscMallocDebug(PetscTruth level) 624 { 625 PetscFunctionBegin; 626 TRdebugLevel = level; 627 PetscFunctionReturn(0); 628 } 629