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 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 219 head->stack.line[head->stack.currentsize-2] = lineno; 220 #endif 221 222 /* 223 Allow logging of all mallocs made 224 */ 225 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 226 if (!PetscLogMalloc) { 227 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 228 if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 229 PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 230 if (!PetscLogMallocDirectory) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 231 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 232 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 233 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 234 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 235 } 236 PetscLogMallocLength[PetscLogMalloc] = nsize; 237 PetscLogMallocDirectory[PetscLogMalloc] = dir; 238 PetscLogMallocFile[PetscLogMalloc] = filename; 239 PetscLogMallocFunction[PetscLogMalloc++] = function; 240 } 241 *result = (void*)inew; 242 PetscFunctionReturn(0); 243 } 244 245 246 #undef __FUNCT__ 247 #define __FUNCT__ "PetscTrFreeDefault" 248 /* 249 PetscTrFreeDefault - Free with tracing. 250 251 Input Parameters: 252 . a - pointer to a block allocated with PetscTrMalloc 253 . lineno - line number where used. Use __LINE__ for this 254 . function - function calling routine. Use __FUNCT__ for this 255 . file - file name where used. Use __FILE__ for this 256 . dir - directory where file is. Use __SDIR__ for this 257 */ 258 PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[],const char dir[]) 259 { 260 char *a = (char*)aa; 261 TRSPACE *head; 262 char *ahead; 263 PetscErrorCode ierr; 264 PetscClassId *nend; 265 266 PetscFunctionBegin; 267 /* Do not try to handle empty blocks */ 268 if (!a) { 269 (*PetscErrorPrintf)("PetscTrFreeDefault called from %s() line %d in %s%s\n",function,line,dir,file); 270 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); 271 } 272 273 if (TRdebugLevel) { 274 ierr = PetscMallocValidate(line,function,file,dir);CHKERRQ(ierr); 275 } 276 277 ahead = a; 278 a = a - sizeof(TrSPACE); 279 head = (TRSPACE *)a; 280 281 if (head->classid != CLASSID_VALUE) { 282 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 283 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 284 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 285 } 286 nend = (PetscClassId *)(ahead + head->size); 287 if (*nend != CLASSID_VALUE) { 288 if (*nend == ALREADY_FREED) { 289 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 290 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 291 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 292 (*PetscErrorPrintf)("Block freed in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 293 } else { 294 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,-head->lineno,head->dirname,head->filename); 295 } 296 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 297 } else { 298 /* Damaged tail */ 299 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file); 300 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 301 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename); 302 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 303 } 304 } 305 /* Mark the location freed */ 306 *nend = ALREADY_FREED; 307 /* Save location where freed. If we suspect the line number, mark as allocated location */ 308 if (line > 0 && line < 50000) { 309 head->lineno = line; 310 head->filename = file; 311 head->functionname = function; 312 head->dirname = dir; 313 } else { 314 head->lineno = - head->lineno; 315 } 316 /* zero out memory - helps to find some reuse of already freed memory */ 317 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 318 319 TRallocated -= head->size; 320 TRfrags --; 321 if (head->prev) head->prev->next = head->next; 322 else TRhead = head->next; 323 324 if (head->next) head->next->prev = head->prev; 325 ierr = PetscFreeAlign(a,line,function,file,dir);CHKERRQ(ierr); 326 PetscFunctionReturn(0); 327 } 328 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "PetscMemoryShowUsage" 332 /*@C 333 PetscMemoryShowUsage - Shows the amount of memory currently being used 334 in a communicator. 335 336 Collective on PetscViewer 337 338 Input Parameter: 339 + viewer - the viewer that defines the communicator 340 - message - string printed before values 341 342 Level: intermediate 343 344 Concepts: memory usage 345 346 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage() 347 @*/ 348 PetscErrorCode PetscMemoryShowUsage(PetscViewer viewer,const char message[]) 349 { 350 PetscLogDouble allocated,maximum,resident,residentmax; 351 PetscErrorCode ierr; 352 PetscMPIInt rank; 353 MPI_Comm comm; 354 355 PetscFunctionBegin; 356 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 357 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 358 ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr); 359 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 360 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 361 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 362 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 363 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 364 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 365 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 366 if (resident && residentmax && allocated) { 367 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);CHKERRQ(ierr); 368 } else if (resident && residentmax) { 369 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);CHKERRQ(ierr); 370 } else if (resident && allocated) { 371 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);CHKERRQ(ierr); 372 } else if (allocated) { 373 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);CHKERRQ(ierr); 374 } else { 375 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 376 } 377 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 378 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 379 PetscFunctionReturn(0); 380 } 381 382 #undef __FUNCT__ 383 #define __FUNCT__ "PetscMallocGetCurrentUsage" 384 /*@C 385 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 386 387 Not Collective 388 389 Output Parameters: 390 . space - number of bytes currently allocated 391 392 Level: intermediate 393 394 Concepts: memory usage 395 396 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 397 PetscMemoryGetMaximumUsage() 398 @*/ 399 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 400 { 401 PetscFunctionBegin; 402 *space = (PetscLogDouble) TRallocated; 403 PetscFunctionReturn(0); 404 } 405 406 #undef __FUNCT__ 407 #define __FUNCT__ "PetscMallocGetMaximumUsage" 408 /*@C 409 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 410 during this run. 411 412 Not Collective 413 414 Output Parameters: 415 . space - maximum number of bytes ever allocated at one time 416 417 Level: intermediate 418 419 Concepts: memory usage 420 421 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 422 PetscMemoryGetCurrentUsage() 423 @*/ 424 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 425 { 426 PetscFunctionBegin; 427 *space = (PetscLogDouble) TRMaxMem; 428 PetscFunctionReturn(0); 429 } 430 431 #if defined(PETSC_USE_DEBUG) 432 #undef __FUNCT__ 433 #define __FUNCT__ "PetscMallocGetStack" 434 /*@C 435 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 436 437 Collective on PETSC_COMM_WORLD 438 439 Input Parameter: 440 . ptr - the memory location 441 442 Output Paramter: 443 . stack - the stack indicating where the program allocated this memory 444 445 Level: intermediate 446 447 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 448 @*/ 449 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 450 { 451 TRSPACE *head; 452 453 PetscFunctionBegin; 454 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 455 *stack = &head->stack; 456 PetscFunctionReturn(0); 457 } 458 #endif 459 460 #undef __FUNCT__ 461 #define __FUNCT__ "PetscMallocDump" 462 /*@C 463 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 464 printed is: size of space (in bytes), address of space, id of space, 465 file in which space was allocated, and line number at which it was 466 allocated. 467 468 Collective on PETSC_COMM_WORLD 469 470 Input Parameter: 471 . fp - file pointer. If fp is NULL, stdout is assumed. 472 473 Options Database Key: 474 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 475 476 Level: intermediate 477 478 Fortran Note: 479 The calling sequence in Fortran is PetscMallocDump(integer ierr) 480 The fp defaults to stdout. 481 482 Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 483 has been freed. 484 485 Concepts: memory usage 486 Concepts: memory bleeding 487 Concepts: bleeding memory 488 489 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 490 @*/ 491 PetscErrorCode PetscMallocDump(FILE *fp) 492 { 493 TRSPACE *head; 494 PetscErrorCode ierr; 495 PetscMPIInt rank; 496 497 PetscFunctionBegin; 498 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 499 if (!fp) fp = PETSC_STDOUT; 500 if (TRallocated > 0) { 501 fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 502 } 503 head = TRhead; 504 while (head) { 505 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,head->filename); 506 #if defined(PETSC_USE_DEBUG) 507 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 508 #endif 509 head = head->next; 510 } 511 PetscFunctionReturn(0); 512 } 513 514 /* ---------------------------------------------------------------------------- */ 515 516 #undef __FUNCT__ 517 #define __FUNCT__ "PetscMallocSetDumpLog" 518 /*@C 519 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 520 521 Not Collective 522 523 Options Database Key: 524 + -malloc_log <filename> - Activates PetscMallocDumpLog() 525 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 526 527 Level: advanced 528 529 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 530 @*/ 531 PetscErrorCode PetscMallocSetDumpLog(void) 532 { 533 PetscErrorCode ierr; 534 535 PetscFunctionBegin; 536 PetscLogMalloc = 0; 537 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 538 PetscFunctionReturn(0); 539 } 540 541 #undef __FUNCT__ 542 #define __FUNCT__ "PetscMallocSetDumpLogThreshold" 543 /*@C 544 PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 545 546 Not Collective 547 548 Input Arguments: 549 . logmin - minimum allocation size to log, or PETSC_DEFAULT 550 551 Options Database Key: 552 + -malloc_log <filename> - Activates PetscMallocDumpLog() 553 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 554 555 Level: advanced 556 557 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 558 @*/ 559 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 560 { 561 PetscErrorCode ierr; 562 563 PetscFunctionBegin; 564 ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 565 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 566 PetscLogMallocThreshold = (size_t)logmin; 567 PetscFunctionReturn(0); 568 } 569 570 #undef __FUNCT__ 571 #define __FUNCT__ "PetscMallocGetDumpLog" 572 /*@C 573 PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 574 575 Not Collective 576 577 Output Arguments 578 . logging - PETSC_TRUE if logging is active 579 580 Options Database Key: 581 . -malloc_log - Activates PetscMallocDumpLog() 582 583 Level: advanced 584 585 .seealso: PetscMallocDump(), PetscMallocDumpLog() 586 @*/ 587 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 588 { 589 590 PetscFunctionBegin; 591 *logging = (PetscBool)(PetscLogMalloc >= 0); 592 PetscFunctionReturn(0); 593 } 594 595 #undef __FUNCT__ 596 #define __FUNCT__ "PetscMallocDumpLog" 597 /*@C 598 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 599 PetscMemoryGetMaximumUsage() 600 601 Collective on PETSC_COMM_WORLD 602 603 Input Parameter: 604 . fp - file pointer; or PETSC_NULL 605 606 Options Database Key: 607 . -malloc_log - Activates PetscMallocDumpLog() 608 609 Level: advanced 610 611 Fortran Note: 612 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 613 The fp defaults to stdout. 614 615 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 616 @*/ 617 PetscErrorCode PetscMallocDumpLog(FILE *fp) 618 { 619 PetscInt i,j,n,dummy,*perm; 620 size_t *shortlength; 621 int *shortcount,err; 622 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 623 PetscBool match; 624 const char **shortfunction; 625 PetscLogDouble rss; 626 MPI_Status status; 627 PetscErrorCode ierr; 628 629 PetscFunctionBegin; 630 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 631 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 632 /* 633 Try to get the data printed in order by processor. This will only sometimes work 634 */ 635 err = fflush(fp); 636 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 637 638 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 639 if (rank) { 640 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 641 } 642 643 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()"); 644 645 if (!fp) fp = PETSC_STDOUT; 646 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 647 if (rss) { 648 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); 649 } else { 650 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); 651 } 652 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 653 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 654 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char *));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 655 for (i=0,n=0; i<PetscLogMalloc; i++) { 656 for (j=0; j<n; j++) { 657 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 658 if (match) { 659 shortlength[j] += PetscLogMallocLength[i]; 660 shortcount[j]++; 661 goto foundit; 662 } 663 } 664 shortfunction[n] = PetscLogMallocFunction[i]; 665 shortlength[n] = PetscLogMallocLength[i]; 666 shortcount[n] = 1; 667 n++; 668 foundit:; 669 } 670 671 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 672 for (i=0; i<n; i++) perm[i] = i; 673 ierr = PetscSortStrWithPermutation(n,(const char **)shortfunction,perm);CHKERRQ(ierr); 674 675 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 676 for (i=0; i<n; i++) { 677 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 678 } 679 free(perm); 680 free(shortlength); 681 free(shortcount); 682 free((char **)shortfunction); 683 err = fflush(fp); 684 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 685 if (rank != size-1) { 686 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 687 } 688 PetscFunctionReturn(0); 689 } 690 691 /* ---------------------------------------------------------------------------- */ 692 693 #undef __FUNCT__ 694 #define __FUNCT__ "PetscMallocDebug" 695 /*@C 696 PetscMallocDebug - Turns on/off debugging for the memory management routines. 697 698 Not Collective 699 700 Input Parameter: 701 . level - PETSC_TRUE or PETSC_FALSE 702 703 Level: intermediate 704 705 .seealso: CHKMEMQ(), PetscMallocValidate() 706 @*/ 707 PetscErrorCode PetscMallocDebug(PetscBool level) 708 { 709 PetscFunctionBegin; 710 TRdebugLevel = level; 711 PetscFunctionReturn(0); 712 } 713