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_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 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) 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 if (resident && residentmax && allocated) { 363 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); 364 } else if (resident && residentmax) { 365 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); 366 } else if (resident && allocated) { 367 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); 368 } else if (allocated) { 369 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); 370 } else { 371 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 372 } 373 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 374 PetscFunctionReturn(0); 375 } 376 377 #undef __FUNCT__ 378 #define __FUNCT__ "PetscMallocGetCurrentUsage" 379 /*@C 380 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 381 382 Not Collective 383 384 Output Parameters: 385 . space - number of bytes currently allocated 386 387 Level: intermediate 388 389 Concepts: memory usage 390 391 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 392 PetscMemoryGetMaximumUsage() 393 @*/ 394 PetscErrorCode PETSC_DLLEXPORT PetscMallocGetCurrentUsage(PetscLogDouble *space) 395 { 396 PetscFunctionBegin; 397 *space = (PetscLogDouble) TRallocated; 398 PetscFunctionReturn(0); 399 } 400 401 #undef __FUNCT__ 402 #define __FUNCT__ "PetscMallocGetMaximumUsage" 403 /*@C 404 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 405 during this run. 406 407 Not Collective 408 409 Output Parameters: 410 . space - maximum number of bytes ever allocated at one time 411 412 Level: intermediate 413 414 Concepts: memory usage 415 416 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 417 PetscMemoryGetCurrentUsage() 418 @*/ 419 PetscErrorCode PETSC_DLLEXPORT PetscMallocGetMaximumUsage(PetscLogDouble *space) 420 { 421 PetscFunctionBegin; 422 *space = (PetscLogDouble) TRMaxMem; 423 PetscFunctionReturn(0); 424 } 425 426 #undef __FUNCT__ 427 #define __FUNCT__ "PetscMallocDump" 428 /*@C 429 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 430 printed is: size of space (in bytes), address of space, id of space, 431 file in which space was allocated, and line number at which it was 432 allocated. 433 434 Collective on PETSC_COMM_WORLD 435 436 Input Parameter: 437 . fp - file pointer. If fp is NULL, stdout is assumed. 438 439 Options Database Key: 440 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 441 442 Level: intermediate 443 444 Fortran Note: 445 The calling sequence in Fortran is PetscMallocDump(integer ierr) 446 The fp defaults to stdout. 447 448 Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 449 has been freed. 450 451 Concepts: memory usage 452 Concepts: memory bleeding 453 Concepts: bleeding memory 454 455 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 456 @*/ 457 PetscErrorCode PETSC_DLLEXPORT PetscMallocDump(FILE *fp) 458 { 459 TRSPACE *head; 460 PetscErrorCode ierr; 461 PetscMPIInt rank; 462 463 PetscFunctionBegin; 464 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 465 if (!fp) fp = PETSC_STDOUT; 466 if (TRallocated > 0) { 467 fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 468 } 469 head = TRhead; 470 while (head) { 471 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,head->filename); 472 #if defined(PETSC_USE_DEBUG) 473 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 474 #endif 475 head = head->next; 476 } 477 PetscFunctionReturn(0); 478 } 479 480 /* ---------------------------------------------------------------------------- */ 481 482 #undef __FUNCT__ 483 #define __FUNCT__ "PetscMallocSetDumpLog" 484 /*@C 485 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 486 487 Not Collective 488 489 Options Database Key: 490 . -malloc_log - Activates PetscMallocDumpLog() 491 492 Level: advanced 493 494 .seealso: PetscMallocDump(), PetscMallocDumpLog() 495 @*/ 496 PetscErrorCode PETSC_DLLEXPORT PetscMallocSetDumpLog(void) 497 { 498 PetscErrorCode ierr; 499 500 PetscFunctionBegin; 501 PetscLogMalloc = 0; 502 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 503 PetscFunctionReturn(0); 504 } 505 506 #undef __FUNCT__ 507 #define __FUNCT__ "PetscMallocDumpLog" 508 /*@C 509 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 510 PetscMemoryGetMaximumUsage() 511 512 Collective on PETSC_COMM_WORLD 513 514 Input Parameter: 515 . fp - file pointer; or PETSC_NULL 516 517 Options Database Key: 518 . -malloc_log - Activates PetscMallocDumpLog() 519 520 Level: advanced 521 522 Fortran Note: 523 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 524 The fp defaults to stdout. 525 526 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 527 @*/ 528 PetscErrorCode PETSC_DLLEXPORT PetscMallocDumpLog(FILE *fp) 529 { 530 PetscInt i,j,n,dummy,*perm; 531 size_t *shortlength; 532 int *shortcount,err; 533 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 534 PetscTruth match; 535 const char **shortfunction; 536 PetscLogDouble rss; 537 MPI_Status status; 538 PetscErrorCode ierr; 539 540 PetscFunctionBegin; 541 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 542 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 543 /* 544 Try to get the data printed in order by processor. This will only sometimes work 545 */ 546 err = fflush(fp); 547 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 548 549 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 550 if (rank) { 551 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 552 } 553 554 if (!fp) fp = PETSC_STDOUT; 555 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 556 if (rss) { 557 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); 558 } else { 559 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); 560 } 561 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()"); 562 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 563 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 564 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char *));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 565 shortfunction[0] = PetscLogMallocFunction[0]; 566 shortlength[0] = PetscLogMallocLength[0]; 567 shortcount[0] = 0; 568 n = 1; 569 for (i=1; i<PetscLogMalloc; i++) { 570 for (j=0; j<n; j++) { 571 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 572 if (match) { 573 shortlength[j] += PetscLogMallocLength[i]; 574 shortcount[j]++; 575 goto foundit; 576 } 577 } 578 shortfunction[n] = PetscLogMallocFunction[i]; 579 shortlength[n] = PetscLogMallocLength[i]; 580 shortcount[n] = 1; 581 n++; 582 foundit:; 583 } 584 585 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 586 for (i=0; i<n; i++) perm[i] = i; 587 ierr = PetscSortStrWithPermutation(n,(const char **)shortfunction,perm);CHKERRQ(ierr); 588 589 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 590 for (i=0; i<n; i++) { 591 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 592 } 593 free(perm); 594 free(shortlength); 595 free(shortcount); 596 free((char **)shortfunction); 597 err = fflush(fp); 598 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 599 if (rank != size-1) { 600 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 601 } 602 PetscFunctionReturn(0); 603 } 604 605 /* ---------------------------------------------------------------------------- */ 606 607 #undef __FUNCT__ 608 #define __FUNCT__ "PetscMallocDebug" 609 /*@C 610 PetscMallocDebug - Turns on/off debugging for the memory management routines. 611 612 Not Collective 613 614 Input Parameter: 615 . level - PETSC_TRUE or PETSC_FALSE 616 617 Level: intermediate 618 619 .seealso: CHKMEMQ(), PetscMallocValidate() 620 @*/ 621 PetscErrorCode PETSC_DLLEXPORT PetscMallocDebug(PetscTruth level) 622 { 623 PetscFunctionBegin; 624 TRdebugLevel = level; 625 PetscFunctionReturn(0); 626 } 627