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