1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay Code that allows a user to dictate what malloc() PETSc uses. 3e5c89e4eSSatish Balay */ 4c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 5ba282f50SJed Brown #include <stdarg.h> 6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 7e5c89e4eSSatish Balay #include <malloc.h> 8e5c89e4eSSatish Balay #endif 9de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 10ca8c994eSHong Zhang #include <errno.h> 11de1d6c17SHong Zhang #include <memkind.h> 12e3acc61dSHong Zhang typedef enum {PETSC_MK_DEFAULT=0,PETSC_MK_HBW_PREFERRED=1} PetscMemkindType; 13e3acc61dSHong Zhang PetscMemkindType currentmktype = PETSC_MK_HBW_PREFERRED; 14e3acc61dSHong Zhang PetscMemkindType previousmktype = PETSC_MK_HBW_PREFERRED; 15de1d6c17SHong Zhang #endif 16e5c89e4eSSatish Balay /* 17e5c89e4eSSatish Balay We want to make sure that all mallocs of double or complex numbers are complex aligned. 18e5c89e4eSSatish Balay 1) on systems with memalign() we call that routine to get an aligned memory location 19e5c89e4eSSatish Balay 2) on systems without memalign() we 20e5c89e4eSSatish Balay - allocate one sizeof(PetscScalar) extra space 21e5c89e4eSSatish Balay - we shift the pointer up slightly if needed to get PetscScalar aligned 220700a824SBarry Smith - if shifted we store at ptr[-1] the amount of shift (plus a classid) 23e5c89e4eSSatish Balay */ 240700a824SBarry Smith #define SHIFT_CLASSID 456123 25e5c89e4eSSatish Balay 26071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t mem,PetscBool clear,int line,const char func[],const char file[],void **result) 27e5c89e4eSSatish Balay { 28071fcb05SBarry Smith PetscErrorCode ierr; 29*2da392ccSBarry Smith #if defined(PETSC_HAVE_MEMKIND) 30*2da392ccSBarry Smith int err; 31*2da392ccSBarry Smith #endif 32071fcb05SBarry Smith 33f0ba7cfcSLisandro Dalcin if (!mem) {*result = NULL; return 0;} 34fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 35fc2a7144SHong Zhang { 36*2da392ccSBarry Smith if (!currentmktype) err = memkind_posix_memalign(MEMKIND_DEFAULT,result,PETSC_MEMALIGN,mem); 37*2da392ccSBarry Smith else err = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,result,PETSC_MEMALIGN,mem); 38*2da392ccSBarry Smith if (err == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 39*2da392ccSBarry Smith if (err == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 40071fcb05SBarry Smith if (clear) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 41fc2a7144SHong Zhang } 42fc2a7144SHong Zhang #else 43e5c89e4eSSatish Balay # if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 44071fcb05SBarry Smith if (clear) { 45071fcb05SBarry Smith *result = calloc(1+mem/sizeof(int),sizeof(int)); 46071fcb05SBarry Smith } else { 47e5c89e4eSSatish Balay *result = malloc(mem); 48071fcb05SBarry Smith } 49071fcb05SBarry Smith if (PetscLogMemory) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 50071fcb05SBarry Smith 51e5c89e4eSSatish Balay # elif defined(PETSC_HAVE_MEMALIGN) 52e5c89e4eSSatish Balay *result = memalign(PETSC_MEMALIGN,mem); 53071fcb05SBarry Smith if (clear || PetscLogMemory) { 54071fcb05SBarry Smith ierr = PetscMemzero(*result,mem);CHKERRQ(ierr); 55071fcb05SBarry Smith } 56e5c89e4eSSatish Balay # else 57e5c89e4eSSatish Balay { 58071fcb05SBarry Smith int *ptr; 59e5c89e4eSSatish Balay /* 60e5c89e4eSSatish Balay malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 61e5c89e4eSSatish Balay */ 62071fcb05SBarry Smith if (clear) { 63071fcb05SBarry Smith ptr = (int*)calloc(1+(mem + 2*PETSC_MEMALIGN)/sizeof(int),sizeof(int)); 64071fcb05SBarry Smith } else { 65071fcb05SBarry Smith ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN); 66071fcb05SBarry Smith } 67e5c89e4eSSatish Balay if (ptr) { 68f0ba7cfcSLisandro Dalcin int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 69e5c89e4eSSatish Balay shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 700700a824SBarry Smith ptr[shift-1] = shift + SHIFT_CLASSID; 71e5c89e4eSSatish Balay ptr += shift; 72e5c89e4eSSatish Balay *result = (void*)ptr; 73071fcb05SBarry Smith if (PetscLogMemory) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 74e5c89e4eSSatish Balay } else { 75f0ba7cfcSLisandro Dalcin *result = NULL; 76e5c89e4eSSatish Balay } 77e5c89e4eSSatish Balay } 78e5c89e4eSSatish Balay # endif 79fc2a7144SHong Zhang #endif 80071fcb05SBarry Smith 81f0ba7cfcSLisandro Dalcin if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 82e5c89e4eSSatish Balay return 0; 83e5c89e4eSSatish Balay } 84e5c89e4eSSatish Balay 8595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[]) 86e5c89e4eSSatish Balay { 87f0ba7cfcSLisandro Dalcin if (!ptr) return 0; 88fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 89fc2a7144SHong Zhang memkind_free(0,ptr); /* specify the kind to 0 so that memkind will look up for the right type */ 90fc2a7144SHong Zhang #else 91e5c89e4eSSatish Balay # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 92f0ba7cfcSLisandro Dalcin { 93e5c89e4eSSatish Balay /* 94e5c89e4eSSatish Balay Previous int tells us how many ints the pointer has been shifted from 95e5c89e4eSSatish Balay the original address provided by the system malloc(). 96e5c89e4eSSatish Balay */ 97f0ba7cfcSLisandro Dalcin int shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 98efca3c55SSatish Balay if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 99efca3c55SSatish Balay if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 100e5c89e4eSSatish Balay ptr = (void*)(((int*)ptr) - shift); 101e5c89e4eSSatish Balay } 102f0ba7cfcSLisandro Dalcin # endif 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay # if defined(PETSC_HAVE_FREE_RETURN_INT) 105e5c89e4eSSatish Balay int err = free(ptr); 106efca3c55SSatish Balay if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 107e5c89e4eSSatish Balay # else 108e5c89e4eSSatish Balay free(ptr); 109e5c89e4eSSatish Balay # endif 110fc2a7144SHong Zhang #endif 111e5c89e4eSSatish Balay return 0; 112e5c89e4eSSatish Balay } 113e5c89e4eSSatish Balay 11495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result) 1153221ece2SMatthew G. Knepley { 116c22f1541SToby Isaac PetscErrorCode ierr; 117c22f1541SToby Isaac 118c22f1541SToby Isaac if (!mem) { 119c22f1541SToby Isaac ierr = PetscFreeAlign(*result, line, func, file); 120c22f1541SToby Isaac if (ierr) return ierr; 121c22f1541SToby Isaac *result = NULL; 122c22f1541SToby Isaac return 0; 123c22f1541SToby Isaac } 124fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 125fc2a7144SHong Zhang if (!currentmktype) *result = memkind_realloc(MEMKIND_DEFAULT,*result,mem); 126e3acc61dSHong Zhang else *result = memkind_realloc(MEMKIND_HBW_PREFERRED,*result,mem); 127fc2a7144SHong Zhang #else 1283221ece2SMatthew G. Knepley # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 1293221ece2SMatthew G. Knepley { 1303221ece2SMatthew G. Knepley /* 1313221ece2SMatthew G. Knepley Previous int tells us how many ints the pointer has been shifted from 1323221ece2SMatthew G. Knepley the original address provided by the system malloc(). 1333221ece2SMatthew G. Knepley */ 1343221ece2SMatthew G. Knepley int shift = *(((int*)*result)-1) - SHIFT_CLASSID; 1353221ece2SMatthew G. Knepley if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 1363221ece2SMatthew G. Knepley if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 1373221ece2SMatthew G. Knepley *result = (void*)(((int*)*result) - shift); 1383221ece2SMatthew G. Knepley } 1393221ece2SMatthew G. Knepley # endif 1403221ece2SMatthew G. Knepley 141c22f1541SToby Isaac # if (defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) || defined(PETSC_HAVE_MEMALIGN) 14241605b92SBarry Smith *result = realloc(*result, mem); 1433221ece2SMatthew G. Knepley # else 1443221ece2SMatthew G. Knepley { 1453221ece2SMatthew G. Knepley /* 1463221ece2SMatthew G. Knepley malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 1473221ece2SMatthew G. Knepley */ 1483221ece2SMatthew G. Knepley int *ptr = (int *) realloc(*result, mem + 2*PETSC_MEMALIGN); 1493221ece2SMatthew G. Knepley if (ptr) { 1503221ece2SMatthew G. Knepley int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 1513221ece2SMatthew G. Knepley shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 1523221ece2SMatthew G. Knepley ptr[shift-1] = shift + SHIFT_CLASSID; 1533221ece2SMatthew G. Knepley ptr += shift; 1543221ece2SMatthew G. Knepley *result = (void*)ptr; 1553221ece2SMatthew G. Knepley } else { 1563221ece2SMatthew G. Knepley *result = NULL; 1573221ece2SMatthew G. Knepley } 1583221ece2SMatthew G. Knepley } 1593221ece2SMatthew G. Knepley # endif 160fc2a7144SHong Zhang #endif 1613221ece2SMatthew G. Knepley if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 162c22f1541SToby Isaac #if defined(PETSC_HAVE_MEMALIGN) 163c22f1541SToby Isaac /* There are no standard guarantees that realloc() maintains the alignment of memalign(), so I think we have to 164c22f1541SToby Isaac * realloc and, if the alignment is wrong, malloc/copy/free. */ 165c22f1541SToby Isaac if (((size_t) (*result)) % PETSC_MEMALIGN) { 166c22f1541SToby Isaac void *newResult; 167fc2a7144SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 168fc2a7144SHong Zhang { 169*2da392ccSBarry Smith int err; 170*2da392ccSBarry Smith if (!currentmktype) err = memkind_posix_memalign(MEMKIND_DEFAULT,&newResult,PETSC_MEMALIGN,mem); 171*2da392ccSBarry Smith else err = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,&newResult,PETSC_MEMALIGN,mem); 172*2da392ccSBarry Smith if (err == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 173*2da392ccSBarry Smith if (err == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 174fc2a7144SHong Zhang } 175fc2a7144SHong Zhang # else 176c22f1541SToby Isaac newResult = memalign(PETSC_MEMALIGN,mem); 177fc2a7144SHong Zhang # endif 178c22f1541SToby Isaac if (!newResult) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 179c22f1541SToby Isaac ierr = PetscMemcpy(newResult,*result,mem); 180c22f1541SToby Isaac if (ierr) return ierr; 181c22f1541SToby Isaac # if defined(PETSC_HAVE_FREE_RETURN_INT) 182c22f1541SToby Isaac { 183c22f1541SToby Isaac int err = free(*result); 184c22f1541SToby Isaac if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 185c22f1541SToby Isaac } 186c22f1541SToby Isaac # else 187de1d6c17SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 188de1d6c17SHong Zhang memkind_free(0,*result); 189de1d6c17SHong Zhang # else 190c22f1541SToby Isaac free(*result); 191c22f1541SToby Isaac # endif 192de1d6c17SHong Zhang # endif 193c22f1541SToby Isaac *result = newResult; 194c22f1541SToby Isaac } 195c22f1541SToby Isaac #endif 1963221ece2SMatthew G. Knepley return 0; 1973221ece2SMatthew G. Knepley } 1983221ece2SMatthew G. Knepley 199071fcb05SBarry Smith PetscErrorCode (*PetscTrMalloc)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign; 200efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 2013221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 202e5c89e4eSSatish Balay 20395c0884eSLisandro Dalcin PETSC_INTERN PetscBool petscsetmallocvisited; 204ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE; 205e5c89e4eSSatish Balay 206e5c89e4eSSatish Balay /*@C 2071d1a0024SBarry Smith PetscMallocSet - Sets the routines used to do mallocs and frees. 208e5c89e4eSSatish Balay This routine MUST be called before PetscInitialize() and may be 209e5c89e4eSSatish Balay called only once. 210e5c89e4eSSatish Balay 211e5c89e4eSSatish Balay Not Collective 212e5c89e4eSSatish Balay 213e5c89e4eSSatish Balay Input Parameters: 21492f119d6SBarry Smith + imalloc - the routine that provides the malloc (also provides calloc(), which is used depends on the second argument) 21592f119d6SBarry Smith . ifree - the routine that provides the free 21692f119d6SBarry Smith - iralloc - the routine that provides the realloc 217e5c89e4eSSatish Balay 218e5c89e4eSSatish Balay Level: developer 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay @*/ 221071fcb05SBarry Smith PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,PetscBool,int,const char[],const char[],void**), 22292f119d6SBarry Smith PetscErrorCode (*ifree)(void*,int,const char[],const char[]), 22392f119d6SBarry Smith PetscErrorCode (*iralloc)(size_t, int, const char[], const char[], void **)) 224e5c89e4eSSatish Balay { 225e5c89e4eSSatish Balay PetscFunctionBegin; 226e32f2f54SBarry Smith if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 227e5c89e4eSSatish Balay PetscTrMalloc = imalloc; 228e5c89e4eSSatish Balay PetscTrFree = ifree; 22992f119d6SBarry Smith PetscTrRealloc = iralloc; 230e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_TRUE; 231e5c89e4eSSatish Balay PetscFunctionReturn(0); 232e5c89e4eSSatish Balay } 233e5c89e4eSSatish Balay 234e5c89e4eSSatish Balay /*@C 23592f119d6SBarry Smith PetscMallocClear - Resets the routines used to do mallocs and frees to the defaults. 236e5c89e4eSSatish Balay 237e5c89e4eSSatish Balay Not Collective 238e5c89e4eSSatish Balay 239e5c89e4eSSatish Balay Level: developer 240e5c89e4eSSatish Balay 241e5c89e4eSSatish Balay Notes: 242e5c89e4eSSatish Balay In general one should never run a PETSc program with different malloc() and 243e5c89e4eSSatish Balay free() settings for different parts; this is because one NEVER wants to 244e5c89e4eSSatish Balay free() an address that was malloced by a different memory management system 245e5c89e4eSSatish Balay 24692f119d6SBarry Smith Called in PetscFinalize() so that if PetscInitialize() is called again it starts with a fresh slate of allocation information 24792f119d6SBarry Smith 248e5c89e4eSSatish Balay @*/ 2497087cfbeSBarry Smith PetscErrorCode PetscMallocClear(void) 250e5c89e4eSSatish Balay { 251e5c89e4eSSatish Balay PetscFunctionBegin; 252e5c89e4eSSatish Balay PetscTrMalloc = PetscMallocAlign; 253e5c89e4eSSatish Balay PetscTrFree = PetscFreeAlign; 25492f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 255e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_FALSE; 256e5c89e4eSSatish Balay PetscFunctionReturn(0); 257e5c89e4eSSatish Balay } 258b44d5720SBarry Smith 259b44d5720SBarry Smith PetscErrorCode PetscMemoryTrace(const char label[]) 260b44d5720SBarry Smith { 261b44d5720SBarry Smith PetscErrorCode ierr; 262b44d5720SBarry Smith PetscLogDouble mem,mal; 263b44d5720SBarry Smith static PetscLogDouble oldmem = 0,oldmal = 0; 264b44d5720SBarry Smith 265b44d5720SBarry Smith PetscFunctionBegin; 266b44d5720SBarry Smith ierr = PetscMemoryGetCurrentUsage(&mem);CHKERRQ(ierr); 267b44d5720SBarry Smith ierr = PetscMallocGetCurrentUsage(&mal);CHKERRQ(ierr); 268b44d5720SBarry Smith 269b44d5720SBarry Smith ierr = PetscPrintf(PETSC_COMM_WORLD,"%s High water %8.3f MB increase %8.3f MB Current %8.3f MB increase %8.3f MB\n",label,mem*1e-6,(mem - oldmem)*1e-6,mal*1e-6,(mal - oldmal)*1e-6);CHKERRQ(ierr); 270b44d5720SBarry Smith oldmem = mem; 271b44d5720SBarry Smith oldmal = mal; 272b44d5720SBarry Smith PetscFunctionReturn(0); 273b44d5720SBarry Smith } 27413850c04SHong Zhang 275071fcb05SBarry Smith static PetscErrorCode (*PetscTrMallocOld)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign; 27692f119d6SBarry Smith static PetscErrorCode (*PetscTrReallocOld)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 27750a41461SHong Zhang static PetscErrorCode (*PetscTrFreeOld)(void*,int,const char[],const char[]) = PetscFreeAlign; 278de1d6c17SHong Zhang 279de1d6c17SHong Zhang /*@C 280de1d6c17SHong Zhang PetscMallocSetDRAM - Set PetscMalloc to use DRAM. 281de1d6c17SHong Zhang If memkind is available, change the memkind type. Otherwise, switch the 282de1d6c17SHong Zhang current malloc and free routines to the PetscMallocAlign and 283de1d6c17SHong Zhang PetscFreeAlign (PETSc default). 284de1d6c17SHong Zhang 285de1d6c17SHong Zhang Not Collective 286de1d6c17SHong Zhang 287de1d6c17SHong Zhang Level: developer 288de1d6c17SHong Zhang 289de1d6c17SHong Zhang Notes: 290de1d6c17SHong Zhang This provides a way to do the allocation on DRAM temporarily. One 291de1d6c17SHong Zhang can switch back to the previous choice by calling PetscMallocReset(). 292de1d6c17SHong Zhang 293de1d6c17SHong Zhang .seealso: PetscMallocReset() 294de1d6c17SHong Zhang @*/ 29513850c04SHong Zhang PetscErrorCode PetscMallocSetDRAM(void) 29613850c04SHong Zhang { 29713850c04SHong Zhang PetscFunctionBegin; 298de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 299de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 300de1d6c17SHong Zhang previousmktype = currentmktype; 301de1d6c17SHong Zhang currentmktype = PETSC_MK_DEFAULT; 302de1d6c17SHong Zhang #endif 303de1d6c17SHong Zhang } else { 30413850c04SHong Zhang /* Save the previous choice */ 30513850c04SHong Zhang PetscTrMallocOld = PetscTrMalloc; 30692f119d6SBarry Smith PetscTrReallocOld = PetscTrRealloc; 30713850c04SHong Zhang PetscTrFreeOld = PetscTrFree; 30813850c04SHong Zhang PetscTrMalloc = PetscMallocAlign; 30913850c04SHong Zhang PetscTrFree = PetscFreeAlign; 31092f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 311de1d6c17SHong Zhang } 31213850c04SHong Zhang PetscFunctionReturn(0); 31313850c04SHong Zhang } 31413850c04SHong Zhang 315de1d6c17SHong Zhang /*@C 316de1d6c17SHong Zhang PetscMallocResetDRAM - Reset the changes made by PetscMallocSetDRAM 317de1d6c17SHong Zhang 318de1d6c17SHong Zhang Not Collective 319de1d6c17SHong Zhang 320de1d6c17SHong Zhang Level: developer 321de1d6c17SHong Zhang 322de1d6c17SHong Zhang .seealso: PetscMallocSetDRAM() 323de1d6c17SHong Zhang @*/ 32413850c04SHong Zhang PetscErrorCode PetscMallocResetDRAM(void) 32513850c04SHong Zhang { 32613850c04SHong Zhang PetscFunctionBegin; 327de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 328de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 329de1d6c17SHong Zhang currentmktype = previousmktype; 330de1d6c17SHong Zhang #endif 331de1d6c17SHong Zhang } else { 33213850c04SHong Zhang /* Reset to the previous choice */ 33313850c04SHong Zhang PetscTrMalloc = PetscTrMallocOld; 33492f119d6SBarry Smith PetscTrRealloc = PetscTrReallocOld; 33513850c04SHong Zhang PetscTrFree = PetscTrFreeOld; 336de1d6c17SHong Zhang } 33713850c04SHong Zhang PetscFunctionReturn(0); 33813850c04SHong Zhang } 339ba282f50SJed Brown 340ba282f50SJed Brown static PetscBool petscmalloccoalesce = 341ba282f50SJed Brown #if defined(PETSC_USE_MALLOC_COALESCED) 342ba282f50SJed Brown PETSC_TRUE; 343ba282f50SJed Brown #else 344ba282f50SJed Brown PETSC_FALSE; 345ba282f50SJed Brown #endif 346ba282f50SJed Brown 347ba282f50SJed Brown /*@C 348ba282f50SJed Brown PetscMallocSetCoalesce - Use coalesced malloc when allocating groups of objects 349ba282f50SJed Brown 350ba282f50SJed Brown Not Collective 351ba282f50SJed Brown 352ba282f50SJed Brown Input Parameters: 353ba282f50SJed Brown . coalesce - PETSC_TRUE to use coalesced malloc for multi-object allocation. 354ba282f50SJed Brown 355ba282f50SJed Brown Options Database Keys: 356ba282f50SJed Brown . -malloc_coalesce - turn coalesced malloc on or off 357ba282f50SJed Brown 358ba282f50SJed Brown Note: 359ba282f50SJed Brown PETSc uses coalesced malloc by default for optimized builds and not for debugging builds. This default can be changed via the command-line option -malloc_coalesce or by calling this function. 36092f119d6SBarry Smith This function can only be called immediately after PetscInitialize() 361ba282f50SJed Brown 362ba282f50SJed Brown Level: developer 363ba282f50SJed Brown 364ba282f50SJed Brown .seealso: PetscMallocA() 365ba282f50SJed Brown @*/ 366ba282f50SJed Brown PetscErrorCode PetscMallocSetCoalesce(PetscBool coalesce) 367ba282f50SJed Brown { 368ba282f50SJed Brown PetscFunctionBegin; 369ba282f50SJed Brown petscmalloccoalesce = coalesce; 370ba282f50SJed Brown PetscFunctionReturn(0); 371ba282f50SJed Brown } 372ba282f50SJed Brown 373ba282f50SJed Brown /*@C 374ba282f50SJed Brown PetscMallocA - Allocate and optionally clear one or more objects, possibly using coalesced malloc 375ba282f50SJed Brown 376ba282f50SJed Brown Not Collective 377ba282f50SJed Brown 378ba282f50SJed Brown Input Parameters: 379ba282f50SJed Brown + n - number of objects to allocate (at least 1) 38089407d75SBarry Smith . clear - use calloc() to allocate space initialized to zero 381ba282f50SJed Brown . lineno - line number to attribute allocation (typically __LINE__) 382ba282f50SJed Brown . function - function to attribute allocation (typically PETSC_FUNCTION_NAME) 383ba282f50SJed Brown . filename - file name to attribute allocation (typically __FILE__) 384ba282f50SJed Brown - bytes0 - first of n object sizes 385ba282f50SJed Brown 386ba282f50SJed Brown Output Parameters: 387ba282f50SJed Brown . ptr0 - first of n pointers to allocate 388ba282f50SJed Brown 389ba282f50SJed Brown Notes: 390ba282f50SJed Brown This function is not normally called directly by users, but rather via the macros PetscMalloc1(), PetscMalloc2(), or PetscCalloc1(), etc. 391ba282f50SJed Brown 392ba282f50SJed Brown Level: developer 393ba282f50SJed Brown 394ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMalloc1(), PetscMalloc2(), PetscMalloc3(), PetscMalloc4(), PetscMalloc5(), PetscMalloc6(), PetscMalloc7(), PetscCalloc1(), PetscCalloc2(), PetscCalloc3(), PetscCalloc4(), PetscCalloc5(), PetscCalloc6(), PetscCalloc7(), PetscFreeA() 395ba282f50SJed Brown @*/ 396ba282f50SJed Brown PetscErrorCode PetscMallocA(int n,PetscBool clear,int lineno,const char *function,const char *filename,size_t bytes0,void *ptr0,...) 397ba282f50SJed Brown { 398ba282f50SJed Brown PetscErrorCode ierr; 399ba282f50SJed Brown va_list Argp; 400ba282f50SJed Brown size_t bytes[8],sumbytes; 401ba282f50SJed Brown void **ptr[8]; 402ba282f50SJed Brown int i; 403ba282f50SJed Brown 404ba282f50SJed Brown PetscFunctionBegin; 405ba282f50SJed Brown if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only 8 supported",n); 406ba282f50SJed Brown bytes[0] = bytes0; 407ba282f50SJed Brown ptr[0] = (void**)ptr0; 408ba282f50SJed Brown sumbytes = (bytes0 + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 409ba282f50SJed Brown va_start(Argp,ptr0); 410ba282f50SJed Brown for (i=1; i<n; i++) { 411ba282f50SJed Brown bytes[i] = va_arg(Argp,size_t); 412ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 413ba282f50SJed Brown sumbytes += (bytes[i] + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 414ba282f50SJed Brown } 415ba282f50SJed Brown va_end(Argp); 416ba282f50SJed Brown if (petscmalloccoalesce) { 417ba282f50SJed Brown char *p; 418071fcb05SBarry Smith ierr = (*PetscTrMalloc)(sumbytes,clear,lineno,function,filename,(void**)&p);CHKERRQ(ierr); 419ba282f50SJed Brown for (i=0; i<n; i++) { 420ba282f50SJed Brown *ptr[i] = bytes[i] ? p : NULL; 421ba282f50SJed Brown p = (char*)PetscAddrAlign(p + bytes[i]); 422ba282f50SJed Brown } 423ba282f50SJed Brown } else { 424ba282f50SJed Brown for (i=0; i<n; i++) { 425071fcb05SBarry Smith ierr = (*PetscTrMalloc)(bytes[i],clear,lineno,function,filename,(void**)ptr[i]);CHKERRQ(ierr); 426ba282f50SJed Brown } 427ba282f50SJed Brown } 428ba282f50SJed Brown PetscFunctionReturn(0); 429ba282f50SJed Brown } 430ba282f50SJed Brown 431ba282f50SJed Brown /*@C 432ba282f50SJed Brown PetscFreeA - Free one or more objects, possibly allocated using coalesced malloc 433ba282f50SJed Brown 434ba282f50SJed Brown Not Collective 435ba282f50SJed Brown 436ba282f50SJed Brown Input Parameters: 437ba282f50SJed Brown + n - number of objects to free (at least 1) 438ba282f50SJed Brown . lineno - line number to attribute deallocation (typically __LINE__) 439ba282f50SJed Brown . function - function to attribute deallocation (typically PETSC_FUNCTION_NAME) 440ba282f50SJed Brown . filename - file name to attribute deallocation (typically __FILE__) 441ba282f50SJed Brown - ptr0 ... - first of n pointers to free 442ba282f50SJed Brown 443ba282f50SJed Brown Note: 444071fcb05SBarry Smith This function is not normally called directly by users, but rather via the macros PetscFree(), PetscFree2(), etc. 445ba282f50SJed Brown 44689407d75SBarry Smith The pointers are zeroed to prevent users from accidently reusing space that has been freed. 44789407d75SBarry Smith 448ba282f50SJed Brown Level: developer 449ba282f50SJed Brown 450ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMallocA(), PetscFree1(), PetscFree2(), PetscFree3(), PetscFree4(), PetscFree5(), PetscFree6(), PetscFree7() 451ba282f50SJed Brown @*/ 452ba282f50SJed Brown PetscErrorCode PetscFreeA(int n,int lineno,const char *function,const char *filename,void *ptr0,...) 453ba282f50SJed Brown { 454ba282f50SJed Brown PetscErrorCode ierr; 455ba282f50SJed Brown va_list Argp; 456ba282f50SJed Brown void **ptr[8]; 457ba282f50SJed Brown int i; 458ba282f50SJed Brown 459ba282f50SJed Brown PetscFunctionBegin; 46089407d75SBarry Smith if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only up to 8 supported",n); 461ba282f50SJed Brown ptr[0] = (void**)ptr0; 462ba282f50SJed Brown va_start(Argp,ptr0); 463ba282f50SJed Brown for (i=1; i<n; i++) { 464ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 465ba282f50SJed Brown } 466ba282f50SJed Brown va_end(Argp); 467ba282f50SJed Brown if (petscmalloccoalesce) { 468ba282f50SJed Brown for (i=0; i<n; i++) { /* Find first nonempty allocation */ 469ba282f50SJed Brown if (*ptr[i]) break; 470ba282f50SJed Brown } 471ba282f50SJed Brown while (--n > i) { 472ba282f50SJed Brown *ptr[n] = NULL; 473ba282f50SJed Brown } 474c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 475ba282f50SJed Brown *ptr[n] = NULL; 476ba282f50SJed Brown } else { 477ba282f50SJed Brown while (--n >= 0) { 478c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 479ba282f50SJed Brown *ptr[n] = NULL; 480ba282f50SJed Brown } 481ba282f50SJed Brown } 482ba282f50SJed Brown PetscFunctionReturn(0); 483ba282f50SJed Brown } 484