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