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