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 PetscFunctionBegin; 503 PetscLogMalloc = 0; 504 PetscFunctionReturn(0); 505 } 506 507 #undef __FUNCT__ 508 #define __FUNCT__ "PetscMallocDumpLog" 509 /*@C 510 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 511 PetscMemoryGetCurrentUsage() and PetscMemoryGetMaximumUsage() 512 513 Collective on PETSC_COMM_WORLD 514 515 Input Parameter: 516 . fp - file pointer; or PETSC_NULL 517 518 Options Database Key: 519 . -malloc_log - Activates PetscMallocDumpLog() 520 521 Level: advanced 522 523 Fortran Note: 524 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 525 The fp defaults to stdout. 526 527 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 528 @*/ 529 PetscErrorCode PETSC_DLLEXPORT PetscMallocDumpLog(FILE *fp) 530 { 531 PetscInt i,j,n,dummy,*perm; 532 size_t *shortlength; 533 int *shortcount,err; 534 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 535 PetscTruth match; 536 const char **shortfunction; 537 PetscLogDouble rss; 538 MPI_Status status; 539 PetscErrorCode ierr; 540 541 PetscFunctionBegin; 542 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 543 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 544 /* 545 Try to get the data printed in order by processor. This will only sometimes work 546 */ 547 err = fflush(fp); 548 if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on file"); 549 550 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 551 if (rank) { 552 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 553 } 554 555 if (!fp) fp = PETSC_STDOUT; 556 ierr = PetscMemoryGetCurrentUsage(&rss);CHKERRQ(ierr); 557 if (rss) { 558 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %D\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr); 559 } else { 560 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); 561 } 562 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()"); 563 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 564 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 565 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char *));if (!shortfunction) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 566 shortfunction[0] = PetscLogMallocFunction[0]; 567 shortlength[0] = PetscLogMallocLength[0]; 568 shortcount[0] = 0; 569 n = 1; 570 for (i=1; i<PetscLogMalloc; i++) { 571 for (j=0; j<n; j++) { 572 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 573 if (match) { 574 shortlength[j] += PetscLogMallocLength[i]; 575 shortcount[j]++; 576 goto foundit; 577 } 578 } 579 shortfunction[n] = PetscLogMallocFunction[i]; 580 shortlength[n] = PetscLogMallocLength[i]; 581 shortcount[n] = 1; 582 n++; 583 foundit:; 584 } 585 586 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_ERR_MEM,"Out of memory"); 587 for (i=0; i<n; i++) perm[i] = i; 588 ierr = PetscSortStrWithPermutation(n,(const char **)shortfunction,perm);CHKERRQ(ierr); 589 590 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 591 for (i=0; i<n; i++) { 592 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 593 } 594 free(perm); 595 free(shortlength); 596 free(shortcount); 597 free((char **)shortfunction); 598 err = fflush(fp); 599 if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on file"); 600 if (rank != size-1) { 601 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 602 } 603 PetscFunctionReturn(0); 604 } 605 606 /* ---------------------------------------------------------------------------- */ 607 608 #undef __FUNCT__ 609 #define __FUNCT__ "PetscMallocDebug" 610 /*@C 611 PetscMallocDebug - Turns on/off debugging for the memory management routines. 612 613 Not Collective 614 615 Input Parameter: 616 . level - PETSC_TRUE or PETSC_FALSE 617 618 Level: intermediate 619 620 .seealso: CHKMEMQ(), PetscMallocValidate() 621 @*/ 622 PetscErrorCode PETSC_DLLEXPORT PetscMallocDebug(PetscTruth level) 623 { 624 PetscFunctionBegin; 625 TRdebugLevel = level; 626 PetscFunctionReturn(0); 627 } 628