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