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