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 26*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t mem,int line,const char func[],const char file[],void **result) 27e5c89e4eSSatish Balay { 28f0ba7cfcSLisandro Dalcin if (!mem) { *result = NULL; return 0; } 29fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 30fc2a7144SHong Zhang { 31fc2a7144SHong Zhang int ierr; 32fc2a7144SHong Zhang if (!currentmktype) ierr = memkind_posix_memalign(MEMKIND_DEFAULT,result,PETSC_MEMALIGN,mem); 33e3acc61dSHong Zhang else ierr = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,result,PETSC_MEMALIGN,mem); 34ca8c994eSHong Zhang if (ierr == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 35ca8c994eSHong Zhang if (ierr == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 36fc2a7144SHong Zhang } 37fc2a7144SHong Zhang #else 38e5c89e4eSSatish Balay # if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 39e5c89e4eSSatish Balay *result = malloc(mem); 40e5c89e4eSSatish Balay # elif defined(PETSC_HAVE_MEMALIGN) 41e5c89e4eSSatish Balay *result = memalign(PETSC_MEMALIGN,mem); 42e5c89e4eSSatish Balay # else 43e5c89e4eSSatish Balay { 44e5c89e4eSSatish Balay /* 45e5c89e4eSSatish Balay malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 46e5c89e4eSSatish Balay */ 475b232624SHong Zhang int *ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN); 48e5c89e4eSSatish Balay if (ptr) { 49f0ba7cfcSLisandro Dalcin int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 50e5c89e4eSSatish Balay shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 510700a824SBarry Smith ptr[shift-1] = shift + SHIFT_CLASSID; 52e5c89e4eSSatish Balay ptr += shift; 53e5c89e4eSSatish Balay *result = (void*)ptr; 54e5c89e4eSSatish Balay } else { 55f0ba7cfcSLisandro Dalcin *result = NULL; 56e5c89e4eSSatish Balay } 57e5c89e4eSSatish Balay } 58e5c89e4eSSatish Balay # endif 59fc2a7144SHong Zhang #endif 60f0ba7cfcSLisandro Dalcin if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 61e5c89e4eSSatish Balay return 0; 62e5c89e4eSSatish Balay } 63e5c89e4eSSatish Balay 64*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[]) 65e5c89e4eSSatish Balay { 66f0ba7cfcSLisandro Dalcin if (!ptr) return 0; 67fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 68fc2a7144SHong Zhang memkind_free(0,ptr); /* specify the kind to 0 so that memkind will look up for the right type */ 69fc2a7144SHong Zhang #else 70e5c89e4eSSatish Balay # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 71f0ba7cfcSLisandro Dalcin { 72e5c89e4eSSatish Balay /* 73e5c89e4eSSatish Balay Previous int tells us how many ints the pointer has been shifted from 74e5c89e4eSSatish Balay the original address provided by the system malloc(). 75e5c89e4eSSatish Balay */ 76f0ba7cfcSLisandro Dalcin int shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 77efca3c55SSatish 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"); 78efca3c55SSatish Balay if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 79e5c89e4eSSatish Balay ptr = (void*)(((int*)ptr) - shift); 80e5c89e4eSSatish Balay } 81f0ba7cfcSLisandro Dalcin # endif 82e5c89e4eSSatish Balay 83e5c89e4eSSatish Balay # if defined(PETSC_HAVE_FREE_RETURN_INT) 84e5c89e4eSSatish Balay int err = free(ptr); 85efca3c55SSatish Balay if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 86e5c89e4eSSatish Balay # else 87e5c89e4eSSatish Balay free(ptr); 88e5c89e4eSSatish Balay # endif 89fc2a7144SHong Zhang #endif 90e5c89e4eSSatish Balay return 0; 91e5c89e4eSSatish Balay } 92e5c89e4eSSatish Balay 93*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result) 943221ece2SMatthew G. Knepley { 95c22f1541SToby Isaac PetscErrorCode ierr; 96c22f1541SToby Isaac 97c22f1541SToby Isaac if (!mem) { 98c22f1541SToby Isaac ierr = PetscFreeAlign(*result, line, func, file); 99c22f1541SToby Isaac if (ierr) return ierr; 100c22f1541SToby Isaac *result = NULL; 101c22f1541SToby Isaac return 0; 102c22f1541SToby Isaac } 103fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 104fc2a7144SHong Zhang if (!currentmktype) *result = memkind_realloc(MEMKIND_DEFAULT,*result,mem); 105e3acc61dSHong Zhang else *result = memkind_realloc(MEMKIND_HBW_PREFERRED,*result,mem); 106fc2a7144SHong Zhang #else 1073221ece2SMatthew G. Knepley # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 1083221ece2SMatthew G. Knepley { 1093221ece2SMatthew G. Knepley /* 1103221ece2SMatthew G. Knepley Previous int tells us how many ints the pointer has been shifted from 1113221ece2SMatthew G. Knepley the original address provided by the system malloc(). 1123221ece2SMatthew G. Knepley */ 1133221ece2SMatthew G. Knepley int shift = *(((int*)*result)-1) - SHIFT_CLASSID; 1143221ece2SMatthew 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"); 1153221ece2SMatthew G. Knepley if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 1163221ece2SMatthew G. Knepley *result = (void*)(((int*)*result) - shift); 1173221ece2SMatthew G. Knepley } 1183221ece2SMatthew G. Knepley # endif 1193221ece2SMatthew G. Knepley 120c22f1541SToby Isaac # if (defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) || defined(PETSC_HAVE_MEMALIGN) 1213221ece2SMatthew G. Knepley *result = realloc(*result, mem); 1223221ece2SMatthew G. Knepley # else 1233221ece2SMatthew G. Knepley { 1243221ece2SMatthew G. Knepley /* 1253221ece2SMatthew G. Knepley malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 1263221ece2SMatthew G. Knepley */ 1273221ece2SMatthew G. Knepley int *ptr = (int *) realloc(*result, mem + 2*PETSC_MEMALIGN); 1283221ece2SMatthew G. Knepley if (ptr) { 1293221ece2SMatthew G. Knepley int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 1303221ece2SMatthew G. Knepley shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 1313221ece2SMatthew G. Knepley ptr[shift-1] = shift + SHIFT_CLASSID; 1323221ece2SMatthew G. Knepley ptr += shift; 1333221ece2SMatthew G. Knepley *result = (void*)ptr; 1343221ece2SMatthew G. Knepley } else { 1353221ece2SMatthew G. Knepley *result = NULL; 1363221ece2SMatthew G. Knepley } 1373221ece2SMatthew G. Knepley } 1383221ece2SMatthew G. Knepley # endif 139fc2a7144SHong Zhang #endif 1403221ece2SMatthew G. Knepley if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 141c22f1541SToby Isaac #if defined(PETSC_HAVE_MEMALIGN) 142c22f1541SToby Isaac /* There are no standard guarantees that realloc() maintains the alignment of memalign(), so I think we have to 143c22f1541SToby Isaac * realloc and, if the alignment is wrong, malloc/copy/free. */ 144c22f1541SToby Isaac if (((size_t) (*result)) % PETSC_MEMALIGN) { 145c22f1541SToby Isaac void *newResult; 146fc2a7144SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 147fc2a7144SHong Zhang { 148fc2a7144SHong Zhang int ierr; 149fc2a7144SHong Zhang if (!currentmktype) ierr = memkind_posix_memalign(MEMKIND_DEFAULT,&newResult,PETSC_MEMALIGN,mem); 150e3acc61dSHong Zhang else ierr = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,&newResult,PETSC_MEMALIGN,mem); 151ca8c994eSHong Zhang if (ierr == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 152ca8c994eSHong Zhang if (ierr == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 153fc2a7144SHong Zhang } 154fc2a7144SHong Zhang # else 155c22f1541SToby Isaac newResult = memalign(PETSC_MEMALIGN,mem); 156fc2a7144SHong Zhang # endif 157c22f1541SToby Isaac if (!newResult) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 158c22f1541SToby Isaac ierr = PetscMemcpy(newResult,*result,mem); 159c22f1541SToby Isaac if (ierr) return ierr; 160c22f1541SToby Isaac # if defined(PETSC_HAVE_FREE_RETURN_INT) 161c22f1541SToby Isaac { 162c22f1541SToby Isaac int err = free(*result); 163c22f1541SToby Isaac if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 164c22f1541SToby Isaac } 165c22f1541SToby Isaac # else 166de1d6c17SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 167de1d6c17SHong Zhang memkind_free(0,*result); 168de1d6c17SHong Zhang # else 169c22f1541SToby Isaac free(*result); 170c22f1541SToby Isaac # endif 171de1d6c17SHong Zhang # endif 172c22f1541SToby Isaac *result = newResult; 173c22f1541SToby Isaac } 174c22f1541SToby Isaac #endif 1753221ece2SMatthew G. Knepley return 0; 1763221ece2SMatthew G. Knepley } 1773221ece2SMatthew G. Knepley 178efca3c55SSatish Balay PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign; 179efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 1803221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 181e5c89e4eSSatish Balay 182*95c0884eSLisandro Dalcin PETSC_INTERN PetscBool petscsetmallocvisited; 183ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE; 184e5c89e4eSSatish Balay 185e5c89e4eSSatish Balay /*@C 1861d1a0024SBarry Smith PetscMallocSet - Sets the routines used to do mallocs and frees. 187e5c89e4eSSatish Balay This routine MUST be called before PetscInitialize() and may be 188e5c89e4eSSatish Balay called only once. 189e5c89e4eSSatish Balay 190e5c89e4eSSatish Balay Not Collective 191e5c89e4eSSatish Balay 192e5c89e4eSSatish Balay Input Parameters: 193e5c89e4eSSatish Balay + malloc - the malloc routine 194e5c89e4eSSatish Balay - free - the free routine 195e5c89e4eSSatish Balay 196e5c89e4eSSatish Balay Level: developer 197e5c89e4eSSatish Balay 198e5c89e4eSSatish Balay Concepts: malloc 199e5c89e4eSSatish Balay Concepts: memory^allocation 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay @*/ 202efca3c55SSatish Balay PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**), 203efca3c55SSatish Balay PetscErrorCode (*ifree)(void*,int,const char[],const char[])) 204e5c89e4eSSatish Balay { 205e5c89e4eSSatish Balay PetscFunctionBegin; 206e32f2f54SBarry Smith if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 207e5c89e4eSSatish Balay PetscTrMalloc = imalloc; 208e5c89e4eSSatish Balay PetscTrFree = ifree; 209e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_TRUE; 210e5c89e4eSSatish Balay PetscFunctionReturn(0); 211e5c89e4eSSatish Balay } 212e5c89e4eSSatish Balay 213e5c89e4eSSatish Balay /*@C 2141d1a0024SBarry Smith PetscMallocClear - Resets the routines used to do mallocs and frees to the 215e5c89e4eSSatish Balay defaults. 216e5c89e4eSSatish Balay 217e5c89e4eSSatish Balay Not Collective 218e5c89e4eSSatish Balay 219e5c89e4eSSatish Balay Level: developer 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay Notes: 222e5c89e4eSSatish Balay In general one should never run a PETSc program with different malloc() and 223e5c89e4eSSatish Balay free() settings for different parts; this is because one NEVER wants to 224e5c89e4eSSatish Balay free() an address that was malloced by a different memory management system 225e5c89e4eSSatish Balay 226e5c89e4eSSatish Balay @*/ 2277087cfbeSBarry Smith PetscErrorCode PetscMallocClear(void) 228e5c89e4eSSatish Balay { 229e5c89e4eSSatish Balay PetscFunctionBegin; 230e5c89e4eSSatish Balay PetscTrMalloc = PetscMallocAlign; 231e5c89e4eSSatish Balay PetscTrFree = PetscFreeAlign; 232e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_FALSE; 233e5c89e4eSSatish Balay PetscFunctionReturn(0); 234e5c89e4eSSatish Balay } 235b44d5720SBarry Smith 236b44d5720SBarry Smith PetscErrorCode PetscMemoryTrace(const char label[]) 237b44d5720SBarry Smith { 238b44d5720SBarry Smith PetscErrorCode ierr; 239b44d5720SBarry Smith PetscLogDouble mem,mal; 240b44d5720SBarry Smith static PetscLogDouble oldmem = 0,oldmal = 0; 241b44d5720SBarry Smith 242b44d5720SBarry Smith PetscFunctionBegin; 243b44d5720SBarry Smith ierr = PetscMemoryGetCurrentUsage(&mem);CHKERRQ(ierr); 244b44d5720SBarry Smith ierr = PetscMallocGetCurrentUsage(&mal);CHKERRQ(ierr); 245b44d5720SBarry Smith 246b44d5720SBarry 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); 247b44d5720SBarry Smith oldmem = mem; 248b44d5720SBarry Smith oldmal = mal; 249b44d5720SBarry Smith PetscFunctionReturn(0); 250b44d5720SBarry Smith } 25113850c04SHong Zhang 25250a41461SHong Zhang static PetscErrorCode (*PetscTrMallocOld)(size_t,int,const char[],const char[],void**) = PetscMallocAlign; 25350a41461SHong Zhang static PetscErrorCode (*PetscTrFreeOld)(void*,int,const char[],const char[]) = PetscFreeAlign; 254de1d6c17SHong Zhang 255de1d6c17SHong Zhang /*@C 256de1d6c17SHong Zhang PetscMallocSetDRAM - Set PetscMalloc to use DRAM. 257de1d6c17SHong Zhang If memkind is available, change the memkind type. Otherwise, switch the 258de1d6c17SHong Zhang current malloc and free routines to the PetscMallocAlign and 259de1d6c17SHong Zhang PetscFreeAlign (PETSc default). 260de1d6c17SHong Zhang 261de1d6c17SHong Zhang Not Collective 262de1d6c17SHong Zhang 263de1d6c17SHong Zhang Level: developer 264de1d6c17SHong Zhang 265de1d6c17SHong Zhang Notes: 266de1d6c17SHong Zhang This provides a way to do the allocation on DRAM temporarily. One 267de1d6c17SHong Zhang can switch back to the previous choice by calling PetscMallocReset(). 268de1d6c17SHong Zhang 269de1d6c17SHong Zhang .seealso: PetscMallocReset() 270de1d6c17SHong Zhang @*/ 27113850c04SHong Zhang PetscErrorCode PetscMallocSetDRAM(void) 27213850c04SHong Zhang { 27313850c04SHong Zhang PetscFunctionBegin; 274de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 275de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 276de1d6c17SHong Zhang previousmktype = currentmktype; 277de1d6c17SHong Zhang currentmktype = PETSC_MK_DEFAULT; 278de1d6c17SHong Zhang #endif 279de1d6c17SHong Zhang } else { 28013850c04SHong Zhang /* Save the previous choice */ 28113850c04SHong Zhang PetscTrMallocOld = PetscTrMalloc; 28213850c04SHong Zhang PetscTrFreeOld = PetscTrFree; 28313850c04SHong Zhang PetscTrMalloc = PetscMallocAlign; 28413850c04SHong Zhang PetscTrFree = PetscFreeAlign; 285de1d6c17SHong Zhang } 28613850c04SHong Zhang PetscFunctionReturn(0); 28713850c04SHong Zhang } 28813850c04SHong Zhang 289de1d6c17SHong Zhang /*@C 290de1d6c17SHong Zhang PetscMallocResetDRAM - Reset the changes made by PetscMallocSetDRAM 291de1d6c17SHong Zhang 292de1d6c17SHong Zhang Not Collective 293de1d6c17SHong Zhang 294de1d6c17SHong Zhang Level: developer 295de1d6c17SHong Zhang 296de1d6c17SHong Zhang .seealso: PetscMallocSetDRAM() 297de1d6c17SHong Zhang @*/ 29813850c04SHong Zhang PetscErrorCode PetscMallocResetDRAM(void) 29913850c04SHong Zhang { 30013850c04SHong Zhang PetscFunctionBegin; 301de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 302de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 303de1d6c17SHong Zhang currentmktype = previousmktype; 304de1d6c17SHong Zhang #endif 305de1d6c17SHong Zhang } else { 30613850c04SHong Zhang /* Reset to the previous choice */ 30713850c04SHong Zhang PetscTrMalloc = PetscTrMallocOld; 30813850c04SHong Zhang PetscTrFree = PetscTrFreeOld; 309de1d6c17SHong Zhang } 31013850c04SHong Zhang PetscFunctionReturn(0); 31113850c04SHong Zhang } 312ba282f50SJed Brown 313ba282f50SJed Brown static PetscBool petscmalloccoalesce = 314ba282f50SJed Brown #if defined(PETSC_USE_MALLOC_COALESCED) 315ba282f50SJed Brown PETSC_TRUE; 316ba282f50SJed Brown #else 317ba282f50SJed Brown PETSC_FALSE; 318ba282f50SJed Brown #endif 319ba282f50SJed Brown 320ba282f50SJed Brown /*@C 321ba282f50SJed Brown PetscMallocSetCoalesce - Use coalesced malloc when allocating groups of objects 322ba282f50SJed Brown 323ba282f50SJed Brown Not Collective 324ba282f50SJed Brown 325ba282f50SJed Brown Input Parameters: 326ba282f50SJed Brown . coalesce - PETSC_TRUE to use coalesced malloc for multi-object allocation. 327ba282f50SJed Brown 328ba282f50SJed Brown Options Database Keys: 329ba282f50SJed Brown . -malloc_coalesce - turn coalesced malloc on or off 330ba282f50SJed Brown 331ba282f50SJed Brown Note: 332ba282f50SJed 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. 333ba282f50SJed Brown 334ba282f50SJed Brown Level: developer 335ba282f50SJed Brown 336ba282f50SJed Brown .seealso: PetscMallocA() 337ba282f50SJed Brown @*/ 338ba282f50SJed Brown PetscErrorCode PetscMallocSetCoalesce(PetscBool coalesce) 339ba282f50SJed Brown { 340ba282f50SJed Brown PetscFunctionBegin; 341ba282f50SJed Brown petscmalloccoalesce = coalesce; 342ba282f50SJed Brown PetscFunctionReturn(0); 343ba282f50SJed Brown } 344ba282f50SJed Brown 345ba282f50SJed Brown /*@C 346ba282f50SJed Brown PetscMallocA - Allocate and optionally clear one or more objects, possibly using coalesced malloc 347ba282f50SJed Brown 348ba282f50SJed Brown Not Collective 349ba282f50SJed Brown 350ba282f50SJed Brown Input Parameters: 351ba282f50SJed Brown + n - number of objects to allocate (at least 1) 35289407d75SBarry Smith . clear - use calloc() to allocate space initialized to zero 353ba282f50SJed Brown . lineno - line number to attribute allocation (typically __LINE__) 354ba282f50SJed Brown . function - function to attribute allocation (typically PETSC_FUNCTION_NAME) 355ba282f50SJed Brown . filename - file name to attribute allocation (typically __FILE__) 356ba282f50SJed Brown - bytes0 - first of n object sizes 357ba282f50SJed Brown 358ba282f50SJed Brown Output Parameters: 359ba282f50SJed Brown . ptr0 - first of n pointers to allocate 360ba282f50SJed Brown 361ba282f50SJed Brown Notes: 362ba282f50SJed Brown This function is not normally called directly by users, but rather via the macros PetscMalloc1(), PetscMalloc2(), or PetscCalloc1(), etc. 363ba282f50SJed Brown 364ba282f50SJed Brown Level: developer 365ba282f50SJed Brown 366ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMalloc1(), PetscMalloc2(), PetscMalloc3(), PetscMalloc4(), PetscMalloc5(), PetscMalloc6(), PetscMalloc7(), PetscCalloc1(), PetscCalloc2(), PetscCalloc3(), PetscCalloc4(), PetscCalloc5(), PetscCalloc6(), PetscCalloc7(), PetscFreeA() 367ba282f50SJed Brown @*/ 368ba282f50SJed Brown PetscErrorCode PetscMallocA(int n,PetscBool clear,int lineno,const char *function,const char *filename,size_t bytes0,void *ptr0,...) 369ba282f50SJed Brown { 370ba282f50SJed Brown PetscErrorCode ierr; 371ba282f50SJed Brown va_list Argp; 372ba282f50SJed Brown size_t bytes[8],sumbytes; 373ba282f50SJed Brown void **ptr[8]; 374ba282f50SJed Brown int i; 375ba282f50SJed Brown 376ba282f50SJed Brown PetscFunctionBegin; 377ba282f50SJed Brown if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only 8 supported",n); 378ba282f50SJed Brown bytes[0] = bytes0; 379ba282f50SJed Brown ptr[0] = (void**)ptr0; 380ba282f50SJed Brown sumbytes = (bytes0 + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 381ba282f50SJed Brown va_start(Argp,ptr0); 382ba282f50SJed Brown for (i=1; i<n; i++) { 383ba282f50SJed Brown bytes[i] = va_arg(Argp,size_t); 384ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 385ba282f50SJed Brown sumbytes += (bytes[i] + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 386ba282f50SJed Brown } 387ba282f50SJed Brown va_end(Argp); 388ba282f50SJed Brown if (petscmalloccoalesce) { 389ba282f50SJed Brown char *p; 390ba282f50SJed Brown ierr = (*PetscTrMalloc)(sumbytes,lineno,function,filename,(void**)&p);CHKERRQ(ierr); 391ba282f50SJed Brown for (i=0; i<n; i++) { 392ba282f50SJed Brown *ptr[i] = bytes[i] ? p : NULL; 393ba282f50SJed Brown p = (char*)PetscAddrAlign(p + bytes[i]); 394ba282f50SJed Brown } 395ba282f50SJed Brown } else { 396ba282f50SJed Brown for (i=0; i<n; i++) { 397ba282f50SJed Brown ierr = (*PetscTrMalloc)(bytes[i],lineno,function,filename,(void**)ptr[i]);CHKERRQ(ierr); 398ba282f50SJed Brown } 399ba282f50SJed Brown } 400ba282f50SJed Brown if (clear) { 401ba282f50SJed Brown for (i=0; i<n; i++) { 402ba282f50SJed Brown ierr = PetscMemzero(*ptr[i],bytes[i]);CHKERRQ(ierr); 403ba282f50SJed Brown } 404ba282f50SJed Brown } 405ba282f50SJed Brown PetscFunctionReturn(0); 406ba282f50SJed Brown } 407ba282f50SJed Brown 408ba282f50SJed Brown /*@C 409ba282f50SJed Brown PetscFreeA - Free one or more objects, possibly allocated using coalesced malloc 410ba282f50SJed Brown 411ba282f50SJed Brown Not Collective 412ba282f50SJed Brown 413ba282f50SJed Brown Input Parameters: 414ba282f50SJed Brown + n - number of objects to free (at least 1) 415ba282f50SJed Brown . lineno - line number to attribute deallocation (typically __LINE__) 416ba282f50SJed Brown . function - function to attribute deallocation (typically PETSC_FUNCTION_NAME) 417ba282f50SJed Brown . filename - file name to attribute deallocation (typically __FILE__) 418ba282f50SJed Brown - ptr0 ... - first of n pointers to free 419ba282f50SJed Brown 420ba282f50SJed Brown Note: 421ba282f50SJed Brown This function is not normally called directly by users, but rather via the macros PetscFree1(), PetscFree2(), etc. 422ba282f50SJed Brown 42389407d75SBarry Smith The pointers are zeroed to prevent users from accidently reusing space that has been freed. 42489407d75SBarry Smith 425ba282f50SJed Brown Level: developer 426ba282f50SJed Brown 427ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMallocA(), PetscFree1(), PetscFree2(), PetscFree3(), PetscFree4(), PetscFree5(), PetscFree6(), PetscFree7() 428ba282f50SJed Brown @*/ 429ba282f50SJed Brown PetscErrorCode PetscFreeA(int n,int lineno,const char *function,const char *filename,void *ptr0,...) 430ba282f50SJed Brown { 431ba282f50SJed Brown PetscErrorCode ierr; 432ba282f50SJed Brown va_list Argp; 433ba282f50SJed Brown void **ptr[8]; 434ba282f50SJed Brown int i; 435ba282f50SJed Brown 436ba282f50SJed Brown PetscFunctionBegin; 43789407d75SBarry Smith if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only up to 8 supported",n); 438ba282f50SJed Brown ptr[0] = (void**)ptr0; 439ba282f50SJed Brown va_start(Argp,ptr0); 440ba282f50SJed Brown for (i=1; i<n; i++) { 441ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 442ba282f50SJed Brown } 443ba282f50SJed Brown va_end(Argp); 444ba282f50SJed Brown if (petscmalloccoalesce) { 445ba282f50SJed Brown for (i=0; i<n; i++) { /* Find first nonempty allocation */ 446ba282f50SJed Brown if (*ptr[i]) break; 447ba282f50SJed Brown } 448ba282f50SJed Brown while (--n > i) { 449ba282f50SJed Brown *ptr[n] = NULL; 450ba282f50SJed Brown } 451c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 452ba282f50SJed Brown *ptr[n] = NULL; 453ba282f50SJed Brown } else { 454ba282f50SJed Brown while (--n >= 0) { 455c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 456ba282f50SJed Brown *ptr[n] = NULL; 457ba282f50SJed Brown } 458ba282f50SJed Brown } 459ba282f50SJed Brown PetscFunctionReturn(0); 460ba282f50SJed Brown } 461