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; 29071fcb05SBarry Smith 30f0ba7cfcSLisandro Dalcin if (!mem) {*result = NULL; return 0;} 31fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 32fc2a7144SHong Zhang { 33fc2a7144SHong Zhang if (!currentmktype) ierr = memkind_posix_memalign(MEMKIND_DEFAULT,result,PETSC_MEMALIGN,mem); 34e3acc61dSHong Zhang else ierr = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,result,PETSC_MEMALIGN,mem); 35ca8c994eSHong Zhang if (ierr == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 36ca8c994eSHong Zhang if (ierr == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 37071fcb05SBarry Smith if (clear) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 38fc2a7144SHong Zhang } 39fc2a7144SHong Zhang #else 40e5c89e4eSSatish Balay # if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 41071fcb05SBarry Smith if (clear) { 42071fcb05SBarry Smith *result = calloc(1+mem/sizeof(int),sizeof(int)); 43071fcb05SBarry Smith } else { 44e5c89e4eSSatish Balay *result = malloc(mem); 45071fcb05SBarry Smith } 46071fcb05SBarry Smith if (PetscLogMemory) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 47071fcb05SBarry Smith 48e5c89e4eSSatish Balay # elif defined(PETSC_HAVE_MEMALIGN) 49e5c89e4eSSatish Balay *result = memalign(PETSC_MEMALIGN,mem); 50071fcb05SBarry Smith if (clear || PetscLogMemory) { 51071fcb05SBarry Smith ierr = PetscMemzero(*result,mem);CHKERRQ(ierr); 52071fcb05SBarry Smith } 53e5c89e4eSSatish Balay # else 54e5c89e4eSSatish Balay { 55071fcb05SBarry Smith int *ptr; 56e5c89e4eSSatish Balay /* 57e5c89e4eSSatish Balay malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 58e5c89e4eSSatish Balay */ 59071fcb05SBarry Smith if (clear) { 60071fcb05SBarry Smith ptr = (int*)calloc(1+(mem + 2*PETSC_MEMALIGN)/sizeof(int),sizeof(int)); 61071fcb05SBarry Smith } else { 62071fcb05SBarry Smith ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN); 63071fcb05SBarry Smith } 64e5c89e4eSSatish Balay if (ptr) { 65f0ba7cfcSLisandro Dalcin int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 66e5c89e4eSSatish Balay shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 670700a824SBarry Smith ptr[shift-1] = shift + SHIFT_CLASSID; 68e5c89e4eSSatish Balay ptr += shift; 69e5c89e4eSSatish Balay *result = (void*)ptr; 70071fcb05SBarry Smith if (PetscLogMemory) {ierr = PetscMemzero(*result,mem);CHKERRQ(ierr);} 71e5c89e4eSSatish Balay } else { 72f0ba7cfcSLisandro Dalcin *result = NULL; 73e5c89e4eSSatish Balay } 74e5c89e4eSSatish Balay } 75e5c89e4eSSatish Balay # endif 76fc2a7144SHong Zhang #endif 77071fcb05SBarry Smith 78f0ba7cfcSLisandro Dalcin if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 79e5c89e4eSSatish Balay return 0; 80e5c89e4eSSatish Balay } 81e5c89e4eSSatish Balay 8295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[]) 83e5c89e4eSSatish Balay { 84f0ba7cfcSLisandro Dalcin if (!ptr) return 0; 85fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 86fc2a7144SHong Zhang memkind_free(0,ptr); /* specify the kind to 0 so that memkind will look up for the right type */ 87fc2a7144SHong Zhang #else 88e5c89e4eSSatish Balay # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 89f0ba7cfcSLisandro Dalcin { 90e5c89e4eSSatish Balay /* 91e5c89e4eSSatish Balay Previous int tells us how many ints the pointer has been shifted from 92e5c89e4eSSatish Balay the original address provided by the system malloc(). 93e5c89e4eSSatish Balay */ 94f0ba7cfcSLisandro Dalcin int shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 95efca3c55SSatish 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"); 96efca3c55SSatish Balay if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 97e5c89e4eSSatish Balay ptr = (void*)(((int*)ptr) - shift); 98e5c89e4eSSatish Balay } 99f0ba7cfcSLisandro Dalcin # endif 100e5c89e4eSSatish Balay 101e5c89e4eSSatish Balay # if defined(PETSC_HAVE_FREE_RETURN_INT) 102e5c89e4eSSatish Balay int err = free(ptr); 103efca3c55SSatish Balay if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 104e5c89e4eSSatish Balay # else 105e5c89e4eSSatish Balay free(ptr); 106e5c89e4eSSatish Balay # endif 107fc2a7144SHong Zhang #endif 108e5c89e4eSSatish Balay return 0; 109e5c89e4eSSatish Balay } 110e5c89e4eSSatish Balay 11195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result) 1123221ece2SMatthew G. Knepley { 113c22f1541SToby Isaac PetscErrorCode ierr; 114c22f1541SToby Isaac 115c22f1541SToby Isaac if (!mem) { 116c22f1541SToby Isaac ierr = PetscFreeAlign(*result, line, func, file); 117c22f1541SToby Isaac if (ierr) return ierr; 118c22f1541SToby Isaac *result = NULL; 119c22f1541SToby Isaac return 0; 120c22f1541SToby Isaac } 121fc2a7144SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 122fc2a7144SHong Zhang if (!currentmktype) *result = memkind_realloc(MEMKIND_DEFAULT,*result,mem); 123e3acc61dSHong Zhang else *result = memkind_realloc(MEMKIND_HBW_PREFERRED,*result,mem); 124fc2a7144SHong Zhang #else 1253221ece2SMatthew G. Knepley # if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 1263221ece2SMatthew G. Knepley { 1273221ece2SMatthew G. Knepley /* 1283221ece2SMatthew G. Knepley Previous int tells us how many ints the pointer has been shifted from 1293221ece2SMatthew G. Knepley the original address provided by the system malloc(). 1303221ece2SMatthew G. Knepley */ 1313221ece2SMatthew G. Knepley int shift = *(((int*)*result)-1) - SHIFT_CLASSID; 1323221ece2SMatthew 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"); 1333221ece2SMatthew G. Knepley if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 1343221ece2SMatthew G. Knepley *result = (void*)(((int*)*result) - shift); 1353221ece2SMatthew G. Knepley } 1363221ece2SMatthew G. Knepley # endif 1373221ece2SMatthew G. Knepley 138c22f1541SToby Isaac # if (defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) || defined(PETSC_HAVE_MEMALIGN) 139*92f119d6SBarry Smith *result = realloc(*request, mem); 1403221ece2SMatthew G. Knepley # else 1413221ece2SMatthew G. Knepley { 1423221ece2SMatthew G. Knepley /* 1433221ece2SMatthew G. Knepley malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 1443221ece2SMatthew G. Knepley */ 1453221ece2SMatthew G. Knepley int *ptr = (int *) realloc(*result, mem + 2*PETSC_MEMALIGN); 1463221ece2SMatthew G. Knepley if (ptr) { 1473221ece2SMatthew G. Knepley int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 1483221ece2SMatthew G. Knepley shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 1493221ece2SMatthew G. Knepley ptr[shift-1] = shift + SHIFT_CLASSID; 1503221ece2SMatthew G. Knepley ptr += shift; 1513221ece2SMatthew G. Knepley *result = (void*)ptr; 1523221ece2SMatthew G. Knepley } else { 1533221ece2SMatthew G. Knepley *result = NULL; 1543221ece2SMatthew G. Knepley } 1553221ece2SMatthew G. Knepley } 1563221ece2SMatthew G. Knepley # endif 157fc2a7144SHong Zhang #endif 1583221ece2SMatthew G. Knepley if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 159c22f1541SToby Isaac #if defined(PETSC_HAVE_MEMALIGN) 160c22f1541SToby Isaac /* There are no standard guarantees that realloc() maintains the alignment of memalign(), so I think we have to 161c22f1541SToby Isaac * realloc and, if the alignment is wrong, malloc/copy/free. */ 162c22f1541SToby Isaac if (((size_t) (*result)) % PETSC_MEMALIGN) { 163c22f1541SToby Isaac void *newResult; 164fc2a7144SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 165fc2a7144SHong Zhang { 166fc2a7144SHong Zhang int ierr; 167fc2a7144SHong Zhang if (!currentmktype) ierr = memkind_posix_memalign(MEMKIND_DEFAULT,&newResult,PETSC_MEMALIGN,mem); 168e3acc61dSHong Zhang else ierr = memkind_posix_memalign(MEMKIND_HBW_PREFERRED,&newResult,PETSC_MEMALIGN,mem); 169ca8c994eSHong Zhang if (ierr == EINVAL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 170ca8c994eSHong Zhang if (ierr == ENOMEM) PetscInfo1(0,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem); 171fc2a7144SHong Zhang } 172fc2a7144SHong Zhang # else 173c22f1541SToby Isaac newResult = memalign(PETSC_MEMALIGN,mem); 174fc2a7144SHong Zhang # endif 175c22f1541SToby Isaac if (!newResult) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 176c22f1541SToby Isaac ierr = PetscMemcpy(newResult,*result,mem); 177c22f1541SToby Isaac if (ierr) return ierr; 178c22f1541SToby Isaac # if defined(PETSC_HAVE_FREE_RETURN_INT) 179c22f1541SToby Isaac { 180c22f1541SToby Isaac int err = free(*result); 181c22f1541SToby Isaac if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 182c22f1541SToby Isaac } 183c22f1541SToby Isaac # else 184de1d6c17SHong Zhang # if defined(PETSC_HAVE_MEMKIND) 185de1d6c17SHong Zhang memkind_free(0,*result); 186de1d6c17SHong Zhang # else 187c22f1541SToby Isaac free(*result); 188c22f1541SToby Isaac # endif 189de1d6c17SHong Zhang # endif 190c22f1541SToby Isaac *result = newResult; 191c22f1541SToby Isaac } 192c22f1541SToby Isaac #endif 1933221ece2SMatthew G. Knepley return 0; 1943221ece2SMatthew G. Knepley } 1953221ece2SMatthew G. Knepley 196071fcb05SBarry Smith PetscErrorCode (*PetscTrMalloc)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign; 197efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 1983221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 199e5c89e4eSSatish Balay 20095c0884eSLisandro Dalcin PETSC_INTERN PetscBool petscsetmallocvisited; 201ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE; 202e5c89e4eSSatish Balay 203e5c89e4eSSatish Balay /*@C 2041d1a0024SBarry Smith PetscMallocSet - Sets the routines used to do mallocs and frees. 205e5c89e4eSSatish Balay This routine MUST be called before PetscInitialize() and may be 206e5c89e4eSSatish Balay called only once. 207e5c89e4eSSatish Balay 208e5c89e4eSSatish Balay Not Collective 209e5c89e4eSSatish Balay 210e5c89e4eSSatish Balay Input Parameters: 211*92f119d6SBarry Smith + imalloc - the routine that provides the malloc (also provides calloc(), which is used depends on the second argument) 212*92f119d6SBarry Smith . ifree - the routine that provides the free 213*92f119d6SBarry Smith - iralloc - the routine that provides the realloc 214e5c89e4eSSatish Balay 215e5c89e4eSSatish Balay Level: developer 216e5c89e4eSSatish Balay 217e5c89e4eSSatish Balay @*/ 218071fcb05SBarry Smith PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,PetscBool,int,const char[],const char[],void**), 219*92f119d6SBarry Smith PetscErrorCode (*ifree)(void*,int,const char[],const char[]), 220*92f119d6SBarry Smith PetscErrorCode (*iralloc)(size_t, int, const char[], const char[], void **)) 221e5c89e4eSSatish Balay { 222e5c89e4eSSatish Balay PetscFunctionBegin; 223e32f2f54SBarry Smith if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 224e5c89e4eSSatish Balay PetscTrMalloc = imalloc; 225e5c89e4eSSatish Balay PetscTrFree = ifree; 226*92f119d6SBarry Smith PetscTrRealloc = iralloc; 227e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_TRUE; 228e5c89e4eSSatish Balay PetscFunctionReturn(0); 229e5c89e4eSSatish Balay } 230e5c89e4eSSatish Balay 231e5c89e4eSSatish Balay /*@C 232*92f119d6SBarry Smith PetscMallocClear - Resets the routines used to do mallocs and frees to the defaults. 233e5c89e4eSSatish Balay 234e5c89e4eSSatish Balay Not Collective 235e5c89e4eSSatish Balay 236e5c89e4eSSatish Balay Level: developer 237e5c89e4eSSatish Balay 238e5c89e4eSSatish Balay Notes: 239e5c89e4eSSatish Balay In general one should never run a PETSc program with different malloc() and 240e5c89e4eSSatish Balay free() settings for different parts; this is because one NEVER wants to 241e5c89e4eSSatish Balay free() an address that was malloced by a different memory management system 242e5c89e4eSSatish Balay 243*92f119d6SBarry Smith Called in PetscFinalize() so that if PetscInitialize() is called again it starts with a fresh slate of allocation information 244*92f119d6SBarry Smith 245e5c89e4eSSatish Balay @*/ 2467087cfbeSBarry Smith PetscErrorCode PetscMallocClear(void) 247e5c89e4eSSatish Balay { 248e5c89e4eSSatish Balay PetscFunctionBegin; 249e5c89e4eSSatish Balay PetscTrMalloc = PetscMallocAlign; 250e5c89e4eSSatish Balay PetscTrFree = PetscFreeAlign; 251*92f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 252e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_FALSE; 253e5c89e4eSSatish Balay PetscFunctionReturn(0); 254e5c89e4eSSatish Balay } 255b44d5720SBarry Smith 256b44d5720SBarry Smith PetscErrorCode PetscMemoryTrace(const char label[]) 257b44d5720SBarry Smith { 258b44d5720SBarry Smith PetscErrorCode ierr; 259b44d5720SBarry Smith PetscLogDouble mem,mal; 260b44d5720SBarry Smith static PetscLogDouble oldmem = 0,oldmal = 0; 261b44d5720SBarry Smith 262b44d5720SBarry Smith PetscFunctionBegin; 263b44d5720SBarry Smith ierr = PetscMemoryGetCurrentUsage(&mem);CHKERRQ(ierr); 264b44d5720SBarry Smith ierr = PetscMallocGetCurrentUsage(&mal);CHKERRQ(ierr); 265b44d5720SBarry Smith 266b44d5720SBarry 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); 267b44d5720SBarry Smith oldmem = mem; 268b44d5720SBarry Smith oldmal = mal; 269b44d5720SBarry Smith PetscFunctionReturn(0); 270b44d5720SBarry Smith } 27113850c04SHong Zhang 272071fcb05SBarry Smith static PetscErrorCode (*PetscTrMallocOld)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign; 273*92f119d6SBarry Smith static PetscErrorCode (*PetscTrReallocOld)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 27450a41461SHong Zhang static PetscErrorCode (*PetscTrFreeOld)(void*,int,const char[],const char[]) = PetscFreeAlign; 275de1d6c17SHong Zhang 276de1d6c17SHong Zhang /*@C 277de1d6c17SHong Zhang PetscMallocSetDRAM - Set PetscMalloc to use DRAM. 278de1d6c17SHong Zhang If memkind is available, change the memkind type. Otherwise, switch the 279de1d6c17SHong Zhang current malloc and free routines to the PetscMallocAlign and 280de1d6c17SHong Zhang PetscFreeAlign (PETSc default). 281de1d6c17SHong Zhang 282de1d6c17SHong Zhang Not Collective 283de1d6c17SHong Zhang 284de1d6c17SHong Zhang Level: developer 285de1d6c17SHong Zhang 286de1d6c17SHong Zhang Notes: 287de1d6c17SHong Zhang This provides a way to do the allocation on DRAM temporarily. One 288de1d6c17SHong Zhang can switch back to the previous choice by calling PetscMallocReset(). 289de1d6c17SHong Zhang 290de1d6c17SHong Zhang .seealso: PetscMallocReset() 291de1d6c17SHong Zhang @*/ 29213850c04SHong Zhang PetscErrorCode PetscMallocSetDRAM(void) 29313850c04SHong Zhang { 29413850c04SHong Zhang PetscFunctionBegin; 295de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 296de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 297de1d6c17SHong Zhang previousmktype = currentmktype; 298de1d6c17SHong Zhang currentmktype = PETSC_MK_DEFAULT; 299de1d6c17SHong Zhang #endif 300de1d6c17SHong Zhang } else { 30113850c04SHong Zhang /* Save the previous choice */ 30213850c04SHong Zhang PetscTrMallocOld = PetscTrMalloc; 303*92f119d6SBarry Smith PetscTrReallocOld = PetscTrRealloc; 30413850c04SHong Zhang PetscTrFreeOld = PetscTrFree; 30513850c04SHong Zhang PetscTrMalloc = PetscMallocAlign; 30613850c04SHong Zhang PetscTrFree = PetscFreeAlign; 307*92f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 308de1d6c17SHong Zhang } 30913850c04SHong Zhang PetscFunctionReturn(0); 31013850c04SHong Zhang } 31113850c04SHong Zhang 312de1d6c17SHong Zhang /*@C 313de1d6c17SHong Zhang PetscMallocResetDRAM - Reset the changes made by PetscMallocSetDRAM 314de1d6c17SHong Zhang 315de1d6c17SHong Zhang Not Collective 316de1d6c17SHong Zhang 317de1d6c17SHong Zhang Level: developer 318de1d6c17SHong Zhang 319de1d6c17SHong Zhang .seealso: PetscMallocSetDRAM() 320de1d6c17SHong Zhang @*/ 32113850c04SHong Zhang PetscErrorCode PetscMallocResetDRAM(void) 32213850c04SHong Zhang { 32313850c04SHong Zhang PetscFunctionBegin; 324de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 325de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 326de1d6c17SHong Zhang currentmktype = previousmktype; 327de1d6c17SHong Zhang #endif 328de1d6c17SHong Zhang } else { 32913850c04SHong Zhang /* Reset to the previous choice */ 33013850c04SHong Zhang PetscTrMalloc = PetscTrMallocOld; 331*92f119d6SBarry Smith PetscTrRealloc = PetscTrReallocOld; 33213850c04SHong Zhang PetscTrFree = PetscTrFreeOld; 333de1d6c17SHong Zhang } 33413850c04SHong Zhang PetscFunctionReturn(0); 33513850c04SHong Zhang } 336ba282f50SJed Brown 337ba282f50SJed Brown static PetscBool petscmalloccoalesce = 338ba282f50SJed Brown #if defined(PETSC_USE_MALLOC_COALESCED) 339ba282f50SJed Brown PETSC_TRUE; 340ba282f50SJed Brown #else 341ba282f50SJed Brown PETSC_FALSE; 342ba282f50SJed Brown #endif 343ba282f50SJed Brown 344ba282f50SJed Brown /*@C 345ba282f50SJed Brown PetscMallocSetCoalesce - Use coalesced malloc when allocating groups of objects 346ba282f50SJed Brown 347ba282f50SJed Brown Not Collective 348ba282f50SJed Brown 349ba282f50SJed Brown Input Parameters: 350ba282f50SJed Brown . coalesce - PETSC_TRUE to use coalesced malloc for multi-object allocation. 351ba282f50SJed Brown 352ba282f50SJed Brown Options Database Keys: 353ba282f50SJed Brown . -malloc_coalesce - turn coalesced malloc on or off 354ba282f50SJed Brown 355ba282f50SJed Brown Note: 356ba282f50SJed 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. 357*92f119d6SBarry Smith This function can only be called immediately after PetscInitialize() 358ba282f50SJed Brown 359ba282f50SJed Brown Level: developer 360ba282f50SJed Brown 361ba282f50SJed Brown .seealso: PetscMallocA() 362ba282f50SJed Brown @*/ 363ba282f50SJed Brown PetscErrorCode PetscMallocSetCoalesce(PetscBool coalesce) 364ba282f50SJed Brown { 365ba282f50SJed Brown PetscFunctionBegin; 366ba282f50SJed Brown petscmalloccoalesce = coalesce; 367ba282f50SJed Brown PetscFunctionReturn(0); 368ba282f50SJed Brown } 369ba282f50SJed Brown 370ba282f50SJed Brown /*@C 371ba282f50SJed Brown PetscMallocA - Allocate and optionally clear one or more objects, possibly using coalesced malloc 372ba282f50SJed Brown 373ba282f50SJed Brown Not Collective 374ba282f50SJed Brown 375ba282f50SJed Brown Input Parameters: 376ba282f50SJed Brown + n - number of objects to allocate (at least 1) 37789407d75SBarry Smith . clear - use calloc() to allocate space initialized to zero 378ba282f50SJed Brown . lineno - line number to attribute allocation (typically __LINE__) 379ba282f50SJed Brown . function - function to attribute allocation (typically PETSC_FUNCTION_NAME) 380ba282f50SJed Brown . filename - file name to attribute allocation (typically __FILE__) 381ba282f50SJed Brown - bytes0 - first of n object sizes 382ba282f50SJed Brown 383ba282f50SJed Brown Output Parameters: 384ba282f50SJed Brown . ptr0 - first of n pointers to allocate 385ba282f50SJed Brown 386ba282f50SJed Brown Notes: 387ba282f50SJed Brown This function is not normally called directly by users, but rather via the macros PetscMalloc1(), PetscMalloc2(), or PetscCalloc1(), etc. 388ba282f50SJed Brown 389ba282f50SJed Brown Level: developer 390ba282f50SJed Brown 391ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMalloc1(), PetscMalloc2(), PetscMalloc3(), PetscMalloc4(), PetscMalloc5(), PetscMalloc6(), PetscMalloc7(), PetscCalloc1(), PetscCalloc2(), PetscCalloc3(), PetscCalloc4(), PetscCalloc5(), PetscCalloc6(), PetscCalloc7(), PetscFreeA() 392ba282f50SJed Brown @*/ 393ba282f50SJed Brown PetscErrorCode PetscMallocA(int n,PetscBool clear,int lineno,const char *function,const char *filename,size_t bytes0,void *ptr0,...) 394ba282f50SJed Brown { 395ba282f50SJed Brown PetscErrorCode ierr; 396ba282f50SJed Brown va_list Argp; 397ba282f50SJed Brown size_t bytes[8],sumbytes; 398ba282f50SJed Brown void **ptr[8]; 399ba282f50SJed Brown int i; 400ba282f50SJed Brown 401ba282f50SJed Brown PetscFunctionBegin; 402ba282f50SJed Brown if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only 8 supported",n); 403ba282f50SJed Brown bytes[0] = bytes0; 404ba282f50SJed Brown ptr[0] = (void**)ptr0; 405ba282f50SJed Brown sumbytes = (bytes0 + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 406ba282f50SJed Brown va_start(Argp,ptr0); 407ba282f50SJed Brown for (i=1; i<n; i++) { 408ba282f50SJed Brown bytes[i] = va_arg(Argp,size_t); 409ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 410ba282f50SJed Brown sumbytes += (bytes[i] + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1); 411ba282f50SJed Brown } 412ba282f50SJed Brown va_end(Argp); 413ba282f50SJed Brown if (petscmalloccoalesce) { 414ba282f50SJed Brown char *p; 415071fcb05SBarry Smith ierr = (*PetscTrMalloc)(sumbytes,clear,lineno,function,filename,(void**)&p);CHKERRQ(ierr); 416ba282f50SJed Brown for (i=0; i<n; i++) { 417ba282f50SJed Brown *ptr[i] = bytes[i] ? p : NULL; 418ba282f50SJed Brown p = (char*)PetscAddrAlign(p + bytes[i]); 419ba282f50SJed Brown } 420ba282f50SJed Brown } else { 421ba282f50SJed Brown for (i=0; i<n; i++) { 422071fcb05SBarry Smith ierr = (*PetscTrMalloc)(bytes[i],clear,lineno,function,filename,(void**)ptr[i]);CHKERRQ(ierr); 423ba282f50SJed Brown } 424ba282f50SJed Brown } 425ba282f50SJed Brown PetscFunctionReturn(0); 426ba282f50SJed Brown } 427ba282f50SJed Brown 428ba282f50SJed Brown /*@C 429ba282f50SJed Brown PetscFreeA - Free one or more objects, possibly allocated using coalesced malloc 430ba282f50SJed Brown 431ba282f50SJed Brown Not Collective 432ba282f50SJed Brown 433ba282f50SJed Brown Input Parameters: 434ba282f50SJed Brown + n - number of objects to free (at least 1) 435ba282f50SJed Brown . lineno - line number to attribute deallocation (typically __LINE__) 436ba282f50SJed Brown . function - function to attribute deallocation (typically PETSC_FUNCTION_NAME) 437ba282f50SJed Brown . filename - file name to attribute deallocation (typically __FILE__) 438ba282f50SJed Brown - ptr0 ... - first of n pointers to free 439ba282f50SJed Brown 440ba282f50SJed Brown Note: 441071fcb05SBarry Smith This function is not normally called directly by users, but rather via the macros PetscFree(), PetscFree2(), etc. 442ba282f50SJed Brown 44389407d75SBarry Smith The pointers are zeroed to prevent users from accidently reusing space that has been freed. 44489407d75SBarry Smith 445ba282f50SJed Brown Level: developer 446ba282f50SJed Brown 447ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMallocA(), PetscFree1(), PetscFree2(), PetscFree3(), PetscFree4(), PetscFree5(), PetscFree6(), PetscFree7() 448ba282f50SJed Brown @*/ 449ba282f50SJed Brown PetscErrorCode PetscFreeA(int n,int lineno,const char *function,const char *filename,void *ptr0,...) 450ba282f50SJed Brown { 451ba282f50SJed Brown PetscErrorCode ierr; 452ba282f50SJed Brown va_list Argp; 453ba282f50SJed Brown void **ptr[8]; 454ba282f50SJed Brown int i; 455ba282f50SJed Brown 456ba282f50SJed Brown PetscFunctionBegin; 45789407d75SBarry Smith if (n > 8) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only up to 8 supported",n); 458ba282f50SJed Brown ptr[0] = (void**)ptr0; 459ba282f50SJed Brown va_start(Argp,ptr0); 460ba282f50SJed Brown for (i=1; i<n; i++) { 461ba282f50SJed Brown ptr[i] = va_arg(Argp,void**); 462ba282f50SJed Brown } 463ba282f50SJed Brown va_end(Argp); 464ba282f50SJed Brown if (petscmalloccoalesce) { 465ba282f50SJed Brown for (i=0; i<n; i++) { /* Find first nonempty allocation */ 466ba282f50SJed Brown if (*ptr[i]) break; 467ba282f50SJed Brown } 468ba282f50SJed Brown while (--n > i) { 469ba282f50SJed Brown *ptr[n] = NULL; 470ba282f50SJed Brown } 471c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 472ba282f50SJed Brown *ptr[n] = NULL; 473ba282f50SJed Brown } else { 474ba282f50SJed Brown while (--n >= 0) { 475c53cf884SJed Brown ierr = (*PetscTrFree)(*ptr[n],lineno,function,filename);CHKERRQ(ierr); 476ba282f50SJed Brown *ptr[n] = NULL; 477ba282f50SJed Brown } 478ba282f50SJed Brown } 479ba282f50SJed Brown PetscFunctionReturn(0); 480ba282f50SJed Brown } 481