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 #include <petscviewer.h> 8 #if defined(PETSC_HAVE_MALLOC_H) 9 #include <malloc.h> 10 #endif 11 12 13 /* 14 These are defined in mal.c and ensure that malloced space is PetscScalar aligned 15 */ 16 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**); 17 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]); 18 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**); 19 PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**); 20 PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]); 21 PETSC_EXTERN PetscErrorCode PetscTrReallocDefault(size_t,int,const char[],const char[],void**); 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 PetscClassId classid; 34 #if defined(PETSC_USE_DEBUG) 35 PetscStack stack; 36 #endif 37 struct _trSPACE *next,*prev; 38 } TRSPACE; 39 40 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 41 It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN. 42 */ 43 44 #define HEADER_BYTES ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1)) 45 46 47 /* This union is used to insure that the block passed to the user retains 48 a minimum alignment of PETSC_MEMALIGN. 49 */ 50 typedef union { 51 TRSPACE sp; 52 char v[HEADER_BYTES]; 53 } TrSPACE; 54 55 #define MAXTRMAXMEMS 50 56 static size_t TRallocated = 0; 57 static int TRfrags = 0; 58 static TRSPACE *TRhead = NULL; 59 static int TRid = 0; 60 static PetscBool TRdebugLevel = PETSC_FALSE; 61 static size_t TRMaxMem = 0; 62 static int NumTRMaxMems = 0; 63 static size_t TRMaxMems[MAXTRMAXMEMS]; 64 static int TRMaxMemsEvents[MAXTRMAXMEMS]; 65 /* 66 Arrays to log information on all Mallocs 67 */ 68 static int PetscLogMallocMax = 10000; 69 static int PetscLogMalloc = -1; 70 static size_t PetscLogMallocThreshold = 0; 71 static size_t *PetscLogMallocLength; 72 static const char **PetscLogMallocFile,**PetscLogMallocFunction; 73 static PetscBool PetscSetUseTrMallocCalled = PETSC_FALSE; 74 75 PETSC_INTERN PetscErrorCode PetscSetUseTrMalloc_Private(void) 76 { 77 PetscErrorCode ierr; 78 79 PetscFunctionBegin; 80 if (PetscSetUseTrMallocCalled) PetscFunctionReturn(0); 81 PetscSetUseTrMallocCalled = PETSC_TRUE; 82 ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr); 83 PetscTrRealloc = PetscTrReallocDefault; 84 85 TRallocated = 0; 86 TRfrags = 0; 87 TRhead = NULL; 88 TRid = 0; 89 TRdebugLevel = PETSC_FALSE; 90 TRMaxMem = 0; 91 PetscLogMallocMax = 10000; 92 PetscLogMalloc = -1; 93 PetscFunctionReturn(0); 94 } 95 96 /*@C 97 PetscMallocValidate - Test the memory for corruption. This can be used to 98 check for memory overwrites. 99 100 Input Parameter: 101 + line - line number where call originated. 102 . function - name of function calling 103 - file - file where function is 104 105 Return value: 106 The number of errors detected. 107 108 Output Effect: 109 Error messages are written to stdout. 110 111 Level: advanced 112 113 Notes: 114 You should generally use CHKMEMQ as a short cut for calling this 115 routine. 116 117 The line, function, file are given by the C preprocessor as 118 119 The Fortran calling sequence is simply PetscMallocValidate(ierr) 120 121 No output is generated if there are no problems detected. 122 123 .seealso: CHKMEMQ 124 125 @*/ 126 PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[]) 127 { 128 TRSPACE *head,*lasthead; 129 char *a; 130 PetscClassId *nend; 131 132 PetscFunctionBegin; 133 head = TRhead; lasthead = NULL; 134 while (head) { 135 if (head->classid != CLASSID_VALUE) { 136 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 137 (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head); 138 (*PetscErrorPrintf)("Probably write past beginning or end of array\n"); 139 if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename); 140 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 141 } 142 a = (char*)(((TrSPACE*)head) + 1); 143 nend = (PetscClassId*)(a + head->size); 144 if (*nend != CLASSID_VALUE) { 145 (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 146 if (*nend == ALREADY_FREED) { 147 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a); 148 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 149 } else { 150 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 151 (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 152 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 153 } 154 } 155 lasthead = head; 156 head = head->next; 157 } 158 PetscFunctionReturn(0); 159 } 160 161 /* 162 PetscTrMallocDefault - Malloc with tracing. 163 164 Input Parameters: 165 + a - number of bytes to allocate 166 . lineno - line number where used. Use __LINE__ for this 167 - filename - file name where used. Use __FILE__ for this 168 169 Returns: 170 double aligned pointer to requested storage, or null if not 171 available. 172 */ 173 PetscErrorCode PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result) 174 { 175 TRSPACE *head; 176 char *inew; 177 size_t nsize; 178 PetscErrorCode ierr; 179 180 PetscFunctionBegin; 181 /* Do not try to handle empty blocks */ 182 if (!a) { *result = NULL; PetscFunctionReturn(0); } 183 184 if (TRdebugLevel) { 185 ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr); 186 } 187 188 nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 189 ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 190 191 if (PetscLogMemory) { 192 /* zero the memory to force the value of PetscMemoryGetCurrentUsage() to accurately reflect allocated memory */ 193 ierr = PetscMemzero(inew,nsize+sizeof(TrSPACE)+sizeof(PetscClassId));CHKERRQ(ierr); 194 } 195 196 head = (TRSPACE*)inew; 197 inew += sizeof(TrSPACE); 198 199 if (TRhead) TRhead->prev = head; 200 head->next = TRhead; 201 TRhead = head; 202 head->prev = NULL; 203 head->size = nsize; 204 head->id = TRid; 205 head->lineno = lineno; 206 207 head->filename = filename; 208 head->functionname = function; 209 head->classid = CLASSID_VALUE; 210 *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 211 212 TRallocated += nsize; 213 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 214 if (PetscLogMemory) { 215 PetscInt i; 216 for (i=0; i<NumTRMaxMems; i++) { 217 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 218 } 219 } 220 TRfrags++; 221 222 #if defined(PETSC_USE_DEBUG) 223 if (PetscStackActive()) { 224 ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 225 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 226 head->stack.line[head->stack.currentsize-2] = lineno; 227 } else { 228 head->stack.currentsize = 0; 229 } 230 #endif 231 232 /* 233 Allow logging of all mallocs made 234 */ 235 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 236 if (!PetscLogMalloc) { 237 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 238 if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 239 240 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 241 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 242 243 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 244 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 245 } 246 PetscLogMallocLength[PetscLogMalloc] = nsize; 247 PetscLogMallocFile[PetscLogMalloc] = filename; 248 PetscLogMallocFunction[PetscLogMalloc++] = function; 249 } 250 *result = (void*)inew; 251 PetscFunctionReturn(0); 252 } 253 254 255 /* 256 PetscTrFreeDefault - Free with tracing. 257 258 Input Parameters: 259 . a - pointer to a block allocated with PetscTrMalloc 260 . lineno - line number where used. Use __LINE__ for this 261 . file - file name where used. Use __FILE__ for this 262 */ 263 PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[]) 264 { 265 char *a = (char*)aa; 266 TRSPACE *head; 267 char *ahead; 268 PetscErrorCode ierr; 269 PetscClassId *nend; 270 271 PetscFunctionBegin; 272 /* Do not try to handle empty blocks */ 273 if (!a) PetscFunctionReturn(0); 274 275 if (TRdebugLevel) { 276 ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr); 277 } 278 279 ahead = a; 280 a = a - sizeof(TrSPACE); 281 head = (TRSPACE*)a; 282 283 if (head->classid != CLASSID_VALUE) { 284 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 285 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 286 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 287 } 288 nend = (PetscClassId*)(ahead + head->size); 289 if (*nend != CLASSID_VALUE) { 290 if (*nend == ALREADY_FREED) { 291 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 292 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 293 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 294 (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 295 } else { 296 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 297 } 298 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 299 } else { 300 /* Damaged tail */ 301 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 302 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 303 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 304 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 305 } 306 } 307 /* Mark the location freed */ 308 *nend = ALREADY_FREED; 309 /* Save location where freed. If we suspect the line number, mark as allocated location */ 310 if (line > 0 && line < 50000) { 311 head->lineno = line; 312 head->filename = file; 313 head->functionname = function; 314 } else { 315 head->lineno = -head->lineno; 316 } 317 /* zero out memory - helps to find some reuse of already freed memory */ 318 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 319 320 if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed"); 321 TRallocated -= head->size; 322 TRfrags--; 323 if (head->prev) head->prev->next = head->next; 324 else TRhead = head->next; 325 326 if (head->next) head->next->prev = head->prev; 327 ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr); 328 PetscFunctionReturn(0); 329 } 330 331 332 333 /* 334 PetscTrReallocDefault - Realloc with tracing. 335 336 Input Parameters: 337 + len - number of bytes to allocate 338 . lineno - line number where used. Use __LINE__ for this 339 . filename - file name where used. Use __FILE__ for this 340 - result - double aligned pointer to initial storage. 341 342 Output Parameter: 343 . result - double aligned pointer to requested storage, or null if not available. 344 345 Level: developer 346 347 .seealso: PetscTrMallocDefault(), PetscTrFreeDefault() 348 */ 349 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) 350 { 351 char *a = (char *) *result; 352 TRSPACE *head; 353 char *ahead, *inew; 354 PetscClassId *nend; 355 size_t nsize; 356 PetscErrorCode ierr; 357 358 PetscFunctionBegin; 359 /* Realloc to zero = free */ 360 if (!len) { 361 ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr); 362 *result = NULL; 363 PetscFunctionReturn(0); 364 } 365 /* Realloc with NULL = malloc */ 366 if (!*result) { 367 ierr = PetscTrMallocDefault(len,lineno,function,filename,result);CHKERRQ(ierr); 368 PetscFunctionReturn(0); 369 } 370 371 if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);} 372 373 ahead = a; 374 a = a - sizeof(TrSPACE); 375 head = (TRSPACE *) a; 376 inew = a; 377 378 if (head->classid != CLASSID_VALUE) { 379 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 380 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 381 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 382 } 383 nend = (PetscClassId *)(ahead + head->size); 384 if (*nend != CLASSID_VALUE) { 385 if (*nend == ALREADY_FREED) { 386 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 387 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 388 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 389 (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 390 } else { 391 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 392 } 393 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 394 } else { 395 /* Damaged tail */ 396 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 397 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 398 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 399 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 400 } 401 } 402 403 TRallocated -= head->size; 404 TRfrags--; 405 if (head->prev) head->prev->next = head->next; 406 else TRhead = head->next; 407 if (head->next) head->next->prev = head->prev; 408 409 nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 410 ierr = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 411 412 head = (TRSPACE*)inew; 413 inew += sizeof(TrSPACE); 414 415 if (TRhead) TRhead->prev = head; 416 head->next = TRhead; 417 TRhead = head; 418 head->prev = NULL; 419 head->size = nsize; 420 head->id = TRid; 421 head->lineno = lineno; 422 423 head->filename = filename; 424 head->functionname = function; 425 head->classid = CLASSID_VALUE; 426 *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 427 428 TRallocated += nsize; 429 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 430 if (PetscLogMemory) { 431 PetscInt i; 432 for (i=0; i<NumTRMaxMems; i++) { 433 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 434 } 435 } 436 TRfrags++; 437 438 #if defined(PETSC_USE_DEBUG) 439 if (PetscStackActive()) { 440 ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 441 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 442 head->stack.line[head->stack.currentsize-2] = lineno; 443 } else { 444 head->stack.currentsize = 0; 445 } 446 #endif 447 448 /* 449 Allow logging of all mallocs made 450 */ 451 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 452 if (!PetscLogMalloc) { 453 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 454 if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 455 456 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 457 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 458 459 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 460 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 461 } 462 PetscLogMallocLength[PetscLogMalloc] = nsize; 463 PetscLogMallocFile[PetscLogMalloc] = filename; 464 PetscLogMallocFunction[PetscLogMalloc++] = function; 465 } 466 *result = (void*)inew; 467 PetscFunctionReturn(0); 468 } 469 470 471 /*@C 472 PetscMemoryView - Shows the amount of memory currently being used 473 in a communicator. 474 475 Collective on PetscViewer 476 477 Input Parameter: 478 + viewer - the viewer that defines the communicator 479 - message - string printed before values 480 481 Options Database: 482 + -malloc - have PETSc track how much memory it has allocated 483 - -memory_view - during PetscFinalize() have this routine called 484 485 Level: intermediate 486 487 Concepts: memory usage 488 489 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage() 490 @*/ 491 PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[]) 492 { 493 PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax; 494 PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax; 495 PetscErrorCode ierr; 496 MPI_Comm comm; 497 498 PetscFunctionBegin; 499 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 500 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 501 ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr); 502 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 503 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 504 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 505 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 506 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 507 if (resident && residentmax && allocated) { 508 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 509 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 510 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 511 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 512 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 513 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 514 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 515 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 516 ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 517 ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 518 ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 519 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);CHKERRQ(ierr); 520 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 521 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 522 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 523 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 524 } else if (resident && residentmax) { 525 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 526 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 527 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 528 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 529 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 530 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 531 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 532 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 533 } else if (resident && allocated) { 534 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 535 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 536 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 537 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 538 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 539 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 540 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 541 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 542 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 543 } else if (allocated) { 544 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 545 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 546 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 547 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 548 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 549 ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr); 550 } else { 551 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 552 } 553 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 554 PetscFunctionReturn(0); 555 } 556 557 /*@ 558 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 559 560 Not Collective 561 562 Output Parameters: 563 . space - number of bytes currently allocated 564 565 Level: intermediate 566 567 Concepts: memory usage 568 569 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 570 PetscMemoryGetMaximumUsage() 571 @*/ 572 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 573 { 574 PetscFunctionBegin; 575 *space = (PetscLogDouble) TRallocated; 576 PetscFunctionReturn(0); 577 } 578 579 /*@ 580 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 581 during this run. 582 583 Not Collective 584 585 Output Parameters: 586 . space - maximum number of bytes ever allocated at one time 587 588 Level: intermediate 589 590 Concepts: memory usage 591 592 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 593 PetscMallocPushMaximumUsage() 594 @*/ 595 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 596 { 597 PetscFunctionBegin; 598 *space = (PetscLogDouble) TRMaxMem; 599 PetscFunctionReturn(0); 600 } 601 602 /*@ 603 PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 604 605 Not Collective 606 607 Input Parameter: 608 . event - an event id; this is just for error checking 609 610 Level: developer 611 612 Concepts: memory usage 613 614 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 615 PetscMallocPopMaximumUsage() 616 @*/ 617 PetscErrorCode PetscMallocPushMaximumUsage(int event) 618 { 619 PetscFunctionBegin; 620 if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0); 621 TRMaxMems[NumTRMaxMems-1] = TRallocated; 622 TRMaxMemsEvents[NumTRMaxMems-1] = event; 623 PetscFunctionReturn(0); 624 } 625 626 /*@ 627 PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 628 629 Not Collective 630 631 Input Parameter: 632 . event - an event id; this is just for error checking 633 634 Output Parameter: 635 . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 636 637 Level: developer 638 639 Concepts: memory usage 640 641 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 642 PetscMallocPushMaximumUsage() 643 @*/ 644 PetscErrorCode PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu) 645 { 646 PetscFunctionBegin; 647 *mu = 0; 648 if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0); 649 if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested"); 650 *mu = TRMaxMems[NumTRMaxMems]; 651 PetscFunctionReturn(0); 652 } 653 654 #if defined(PETSC_USE_DEBUG) 655 /*@C 656 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 657 658 Collective on PETSC_COMM_WORLD 659 660 Input Parameter: 661 . ptr - the memory location 662 663 Output Paramter: 664 . stack - the stack indicating where the program allocated this memory 665 666 Level: intermediate 667 668 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 669 @*/ 670 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 671 { 672 TRSPACE *head; 673 674 PetscFunctionBegin; 675 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 676 *stack = &head->stack; 677 PetscFunctionReturn(0); 678 } 679 #else 680 PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 681 { 682 PetscFunctionBegin; 683 *stack = NULL; 684 PetscFunctionReturn(0); 685 } 686 #endif 687 688 /*@C 689 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 690 printed is: size of space (in bytes), address of space, id of space, 691 file in which space was allocated, and line number at which it was 692 allocated. 693 694 Collective on PETSC_COMM_WORLD 695 696 Input Parameter: 697 . fp - file pointer. If fp is NULL, stdout is assumed. 698 699 Options Database Key: 700 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 701 702 Level: intermediate 703 704 Fortran Note: 705 The calling sequence in Fortran is PetscMallocDump(integer ierr) 706 The fp defaults to stdout. 707 708 Notes: 709 uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 710 has been freed. 711 712 Concepts: memory usage 713 Concepts: memory bleeding 714 Concepts: bleeding memory 715 716 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 717 @*/ 718 PetscErrorCode PetscMallocDump(FILE *fp) 719 { 720 TRSPACE *head; 721 size_t libAlloc = 0; 722 PetscErrorCode ierr; 723 PetscMPIInt rank; 724 725 PetscFunctionBegin; 726 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 727 if (!fp) fp = PETSC_STDOUT; 728 head = TRhead; 729 while (head) { 730 libAlloc += head->size; 731 head = head->next; 732 } 733 if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 734 head = TRhead; 735 while (head) { 736 PetscBool isLib; 737 738 ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 739 if (!isLib) { 740 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 741 #if defined(PETSC_USE_DEBUG) 742 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 743 #endif 744 } 745 head = head->next; 746 } 747 PetscFunctionReturn(0); 748 } 749 750 /* ---------------------------------------------------------------------------- */ 751 752 /*@ 753 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 754 755 Not Collective 756 757 Options Database Key: 758 + -malloc_log <filename> - Activates PetscMallocDumpLog() 759 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 760 761 Level: advanced 762 763 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 764 @*/ 765 PetscErrorCode PetscMallocSetDumpLog(void) 766 { 767 PetscErrorCode ierr; 768 769 PetscFunctionBegin; 770 PetscLogMalloc = 0; 771 772 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 773 PetscFunctionReturn(0); 774 } 775 776 /*@ 777 PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 778 779 Not Collective 780 781 Input Arguments: 782 . logmin - minimum allocation size to log, or PETSC_DEFAULT 783 784 Options Database Key: 785 + -malloc_log <filename> - Activates PetscMallocDumpLog() 786 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 787 788 Level: advanced 789 790 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 791 @*/ 792 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 793 { 794 PetscErrorCode ierr; 795 796 PetscFunctionBegin; 797 ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 798 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 799 PetscLogMallocThreshold = (size_t)logmin; 800 PetscFunctionReturn(0); 801 } 802 803 /*@ 804 PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 805 806 Not Collective 807 808 Output Arguments 809 . logging - PETSC_TRUE if logging is active 810 811 Options Database Key: 812 . -malloc_log - Activates PetscMallocDumpLog() 813 814 Level: advanced 815 816 .seealso: PetscMallocDump(), PetscMallocDumpLog() 817 @*/ 818 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 819 { 820 821 PetscFunctionBegin; 822 *logging = (PetscBool)(PetscLogMalloc >= 0); 823 PetscFunctionReturn(0); 824 } 825 826 /*@C 827 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 828 PetscMemoryGetMaximumUsage() 829 830 Collective on PETSC_COMM_WORLD 831 832 Input Parameter: 833 . fp - file pointer; or NULL 834 835 Options Database Key: 836 . -malloc_log - Activates PetscMallocDumpLog() 837 838 Level: advanced 839 840 Fortran Note: 841 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 842 The fp defaults to stdout. 843 844 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 845 @*/ 846 PetscErrorCode PetscMallocDumpLog(FILE *fp) 847 { 848 PetscInt i,j,n,dummy,*perm; 849 size_t *shortlength; 850 int *shortcount,err; 851 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 852 PetscBool match; 853 const char **shortfunction; 854 PetscLogDouble rss; 855 MPI_Status status; 856 PetscErrorCode ierr; 857 858 PetscFunctionBegin; 859 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 860 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 861 /* 862 Try to get the data printed in order by processor. This will only sometimes work 863 */ 864 err = fflush(fp); 865 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 866 867 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 868 if (rank) { 869 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 870 } 871 872 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()"); 873 874 if (!fp) fp = PETSC_STDOUT; 875 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 876 if (rss) { 877 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); 878 } else { 879 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); 880 } 881 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 882 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 883 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 884 for (i=0,n=0; i<PetscLogMalloc; i++) { 885 for (j=0; j<n; j++) { 886 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 887 if (match) { 888 shortlength[j] += PetscLogMallocLength[i]; 889 shortcount[j]++; 890 goto foundit; 891 } 892 } 893 shortfunction[n] = PetscLogMallocFunction[i]; 894 shortlength[n] = PetscLogMallocLength[i]; 895 shortcount[n] = 1; 896 n++; 897 foundit:; 898 } 899 900 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 901 for (i=0; i<n; i++) perm[i] = i; 902 ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 903 904 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 905 for (i=0; i<n; i++) { 906 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 907 } 908 free(perm); 909 free(shortlength); 910 free(shortcount); 911 free((char**)shortfunction); 912 err = fflush(fp); 913 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 914 if (rank != size-1) { 915 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 916 } 917 PetscFunctionReturn(0); 918 } 919 920 /* ---------------------------------------------------------------------------- */ 921 922 /*@ 923 PetscMallocDebug - Turns on/off debugging for the memory management routines. 924 925 Not Collective 926 927 Input Parameter: 928 . level - PETSC_TRUE or PETSC_FALSE 929 930 Level: intermediate 931 932 .seealso: CHKMEMQ(), PetscMallocValidate() 933 @*/ 934 PetscErrorCode PetscMallocDebug(PetscBool level) 935 { 936 PetscFunctionBegin; 937 TRdebugLevel = level; 938 PetscFunctionReturn(0); 939 } 940 941 /*@ 942 PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 943 944 Not Collective 945 946 Output Parameter: 947 . flg - PETSC_TRUE if any debugger 948 949 Level: intermediate 950 951 Note that by default, the debug version always does some debugging unless you run with -malloc no 952 953 954 .seealso: CHKMEMQ(), PetscMallocValidate() 955 @*/ 956 PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 957 { 958 PetscFunctionBegin; 959 if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 960 else *flg = PETSC_FALSE; 961 PetscFunctionReturn(0); 962 } 963