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