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