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