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