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