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