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