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 TRdebugIinitializenan= 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 PetscMallocSetDebug() 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 && TRdebugIinitializenan) { 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 = 0x7F800002; 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(), 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 Parameter: 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 - -log_view_memory - view the memory usage also with the -log_view option 729 730 Level: advanced 731 732 Notes: Must be called after PetscMallocSetDebug() 733 734 Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available 735 736 .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet() 737 @*/ 738 PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) 739 { 740 PetscErrorCode ierr; 741 742 PetscFunctionBegin; 743 PetscLogMalloc = 0; 744 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 745 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 746 PetscLogMallocThreshold = (size_t)logmin; 747 PetscFunctionReturn(0); 748 } 749 750 /*@ 751 PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged 752 753 Not Collective 754 755 Output Arguments 756 . logging - PETSC_TRUE if logging is active 757 758 Options Database Key: 759 . -malloc_view <optional filename> - Activates PetscMallocView() 760 761 Level: advanced 762 763 .seealso: PetscMallocDump(), PetscMallocView() 764 @*/ 765 PetscErrorCode PetscMallocViewGet(PetscBool *logging) 766 { 767 768 PetscFunctionBegin; 769 *logging = (PetscBool)(PetscLogMalloc >= 0); 770 PetscFunctionReturn(0); 771 } 772 773 /*@C 774 PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls 775 PetscMemoryGetMaximumUsage() 776 777 Not Collective 778 779 Input Parameter: 780 . fp - file pointer; or NULL 781 782 Options Database Key: 783 . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize() 784 785 Level: advanced 786 787 Fortran Note: 788 The calling sequence in Fortran is PetscMallocView(integer ierr) 789 The fp defaults to stdout. 790 791 Notes: 792 PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated 793 794 PetscMemoryView() gives a brief summary of current memory usage 795 796 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView() 797 @*/ 798 PetscErrorCode PetscMallocView(FILE *fp) 799 { 800 PetscInt i,j,n,*perm; 801 size_t *shortlength; 802 int *shortcount,err; 803 PetscMPIInt rank; 804 PetscBool match; 805 const char **shortfunction; 806 PetscLogDouble rss; 807 PetscErrorCode ierr; 808 809 PetscFunctionBegin; 810 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 811 err = fflush(fp); 812 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 813 814 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_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 815 816 if (!fp) fp = PETSC_STDOUT; 817 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 818 if (rss) { 819 (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss); 820 } else { 821 (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem); 822 } 823 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 824 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 825 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 826 for (i=0,n=0; i<PetscLogMalloc; i++) { 827 for (j=0; j<n; j++) { 828 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 829 if (match) { 830 shortlength[j] += PetscLogMallocLength[i]; 831 shortcount[j]++; 832 goto foundit; 833 } 834 } 835 shortfunction[n] = PetscLogMallocFunction[i]; 836 shortlength[n] = PetscLogMallocLength[i]; 837 shortcount[n] = 1; 838 n++; 839 foundit:; 840 } 841 842 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 843 for (i=0; i<n; i++) perm[i] = i; 844 ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 845 846 (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank); 847 for (i=0; i<n; i++) { 848 (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]); 849 } 850 free(perm); 851 free(shortlength); 852 free(shortcount); 853 free((char**)shortfunction); 854 err = fflush(fp); 855 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 856 PetscFunctionReturn(0); 857 } 858 859 /* ---------------------------------------------------------------------------- */ 860 861 /*@ 862 PetscMallocSetDebug - Set's PETSc memory debugging 863 864 Not Collective 865 866 Input Parameter: 867 + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree() 868 - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays 869 870 Options Database: 871 + -malloc_debug <true or false> - turns on or off debugging 872 . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored 873 . -malloc_view_threshold t - log only allocations larger than t 874 . -malloc_dump <filename> - print a list of all memory that has not been freed 875 . -malloc no - (deprecated) same as -malloc_debug no 876 - -malloc_log - (deprecated) same as -malloc_view 877 878 Level: developer 879 880 Notes: This is called in PetscInitialize() and should not be called elsewhere 881 882 .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug() 883 @*/ 884 PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) 885 { 886 PetscErrorCode ierr; 887 888 PetscFunctionBegin; 889 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()"); 890 ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);CHKERRQ(ierr); 891 892 TRallocated = 0; 893 TRfrags = 0; 894 TRhead = NULL; 895 TRid = 0; 896 TRdebugLevel = eachcall; 897 TRMaxMem = 0; 898 PetscLogMallocMax = 10000; 899 PetscLogMalloc = -1; 900 TRdebugIinitializenan = initializenan; 901 PetscFunctionReturn(0); 902 } 903 904 /*@ 905 PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 906 907 Not Collective 908 909 Output Parameters: 910 + basic - doing basic debugging 911 . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree() 912 - initializenan - initializes memory with NaN 913 914 Level: intermediate 915 916 Notes: 917 By default, the debug version always does some debugging unless you run with -malloc_debug no 918 919 .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug() 920 @*/ 921 PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) 922 { 923 PetscFunctionBegin; 924 if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 925 if (eachcall) *eachcall = TRdebugLevel; 926 if (initializenan) *initializenan = TRdebugIinitializenan; 927 PetscFunctionReturn(0); 928 } 929