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 /* Realloc to zero = free */ 356 if (!len) { 357 ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr); 358 *result = NULL; 359 PetscFunctionReturn(0); 360 } 361 362 if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);} 363 364 ahead = a; 365 a = a - sizeof(TrSPACE); 366 head = (TRSPACE *) a; 367 inew = a; 368 369 if (head->classid != CLASSID_VALUE) { 370 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 371 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 372 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 373 } 374 nend = (PetscClassId *)(ahead + head->size); 375 if (*nend != CLASSID_VALUE) { 376 if (*nend == ALREADY_FREED) { 377 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 378 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 379 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 380 (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 381 } else { 382 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 383 } 384 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 385 } else { 386 /* Damaged tail */ 387 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 388 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 389 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 390 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 391 } 392 } 393 394 TRallocated -= head->size; 395 TRfrags--; 396 if (head->prev) head->prev->next = head->next; 397 else TRhead = head->next; 398 if (head->next) head->next->prev = head->prev; 399 400 nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 401 ierr = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 402 403 head = (TRSPACE*)inew; 404 inew += sizeof(TrSPACE); 405 406 if (TRhead) TRhead->prev = head; 407 head->next = TRhead; 408 TRhead = head; 409 head->prev = NULL; 410 head->size = nsize; 411 head->id = TRid; 412 head->lineno = lineno; 413 414 head->filename = filename; 415 head->functionname = function; 416 head->classid = CLASSID_VALUE; 417 *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 418 419 TRallocated += nsize; 420 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 421 TRfrags++; 422 423 #if defined(PETSC_USE_DEBUG) 424 if (PetscStackActive()) { 425 ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 426 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 427 head->stack.line[head->stack.currentsize-2] = lineno; 428 } else { 429 head->stack.currentsize = 0; 430 } 431 #endif 432 433 /* 434 Allow logging of all mallocs made 435 */ 436 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 437 if (!PetscLogMalloc) { 438 PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 439 if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 440 441 PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 442 if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 443 444 PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 445 if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 446 } 447 PetscLogMallocLength[PetscLogMalloc] = nsize; 448 PetscLogMallocFile[PetscLogMalloc] = filename; 449 PetscLogMallocFunction[PetscLogMalloc++] = function; 450 } 451 *result = (void*)inew; 452 PetscFunctionReturn(0); 453 } 454 455 456 #undef __FUNCT__ 457 #define __FUNCT__ "PetscMemoryView" 458 /*@C 459 PetscMemoryView - Shows the amount of memory currently being used 460 in a communicator. 461 462 Collective on PetscViewer 463 464 Input Parameter: 465 + viewer - the viewer that defines the communicator 466 - message - string printed before values 467 468 Options Database: 469 + -malloc - have PETSc track how much memory it has allocated 470 - -memory_view - during PetscFinalize() have this routine called 471 472 Level: intermediate 473 474 Concepts: memory usage 475 476 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage() 477 @*/ 478 PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[]) 479 { 480 PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax; 481 PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax; 482 PetscErrorCode ierr; 483 MPI_Comm comm; 484 485 PetscFunctionBegin; 486 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 487 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 488 ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr); 489 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 490 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 491 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 492 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 493 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 494 if (resident && residentmax && allocated) { 495 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 496 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 497 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 498 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 499 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 500 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 501 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 502 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 503 ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 504 ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 505 ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 506 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); 507 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 508 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 509 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 510 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 511 } else if (resident && residentmax) { 512 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 513 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 514 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 515 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 516 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 517 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 518 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 519 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 520 } else if (resident && allocated) { 521 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 522 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 523 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 524 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 525 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 526 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 527 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 528 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 529 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 530 } else if (allocated) { 531 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 532 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 533 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 534 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 535 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 536 ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr); 537 } else { 538 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 539 } 540 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 541 PetscFunctionReturn(0); 542 } 543 544 #undef __FUNCT__ 545 #define __FUNCT__ "PetscMallocGetCurrentUsage" 546 /*@C 547 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 548 549 Not Collective 550 551 Output Parameters: 552 . space - number of bytes currently allocated 553 554 Level: intermediate 555 556 Concepts: memory usage 557 558 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 559 PetscMemoryGetMaximumUsage() 560 @*/ 561 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 562 { 563 PetscFunctionBegin; 564 *space = (PetscLogDouble) TRallocated; 565 PetscFunctionReturn(0); 566 } 567 568 #undef __FUNCT__ 569 #define __FUNCT__ "PetscMallocGetMaximumUsage" 570 /*@C 571 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 572 during this run. 573 574 Not Collective 575 576 Output Parameters: 577 . space - maximum number of bytes ever allocated at one time 578 579 Level: intermediate 580 581 Concepts: memory usage 582 583 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 584 PetscMemoryGetCurrentUsage() 585 @*/ 586 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 587 { 588 PetscFunctionBegin; 589 *space = (PetscLogDouble) TRMaxMem; 590 PetscFunctionReturn(0); 591 } 592 593 #if defined(PETSC_USE_DEBUG) 594 #undef __FUNCT__ 595 #define __FUNCT__ "PetscMallocGetStack" 596 /*@C 597 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 598 599 Collective on PETSC_COMM_WORLD 600 601 Input Parameter: 602 . ptr - the memory location 603 604 Output Paramter: 605 . stack - the stack indicating where the program allocated this memory 606 607 Level: intermediate 608 609 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 610 @*/ 611 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 612 { 613 TRSPACE *head; 614 615 PetscFunctionBegin; 616 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 617 *stack = &head->stack; 618 PetscFunctionReturn(0); 619 } 620 #else 621 #undef __FUNCT__ 622 #define __FUNCT__ "PetscMallocGetStack" 623 PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 624 { 625 PetscFunctionBegin; 626 *stack = NULL; 627 PetscFunctionReturn(0); 628 } 629 #endif 630 631 #undef __FUNCT__ 632 #define __FUNCT__ "PetscMallocDump" 633 /*@C 634 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 635 printed is: size of space (in bytes), address of space, id of space, 636 file in which space was allocated, and line number at which it was 637 allocated. 638 639 Collective on PETSC_COMM_WORLD 640 641 Input Parameter: 642 . fp - file pointer. If fp is NULL, stdout is assumed. 643 644 Options Database Key: 645 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 646 647 Level: intermediate 648 649 Fortran Note: 650 The calling sequence in Fortran is PetscMallocDump(integer ierr) 651 The fp defaults to stdout. 652 653 Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 654 has been freed. 655 656 Concepts: memory usage 657 Concepts: memory bleeding 658 Concepts: bleeding memory 659 660 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 661 @*/ 662 PetscErrorCode PetscMallocDump(FILE *fp) 663 { 664 TRSPACE *head; 665 PetscInt libAlloc = 0; 666 PetscErrorCode ierr; 667 PetscMPIInt rank; 668 669 PetscFunctionBegin; 670 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 671 if (!fp) fp = PETSC_STDOUT; 672 head = TRhead; 673 while (head) { 674 PetscBool isLib; 675 676 ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 677 libAlloc += head->size; 678 head = head->next; 679 } 680 if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 681 head = TRhead; 682 while (head) { 683 PetscBool isLib; 684 685 ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 686 if (!isLib) { 687 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 688 #if defined(PETSC_USE_DEBUG) 689 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 690 #endif 691 } 692 head = head->next; 693 } 694 PetscFunctionReturn(0); 695 } 696 697 /* ---------------------------------------------------------------------------- */ 698 699 #undef __FUNCT__ 700 #define __FUNCT__ "PetscMallocSetDumpLog" 701 /*@C 702 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 703 704 Not Collective 705 706 Options Database Key: 707 + -malloc_log <filename> - Activates PetscMallocDumpLog() 708 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 709 710 Level: advanced 711 712 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 713 @*/ 714 PetscErrorCode PetscMallocSetDumpLog(void) 715 { 716 PetscErrorCode ierr; 717 718 PetscFunctionBegin; 719 PetscLogMalloc = 0; 720 721 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 722 PetscFunctionReturn(0); 723 } 724 725 #undef __FUNCT__ 726 #define __FUNCT__ "PetscMallocSetDumpLogThreshold" 727 /*@C 728 PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 729 730 Not Collective 731 732 Input Arguments: 733 . logmin - minimum allocation size to log, or PETSC_DEFAULT 734 735 Options Database Key: 736 + -malloc_log <filename> - Activates PetscMallocDumpLog() 737 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 738 739 Level: advanced 740 741 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 742 @*/ 743 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 744 { 745 PetscErrorCode ierr; 746 747 PetscFunctionBegin; 748 ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 749 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 750 PetscLogMallocThreshold = (size_t)logmin; 751 PetscFunctionReturn(0); 752 } 753 754 #undef __FUNCT__ 755 #define __FUNCT__ "PetscMallocGetDumpLog" 756 /*@C 757 PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 758 759 Not Collective 760 761 Output Arguments 762 . logging - PETSC_TRUE if logging is active 763 764 Options Database Key: 765 . -malloc_log - Activates PetscMallocDumpLog() 766 767 Level: advanced 768 769 .seealso: PetscMallocDump(), PetscMallocDumpLog() 770 @*/ 771 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 772 { 773 774 PetscFunctionBegin; 775 *logging = (PetscBool)(PetscLogMalloc >= 0); 776 PetscFunctionReturn(0); 777 } 778 779 #undef __FUNCT__ 780 #define __FUNCT__ "PetscMallocDumpLog" 781 /*@C 782 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 783 PetscMemoryGetMaximumUsage() 784 785 Collective on PETSC_COMM_WORLD 786 787 Input Parameter: 788 . fp - file pointer; or NULL 789 790 Options Database Key: 791 . -malloc_log - Activates PetscMallocDumpLog() 792 793 Level: advanced 794 795 Fortran Note: 796 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 797 The fp defaults to stdout. 798 799 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 800 @*/ 801 PetscErrorCode PetscMallocDumpLog(FILE *fp) 802 { 803 PetscInt i,j,n,dummy,*perm; 804 size_t *shortlength; 805 int *shortcount,err; 806 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 807 PetscBool match; 808 const char **shortfunction; 809 PetscLogDouble rss; 810 MPI_Status status; 811 PetscErrorCode ierr; 812 813 PetscFunctionBegin; 814 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 815 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 816 /* 817 Try to get the data printed in order by processor. This will only sometimes work 818 */ 819 err = fflush(fp); 820 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 821 822 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 823 if (rank) { 824 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 825 } 826 827 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()"); 828 829 if (!fp) fp = PETSC_STDOUT; 830 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 831 if (rss) { 832 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); 833 } else { 834 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); 835 } 836 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 837 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 838 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 839 for (i=0,n=0; i<PetscLogMalloc; i++) { 840 for (j=0; j<n; j++) { 841 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 842 if (match) { 843 shortlength[j] += PetscLogMallocLength[i]; 844 shortcount[j]++; 845 goto foundit; 846 } 847 } 848 shortfunction[n] = PetscLogMallocFunction[i]; 849 shortlength[n] = PetscLogMallocLength[i]; 850 shortcount[n] = 1; 851 n++; 852 foundit:; 853 } 854 855 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 856 for (i=0; i<n; i++) perm[i] = i; 857 ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 858 859 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 860 for (i=0; i<n; i++) { 861 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 862 } 863 free(perm); 864 free(shortlength); 865 free(shortcount); 866 free((char**)shortfunction); 867 err = fflush(fp); 868 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 869 if (rank != size-1) { 870 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 871 } 872 PetscFunctionReturn(0); 873 } 874 875 /* ---------------------------------------------------------------------------- */ 876 877 #undef __FUNCT__ 878 #define __FUNCT__ "PetscMallocDebug" 879 /*@C 880 PetscMallocDebug - Turns on/off debugging for the memory management routines. 881 882 Not Collective 883 884 Input Parameter: 885 . level - PETSC_TRUE or PETSC_FALSE 886 887 Level: intermediate 888 889 .seealso: CHKMEMQ(), PetscMallocValidate() 890 @*/ 891 PetscErrorCode PetscMallocDebug(PetscBool level) 892 { 893 PetscFunctionBegin; 894 TRdebugLevel = level; 895 PetscFunctionReturn(0); 896 } 897 898 #undef __FUNCT__ 899 #define __FUNCT__ "PetscMallocGetDebug" 900 /*@C 901 PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 902 903 Not Collective 904 905 Output Parameter: 906 . flg - PETSC_TRUE if any debugger 907 908 Level: intermediate 909 910 Note that by default, the debug version always does some debugging unless you run with -malloc no 911 912 913 .seealso: CHKMEMQ(), PetscMallocValidate() 914 @*/ 915 PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 916 { 917 PetscFunctionBegin; 918 if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 919 else *flg = PETSC_FALSE; 920 PetscFunctionReturn(0); 921 } 922