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 } 216 #endif 217 218 /* 219 Allow logging of all mallocs made 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 #undef __FUNCT__ 242 #define __FUNCT__ "PetscTrFreeDefault" 243 /* 244 PetscTrFreeDefault - Free with tracing. 245 246 Input Parameters: 247 . a - pointer to a block allocated with PetscTrMalloc 248 . lineno - line number where used. Use __LINE__ for this 249 . function - function calling routine. Use __FUNCT__ for this 250 . file - file name where used. Use __FILE__ for this 251 */ 252 PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[]) 253 { 254 char *a = (char*)aa; 255 TRSPACE *head; 256 char *ahead; 257 PetscErrorCode ierr; 258 PetscClassId *nend; 259 260 PetscFunctionBegin; 261 /* Do not try to handle empty blocks */ 262 if (!a) PetscFunctionReturn(0); 263 264 if (TRdebugLevel) { 265 ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr); 266 } 267 268 ahead = a; 269 a = a - sizeof(TrSPACE); 270 head = (TRSPACE*)a; 271 272 if (head->classid != CLASSID_VALUE) { 273 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 274 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 275 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 276 } 277 nend = (PetscClassId*)(ahead + head->size); 278 if (*nend != CLASSID_VALUE) { 279 if (*nend == ALREADY_FREED) { 280 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 281 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 282 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 283 (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 284 } else { 285 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 286 } 287 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 288 } else { 289 /* Damaged tail */ 290 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 291 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 292 (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 293 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 294 } 295 } 296 /* Mark the location freed */ 297 *nend = ALREADY_FREED; 298 /* Save location where freed. If we suspect the line number, mark as allocated location */ 299 if (line > 0 && line < 50000) { 300 head->lineno = line; 301 head->filename = file; 302 head->functionname = function; 303 } else { 304 head->lineno = -head->lineno; 305 } 306 /* zero out memory - helps to find some reuse of already freed memory */ 307 ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 308 309 TRallocated -= head->size; 310 TRfrags--; 311 if (head->prev) head->prev->next = head->next; 312 else TRhead = head->next; 313 314 if (head->next) head->next->prev = head->prev; 315 ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr); 316 PetscFunctionReturn(0); 317 } 318 319 320 #undef __FUNCT__ 321 #define __FUNCT__ "PetscMemoryView" 322 /*@C 323 PetscMemoryView - Shows the amount of memory currently being used 324 in a communicator. 325 326 Collective on PetscViewer 327 328 Input Parameter: 329 + viewer - the viewer that defines the communicator 330 - message - string printed before values 331 332 Options Database: 333 + -malloc - have PETSc track how much memory it has allocated 334 - -memory_view - during PetscFinalize() have this routine called 335 336 Level: intermediate 337 338 Concepts: memory usage 339 340 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage() 341 @*/ 342 PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[]) 343 { 344 PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax; 345 PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax; 346 PetscErrorCode ierr; 347 MPI_Comm comm; 348 349 PetscFunctionBegin; 350 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 351 ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 352 ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr); 353 ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 354 ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 355 if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 356 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 357 ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 358 if (resident && residentmax && allocated) { 359 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 360 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 361 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 362 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 363 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 364 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 365 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 366 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 367 ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 368 ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 369 ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 370 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); 371 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 372 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 373 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 374 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 375 } else if (resident && residentmax) { 376 ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 377 ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 378 ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 379 ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 380 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 381 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 382 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 383 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 384 } else if (resident && allocated) { 385 ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 386 ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 387 ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 388 ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 389 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 390 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 391 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 392 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 393 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 394 } else if (allocated) { 395 ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 396 ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 397 ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 398 ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 399 ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 400 ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr); 401 } else { 402 ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 403 } 404 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 405 PetscFunctionReturn(0); 406 } 407 408 #undef __FUNCT__ 409 #define __FUNCT__ "PetscMallocGetCurrentUsage" 410 /*@C 411 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 412 413 Not Collective 414 415 Output Parameters: 416 . space - number of bytes currently allocated 417 418 Level: intermediate 419 420 Concepts: memory usage 421 422 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 423 PetscMemoryGetMaximumUsage() 424 @*/ 425 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 426 { 427 PetscFunctionBegin; 428 *space = (PetscLogDouble) TRallocated; 429 PetscFunctionReturn(0); 430 } 431 432 #undef __FUNCT__ 433 #define __FUNCT__ "PetscMallocGetMaximumUsage" 434 /*@C 435 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 436 during this run. 437 438 Not Collective 439 440 Output Parameters: 441 . space - maximum number of bytes ever allocated at one time 442 443 Level: intermediate 444 445 Concepts: memory usage 446 447 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 448 PetscMemoryGetCurrentUsage() 449 @*/ 450 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 451 { 452 PetscFunctionBegin; 453 *space = (PetscLogDouble) TRMaxMem; 454 PetscFunctionReturn(0); 455 } 456 457 #if defined(PETSC_USE_DEBUG) 458 #undef __FUNCT__ 459 #define __FUNCT__ "PetscMallocGetStack" 460 /*@C 461 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 462 463 Collective on PETSC_COMM_WORLD 464 465 Input Parameter: 466 . ptr - the memory location 467 468 Output Paramter: 469 . stack - the stack indicating where the program allocated this memory 470 471 Level: intermediate 472 473 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 474 @*/ 475 PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 476 { 477 TRSPACE *head; 478 479 PetscFunctionBegin; 480 head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 481 *stack = &head->stack; 482 PetscFunctionReturn(0); 483 } 484 #else 485 #undef __FUNCT__ 486 #define __FUNCT__ "PetscMallocGetStack" 487 PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 488 { 489 PetscFunctionBegin; 490 *stack = NULL; 491 PetscFunctionReturn(0); 492 } 493 #endif 494 495 #undef __FUNCT__ 496 #define __FUNCT__ "PetscMallocDump" 497 /*@C 498 PetscMallocDump - Dumps the allocated memory blocks to a file. The information 499 printed is: size of space (in bytes), address of space, id of space, 500 file in which space was allocated, and line number at which it was 501 allocated. 502 503 Collective on PETSC_COMM_WORLD 504 505 Input Parameter: 506 . fp - file pointer. If fp is NULL, stdout is assumed. 507 508 Options Database Key: 509 . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 510 511 Level: intermediate 512 513 Fortran Note: 514 The calling sequence in Fortran is PetscMallocDump(integer ierr) 515 The fp defaults to stdout. 516 517 Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 518 has been freed. 519 520 Concepts: memory usage 521 Concepts: memory bleeding 522 Concepts: bleeding memory 523 524 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 525 @*/ 526 PetscErrorCode PetscMallocDump(FILE *fp) 527 { 528 TRSPACE *head; 529 PetscErrorCode ierr; 530 PetscMPIInt rank; 531 532 PetscFunctionBegin; 533 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 534 if (!fp) fp = PETSC_STDOUT; 535 if (TRallocated > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 536 head = TRhead; 537 while (head) { 538 fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 539 #if defined(PETSC_USE_DEBUG) 540 ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 541 #endif 542 head = head->next; 543 } 544 PetscFunctionReturn(0); 545 } 546 547 /* ---------------------------------------------------------------------------- */ 548 549 #undef __FUNCT__ 550 #define __FUNCT__ "PetscMallocSetDumpLog" 551 /*@C 552 PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 553 554 Not Collective 555 556 Options Database Key: 557 + -malloc_log <filename> - Activates PetscMallocDumpLog() 558 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 559 560 Level: advanced 561 562 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 563 @*/ 564 PetscErrorCode PetscMallocSetDumpLog(void) 565 { 566 PetscErrorCode ierr; 567 568 PetscFunctionBegin; 569 PetscLogMalloc = 0; 570 571 ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 572 PetscFunctionReturn(0); 573 } 574 575 #undef __FUNCT__ 576 #define __FUNCT__ "PetscMallocSetDumpLogThreshold" 577 /*@C 578 PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 579 580 Not Collective 581 582 Input Arguments: 583 . logmin - minimum allocation size to log, or PETSC_DEFAULT 584 585 Options Database Key: 586 + -malloc_log <filename> - Activates PetscMallocDumpLog() 587 - -malloc_log_threshold <min> - Activates logging and sets a minimum size 588 589 Level: advanced 590 591 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 592 @*/ 593 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 594 { 595 PetscErrorCode ierr; 596 597 PetscFunctionBegin; 598 ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 599 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 600 PetscLogMallocThreshold = (size_t)logmin; 601 PetscFunctionReturn(0); 602 } 603 604 #undef __FUNCT__ 605 #define __FUNCT__ "PetscMallocGetDumpLog" 606 /*@C 607 PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 608 609 Not Collective 610 611 Output Arguments 612 . logging - PETSC_TRUE if logging is active 613 614 Options Database Key: 615 . -malloc_log - Activates PetscMallocDumpLog() 616 617 Level: advanced 618 619 .seealso: PetscMallocDump(), PetscMallocDumpLog() 620 @*/ 621 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 622 { 623 624 PetscFunctionBegin; 625 *logging = (PetscBool)(PetscLogMalloc >= 0); 626 PetscFunctionReturn(0); 627 } 628 629 #undef __FUNCT__ 630 #define __FUNCT__ "PetscMallocDumpLog" 631 /*@C 632 PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 633 PetscMemoryGetMaximumUsage() 634 635 Collective on PETSC_COMM_WORLD 636 637 Input Parameter: 638 . fp - file pointer; or NULL 639 640 Options Database Key: 641 . -malloc_log - Activates PetscMallocDumpLog() 642 643 Level: advanced 644 645 Fortran Note: 646 The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 647 The fp defaults to stdout. 648 649 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 650 @*/ 651 PetscErrorCode PetscMallocDumpLog(FILE *fp) 652 { 653 PetscInt i,j,n,dummy,*perm; 654 size_t *shortlength; 655 int *shortcount,err; 656 PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 657 PetscBool match; 658 const char **shortfunction; 659 PetscLogDouble rss; 660 MPI_Status status; 661 PetscErrorCode ierr; 662 663 PetscFunctionBegin; 664 ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 665 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 666 /* 667 Try to get the data printed in order by processor. This will only sometimes work 668 */ 669 err = fflush(fp); 670 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 671 672 ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 673 if (rank) { 674 ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 675 } 676 677 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()"); 678 679 if (!fp) fp = PETSC_STDOUT; 680 ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 681 if (rss) { 682 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); 683 } else { 684 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); 685 } 686 shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 687 shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 688 shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 689 for (i=0,n=0; i<PetscLogMalloc; i++) { 690 for (j=0; j<n; j++) { 691 ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 692 if (match) { 693 shortlength[j] += PetscLogMallocLength[i]; 694 shortcount[j]++; 695 goto foundit; 696 } 697 } 698 shortfunction[n] = PetscLogMallocFunction[i]; 699 shortlength[n] = PetscLogMallocLength[i]; 700 shortcount[n] = 1; 701 n++; 702 foundit:; 703 } 704 705 perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 706 for (i=0; i<n; i++) perm[i] = i; 707 ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 708 709 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 710 for (i=0; i<n; i++) { 711 ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 712 } 713 free(perm); 714 free(shortlength); 715 free(shortcount); 716 free((char**)shortfunction); 717 err = fflush(fp); 718 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 719 if (rank != size-1) { 720 ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 721 } 722 PetscFunctionReturn(0); 723 } 724 725 /* ---------------------------------------------------------------------------- */ 726 727 #undef __FUNCT__ 728 #define __FUNCT__ "PetscMallocDebug" 729 /*@C 730 PetscMallocDebug - Turns on/off debugging for the memory management routines. 731 732 Not Collective 733 734 Input Parameter: 735 . level - PETSC_TRUE or PETSC_FALSE 736 737 Level: intermediate 738 739 .seealso: CHKMEMQ(), PetscMallocValidate() 740 @*/ 741 PetscErrorCode PetscMallocDebug(PetscBool level) 742 { 743 PetscFunctionBegin; 744 TRdebugLevel = level; 745 PetscFunctionReturn(0); 746 } 747 748 #undef __FUNCT__ 749 #define __FUNCT__ "PetscMallocGetDebug" 750 /*@C 751 PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 752 753 Not Collective 754 755 Output Parameter: 756 . flg - PETSC_TRUE if any debugger 757 758 Level: intermediate 759 760 Note that by default, the debug version always does some debugging unless you run with -malloc no 761 762 763 .seealso: CHKMEMQ(), PetscMallocValidate() 764 @*/ 765 PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 766 { 767 PetscFunctionBegin; 768 if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 769 else *flg = PETSC_FALSE; 770 PetscFunctionReturn(0); 771 } 772