1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay Code that allows a user to dictate what malloc() PETSc uses. 3e5c89e4eSSatish Balay */ 4d7976ebaSJed Brown #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for posix_memalign() */ 5c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 6ba282f50SJed Brown #include <stdarg.h> 7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 8e5c89e4eSSatish Balay #include <malloc.h> 9e5c89e4eSSatish Balay #endif 10de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 11ca8c994eSHong Zhang #include <errno.h> 12de1d6c17SHong Zhang #include <memkind.h> 139371c9d4SSatish Balay typedef enum { 149371c9d4SSatish Balay PETSC_MK_DEFAULT = 0, 159371c9d4SSatish Balay PETSC_MK_HBW_PREFERRED = 1 169371c9d4SSatish Balay } PetscMemkindType; 17e3acc61dSHong Zhang PetscMemkindType currentmktype = PETSC_MK_HBW_PREFERRED; 18e3acc61dSHong Zhang PetscMemkindType previousmktype = PETSC_MK_HBW_PREFERRED; 19de1d6c17SHong Zhang #endif 20e5c89e4eSSatish Balay /* 21e5c89e4eSSatish Balay We want to make sure that all mallocs of double or complex numbers are complex aligned. 22e5c89e4eSSatish Balay 1) on systems with memalign() we call that routine to get an aligned memory location 23e5c89e4eSSatish Balay 2) on systems without memalign() we 24e5c89e4eSSatish Balay - allocate one sizeof(PetscScalar) extra space 25e5c89e4eSSatish Balay - we shift the pointer up slightly if needed to get PetscScalar aligned 260700a824SBarry Smith - if shifted we store at ptr[-1] the amount of shift (plus a classid) 27e5c89e4eSSatish Balay */ 280700a824SBarry Smith #define SHIFT_CLASSID 456123 29e5c89e4eSSatish Balay 309371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t mem, PetscBool clear, int line, const char func[], const char file[], void **result) { 319371c9d4SSatish Balay if (!mem) { 329371c9d4SSatish Balay *result = NULL; 339371c9d4SSatish Balay return 0; 349371c9d4SSatish Balay } 357f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND) 36fc2a7144SHong Zhang { 377f18b027SJacob Faibussowitsch int err; 387f18b027SJacob Faibussowitsch 397f18b027SJacob Faibussowitsch err = memkind_posix_memalign(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT, result, PETSC_MEMALIGN, mem); 407f18b027SJacob Faibussowitsch PetscCheck(err != EINVAL, PETSC_COMM_SELF, PETSC_ERR_MEM, "Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 417f18b027SJacob Faibussowitsch if (err == ENOMEM) PetscInfo(NULL, "Memkind: fail to request HBW memory %.0f, falling back to normal memory\n", (PetscLogDouble)mem); 427f18b027SJacob Faibussowitsch PetscCheck(*result, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 439566063dSJacob Faibussowitsch if (clear) PetscCall(PetscMemzero(*result, mem)); 44fc2a7144SHong Zhang } 457f18b027SJacob Faibussowitsch #else /* PetscDefined(HAVE_MEMKIND) */ 467f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 477f18b027SJacob Faibussowitsch if (clear) *result = calloc(1 + mem / sizeof(int), sizeof(int)); 487f18b027SJacob Faibussowitsch else *result = malloc(mem); 497f18b027SJacob Faibussowitsch 507f18b027SJacob Faibussowitsch PetscCheck(*result, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 519566063dSJacob Faibussowitsch if (PetscLogMemory) PetscCall(PetscMemzero(*result, mem)); 52d7976ebaSJed Brown #elif PetscDefined(HAVE_POSIX_MEMALIGN) 53d7976ebaSJed Brown int ret = posix_memalign(result, PETSC_MEMALIGN, mem); 54d7976ebaSJed Brown PetscCheck(ret == 0, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 557f18b027SJacob Faibussowitsch if (clear || PetscLogMemory) PetscCall(PetscMemzero(*result, mem)); 56d7976ebaSJed Brown #else /* PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) || PetscDefined(HAVE_POSIX_MEMALIGN) */ 57e5c89e4eSSatish Balay { 5866c772faSBarry Smith int *ptr, shift; 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 } 677f18b027SJacob Faibussowitsch PetscCheck(ptr, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 6866c772faSBarry Smith 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; 739566063dSJacob Faibussowitsch if (PetscLogMemory) PetscCall(PetscMemzero(*result, mem)); 74e5c89e4eSSatish Balay } 75d7976ebaSJed Brown #endif /* PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) || PetscDefined(HAVE_POSIX_MEMALIGN) */ 767f18b027SJacob Faibussowitsch #endif /* PetscDefined(HAVE_MEMKIND) */ 77e5c89e4eSSatish Balay return 0; 78e5c89e4eSSatish Balay } 79e5c89e4eSSatish Balay 809371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *ptr, int line, const char func[], const char file[]) { 81f0ba7cfcSLisandro Dalcin if (!ptr) return 0; 827f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND) 83fc2a7144SHong Zhang memkind_free(0, ptr); /* specify the kind to 0 so that memkind will look up for the right type */ 847f18b027SJacob Faibussowitsch #else /* PetscDefined(HAVE_MEMKIND) */ 85d7976ebaSJed Brown #if (!(PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !PetscDefined(HAVE_POSIX_MEMALIGN)) 86f0ba7cfcSLisandro Dalcin { 87e5c89e4eSSatish Balay /* 88e5c89e4eSSatish Balay Previous int tells us how many ints the pointer has been shifted from 89e5c89e4eSSatish Balay the original address provided by the system malloc(). 90e5c89e4eSSatish Balay */ 917f18b027SJacob Faibussowitsch const int shift = *(((int *)ptr) - 1) - SHIFT_CLASSID; 927f18b027SJacob Faibussowitsch 937f18b027SJacob Faibussowitsch PetscCheck(shift <= PETSC_MEMALIGN - 1, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "Likely memory corruption in heap"); 947f18b027SJacob Faibussowitsch PetscCheck(shift >= 0, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "Likely memory corruption in heap"); 95e5c89e4eSSatish Balay ptr = (void *)(((int *)ptr) - shift); 96e5c89e4eSSatish Balay } 97f0ba7cfcSLisandro Dalcin #endif 98e5c89e4eSSatish Balay 997f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_FREE_RETURN_INT) 100e5c89e4eSSatish Balay int err = free(ptr); 1017f18b027SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "System free returned error %d\n", err); 102e5c89e4eSSatish Balay #else 103e5c89e4eSSatish Balay free(ptr); 104e5c89e4eSSatish Balay #endif 105fc2a7144SHong Zhang #endif 106e5c89e4eSSatish Balay return 0; 107e5c89e4eSSatish Balay } 108e5c89e4eSSatish Balay 1099371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result) { 110c22f1541SToby Isaac if (!mem) { 1117f18b027SJacob Faibussowitsch PetscCall(PetscFreeAlign(*result, line, func, file)); 112c22f1541SToby Isaac *result = NULL; 113c22f1541SToby Isaac return 0; 114c22f1541SToby Isaac } 1157f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND) 1167f18b027SJacob Faibussowitsch *result = memkind_realloc(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT, *result, mem); 117fc2a7144SHong Zhang #else 118d7976ebaSJed Brown #if (!(PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !PetscDefined(HAVE_POSIX_MEMALIGN)) 1193221ece2SMatthew G. Knepley { 1203221ece2SMatthew G. Knepley /* 1213221ece2SMatthew G. Knepley Previous int tells us how many ints the pointer has been shifted from 1223221ece2SMatthew G. Knepley the original address provided by the system malloc(). 1233221ece2SMatthew G. Knepley */ 1243221ece2SMatthew G. Knepley int shift = *(((int *)*result) - 1) - SHIFT_CLASSID; 1257f18b027SJacob Faibussowitsch PetscCheck(shift <= PETSC_MEMALIGN - 1, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "Likely memory corruption in heap"); 1267f18b027SJacob Faibussowitsch PetscCheck(shift >= 0, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "Likely memory corruption in heap"); 1273221ece2SMatthew G. Knepley *result = (void *)(((int *)*result) - shift); 1283221ece2SMatthew G. Knepley } 1293221ece2SMatthew G. Knepley #endif 1303221ece2SMatthew G. Knepley 131d7976ebaSJed Brown #if (PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) || PetscDefined(HAVE_POSIX_MEMALIGN) 13241605b92SBarry Smith *result = realloc(*result, mem); 1333221ece2SMatthew G. Knepley #else 1343221ece2SMatthew G. Knepley { 1353221ece2SMatthew G. Knepley /* 1363221ece2SMatthew G. Knepley malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 1373221ece2SMatthew G. Knepley */ 1383221ece2SMatthew G. Knepley int *ptr = (int *)realloc(*result, mem + 2 * PETSC_MEMALIGN); 1393221ece2SMatthew G. Knepley if (ptr) { 1403221ece2SMatthew G. Knepley int shift = (int)(((PETSC_UINTPTR_T)ptr) % PETSC_MEMALIGN); 1413221ece2SMatthew G. Knepley shift = (2 * PETSC_MEMALIGN - shift) / sizeof(int); 1423221ece2SMatthew G. Knepley ptr[shift - 1] = shift + SHIFT_CLASSID; 1433221ece2SMatthew G. Knepley ptr += shift; 1443221ece2SMatthew G. Knepley *result = (void *)ptr; 1453221ece2SMatthew G. Knepley } else { 1463221ece2SMatthew G. Knepley *result = NULL; 1473221ece2SMatthew G. Knepley } 1483221ece2SMatthew G. Knepley } 1493221ece2SMatthew G. Knepley #endif 150fc2a7144SHong Zhang #endif 1517f18b027SJacob Faibussowitsch PetscCheck(*result, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 152d7976ebaSJed Brown #if PetscDefined(HAVE_POSIX_MEMALIGN) 153c22f1541SToby Isaac /* There are no standard guarantees that realloc() maintains the alignment of memalign(), so I think we have to 154c22f1541SToby Isaac * realloc and, if the alignment is wrong, malloc/copy/free. */ 155c22f1541SToby Isaac if (((size_t)(*result)) % PETSC_MEMALIGN) { 156c22f1541SToby Isaac void *newResult; 1577f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND) 158fc2a7144SHong Zhang { 1592da392ccSBarry Smith int err; 1607f18b027SJacob Faibussowitsch err = memkind_posix_memalign(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT, &newResult, PETSC_MEMALIGN, mem); 1617f18b027SJacob Faibussowitsch PetscCheck(err != EINVAL, PETSC_COMM_SELF, PETSC_ERR_MEM, "Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()"); 1627f18b027SJacob Faibussowitsch if (err == ENOMEM) PetscInfo(NULL, "Memkind: fail to request HBW memory %.0f, falling back to normal memory\n", (PetscLogDouble)mem); 163fc2a7144SHong Zhang } 1647f18b027SJacob Faibussowitsch PetscCheck(newResult, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 165d7976ebaSJed Brown #else 166d7976ebaSJed Brown PetscCheck(posix_memalign(&newResult, PETSC_MEMALIGN, mem) == 0, PETSC_COMM_SELF, line, func, file, PETSC_ERR_MEM, PETSC_ERROR_INITIAL, "Memory requested %.0f", (PetscLogDouble)mem); 167d7976ebaSJed Brown #endif 1687f18b027SJacob Faibussowitsch PetscCall(PetscMemcpy(newResult, *result, mem)); 1697f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_FREE_RETURN_INT) 170c22f1541SToby Isaac { 171c22f1541SToby Isaac int err = free(*result); 1727f18b027SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, line, func, file, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, "System free returned error %d\n", err); 173c22f1541SToby Isaac } 174c22f1541SToby Isaac #else 175de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 176de1d6c17SHong Zhang memkind_free(0, *result); 177de1d6c17SHong Zhang #else 178c22f1541SToby Isaac free(*result); 179c22f1541SToby Isaac #endif 180de1d6c17SHong Zhang #endif 181c22f1541SToby Isaac *result = newResult; 182c22f1541SToby Isaac } 183c22f1541SToby Isaac #endif 1843221ece2SMatthew G. Knepley return 0; 1853221ece2SMatthew G. Knepley } 1863221ece2SMatthew G. Knepley 187071fcb05SBarry Smith PetscErrorCode (*PetscTrMalloc)(size_t, PetscBool, int, const char[], const char[], void **) = PetscMallocAlign; 188efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void *, int, const char[], const char[]) = PetscFreeAlign; 1893221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t, int, const char[], const char[], void **) = PetscReallocAlign; 190e5c89e4eSSatish Balay 19195c0884eSLisandro Dalcin PETSC_INTERN PetscBool petscsetmallocvisited; 192ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE; 193e5c89e4eSSatish Balay 194e5c89e4eSSatish Balay /*@C 1951d1a0024SBarry Smith PetscMallocSet - Sets the routines used to do mallocs and frees. 196*811af0c4SBarry Smith This routine MUST be called before `PetscInitialize()` and may be 197e5c89e4eSSatish Balay called only once. 198e5c89e4eSSatish Balay 199e5c89e4eSSatish Balay Not Collective 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay Input Parameters: 20292f119d6SBarry Smith + imalloc - the routine that provides the malloc (also provides calloc(), which is used depends on the second argument) 20392f119d6SBarry Smith . ifree - the routine that provides the free 20492f119d6SBarry Smith - iralloc - the routine that provides the realloc 205e5c89e4eSSatish Balay 206e5c89e4eSSatish Balay Level: developer 207e5c89e4eSSatish Balay 208*811af0c4SBarry Smith .seealso: `PetscMallocClear()` 209e5c89e4eSSatish Balay @*/ 2109371c9d4SSatish Balay PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t, PetscBool, int, const char[], const char[], void **), PetscErrorCode (*ifree)(void *, int, const char[], const char[]), PetscErrorCode (*iralloc)(size_t, int, const char[], const char[], void **)) { 211e5c89e4eSSatish Balay PetscFunctionBegin; 21208401ef6SPierre Jolivet PetscCheck(!petscsetmallocvisited || !(imalloc != PetscTrMalloc || ifree != PetscTrFree), PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot call multiple times"); 213e5c89e4eSSatish Balay PetscTrMalloc = imalloc; 214e5c89e4eSSatish Balay PetscTrFree = ifree; 21592f119d6SBarry Smith PetscTrRealloc = iralloc; 216e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_TRUE; 217e5c89e4eSSatish Balay PetscFunctionReturn(0); 218e5c89e4eSSatish Balay } 219e5c89e4eSSatish Balay 220e5c89e4eSSatish Balay /*@C 22192f119d6SBarry Smith PetscMallocClear - Resets the routines used to do mallocs and frees to the defaults. 222e5c89e4eSSatish Balay 223e5c89e4eSSatish Balay Not Collective 224e5c89e4eSSatish Balay 225e5c89e4eSSatish Balay Level: developer 226e5c89e4eSSatish Balay 227*811af0c4SBarry Smith Note: 228e5c89e4eSSatish Balay In general one should never run a PETSc program with different malloc() and 229e5c89e4eSSatish Balay free() settings for different parts; this is because one NEVER wants to 230e5c89e4eSSatish Balay free() an address that was malloced by a different memory management system 231e5c89e4eSSatish Balay 232*811af0c4SBarry Smith Called in `PetscFinalize()` so that if `PetscInitialize()` is called again it starts with a fresh slate of allocation information 23392f119d6SBarry Smith 234*811af0c4SBarry Smith .seealso: `PetscMallocSet` 235e5c89e4eSSatish Balay @*/ 2369371c9d4SSatish Balay PetscErrorCode PetscMallocClear(void) { 237e5c89e4eSSatish Balay PetscFunctionBegin; 238e5c89e4eSSatish Balay PetscTrMalloc = PetscMallocAlign; 239e5c89e4eSSatish Balay PetscTrFree = PetscFreeAlign; 24092f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 241e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_FALSE; 242e5c89e4eSSatish Balay PetscFunctionReturn(0); 243e5c89e4eSSatish Balay } 244b44d5720SBarry Smith 2459371c9d4SSatish Balay PetscErrorCode PetscMemoryTrace(const char label[]) { 246b44d5720SBarry Smith PetscLogDouble mem, mal; 247b44d5720SBarry Smith static PetscLogDouble oldmem = 0, oldmal = 0; 248b44d5720SBarry Smith 249b44d5720SBarry Smith PetscFunctionBegin; 2509566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&mem)); 2519566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&mal)); 252b44d5720SBarry Smith 2539566063dSJacob Faibussowitsch PetscCall(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)); 254b44d5720SBarry Smith oldmem = mem; 255b44d5720SBarry Smith oldmal = mal; 256b44d5720SBarry Smith PetscFunctionReturn(0); 257b44d5720SBarry Smith } 25813850c04SHong Zhang 259071fcb05SBarry Smith static PetscErrorCode (*PetscTrMallocOld)(size_t, PetscBool, int, const char[], const char[], void **) = PetscMallocAlign; 26092f119d6SBarry Smith static PetscErrorCode (*PetscTrReallocOld)(size_t, int, const char[], const char[], void **) = PetscReallocAlign; 26150a41461SHong Zhang static PetscErrorCode (*PetscTrFreeOld)(void *, int, const char[], const char[]) = PetscFreeAlign; 262de1d6c17SHong Zhang 263de1d6c17SHong Zhang /*@C 264*811af0c4SBarry Smith PetscMallocSetDRAM - Set `PetscMalloc()` to use DRAM. 265de1d6c17SHong Zhang If memkind is available, change the memkind type. Otherwise, switch the 266*811af0c4SBarry Smith current malloc and free routines to the `PetscMallocAlign()` and 267*811af0c4SBarry Smith `PetscFreeAlign()` (PETSc default). 268de1d6c17SHong Zhang 269de1d6c17SHong Zhang Not Collective 270de1d6c17SHong Zhang 271de1d6c17SHong Zhang Level: developer 272de1d6c17SHong Zhang 273*811af0c4SBarry Smith Note: 274de1d6c17SHong Zhang This provides a way to do the allocation on DRAM temporarily. One 275*811af0c4SBarry Smith can switch back to the previous choice by calling `PetscMallocReset()`. 276de1d6c17SHong Zhang 277db781477SPatrick Sanan .seealso: `PetscMallocReset()` 278de1d6c17SHong Zhang @*/ 2799371c9d4SSatish Balay PetscErrorCode PetscMallocSetDRAM(void) { 28013850c04SHong Zhang PetscFunctionBegin; 281de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 282de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 283de1d6c17SHong Zhang previousmktype = currentmktype; 284de1d6c17SHong Zhang currentmktype = PETSC_MK_DEFAULT; 285de1d6c17SHong Zhang #endif 286de1d6c17SHong Zhang } else { 28713850c04SHong Zhang /* Save the previous choice */ 28813850c04SHong Zhang PetscTrMallocOld = PetscTrMalloc; 28992f119d6SBarry Smith PetscTrReallocOld = PetscTrRealloc; 29013850c04SHong Zhang PetscTrFreeOld = PetscTrFree; 29113850c04SHong Zhang PetscTrMalloc = PetscMallocAlign; 29213850c04SHong Zhang PetscTrFree = PetscFreeAlign; 29392f119d6SBarry Smith PetscTrRealloc = PetscReallocAlign; 294de1d6c17SHong Zhang } 29513850c04SHong Zhang PetscFunctionReturn(0); 29613850c04SHong Zhang } 29713850c04SHong Zhang 298de1d6c17SHong Zhang /*@C 299*811af0c4SBarry Smith PetscMallocResetDRAM - Reset the changes made by `PetscMallocSetDRAM()` 300de1d6c17SHong Zhang 301de1d6c17SHong Zhang Not Collective 302de1d6c17SHong Zhang 303de1d6c17SHong Zhang Level: developer 304de1d6c17SHong Zhang 305db781477SPatrick Sanan .seealso: `PetscMallocSetDRAM()` 306de1d6c17SHong Zhang @*/ 3079371c9d4SSatish Balay PetscErrorCode PetscMallocResetDRAM(void) { 30813850c04SHong Zhang PetscFunctionBegin; 309de1d6c17SHong Zhang if (PetscTrMalloc == PetscMallocAlign) { 310de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND) 311de1d6c17SHong Zhang currentmktype = previousmktype; 312de1d6c17SHong Zhang #endif 313de1d6c17SHong Zhang } else { 31413850c04SHong Zhang /* Reset to the previous choice */ 31513850c04SHong Zhang PetscTrMalloc = PetscTrMallocOld; 31692f119d6SBarry Smith PetscTrRealloc = PetscTrReallocOld; 31713850c04SHong Zhang PetscTrFree = PetscTrFreeOld; 318de1d6c17SHong Zhang } 31913850c04SHong Zhang PetscFunctionReturn(0); 32013850c04SHong Zhang } 321ba282f50SJed Brown 322ba282f50SJed Brown static PetscBool petscmalloccoalesce = 323ba282f50SJed Brown #if defined(PETSC_USE_MALLOC_COALESCED) 324ba282f50SJed Brown PETSC_TRUE; 325ba282f50SJed Brown #else 326ba282f50SJed Brown PETSC_FALSE; 327ba282f50SJed Brown #endif 328ba282f50SJed Brown 329ba282f50SJed Brown /*@C 330ba282f50SJed Brown PetscMallocSetCoalesce - Use coalesced malloc when allocating groups of objects 331ba282f50SJed Brown 332ba282f50SJed Brown Not Collective 333ba282f50SJed Brown 334ba282f50SJed Brown Input Parameters: 335*811af0c4SBarry Smith . coalesce - `PETSC_TRUE` to use coalesced malloc for multi-object allocation. 336ba282f50SJed Brown 337ba282f50SJed Brown Options Database Keys: 338ba282f50SJed Brown . -malloc_coalesce - turn coalesced malloc on or off 339ba282f50SJed Brown 340*811af0c4SBarry Smith Notes: 341*811af0c4SBarry Smith PETSc uses coalesced malloc by default for optimized builds and not for debugging builds. 342*811af0c4SBarry Smith 343*811af0c4SBarry Smith This default can be changed via the command-line option -malloc_coalesce or by calling this function. 344*811af0c4SBarry Smith 345*811af0c4SBarry Smith This function can only be called immediately after `PetscInitialize()` 346ba282f50SJed Brown 347ba282f50SJed Brown Level: developer 348ba282f50SJed Brown 349db781477SPatrick Sanan .seealso: `PetscMallocA()` 350ba282f50SJed Brown @*/ 3519371c9d4SSatish Balay PetscErrorCode PetscMallocSetCoalesce(PetscBool coalesce) { 352ba282f50SJed Brown PetscFunctionBegin; 353ba282f50SJed Brown petscmalloccoalesce = coalesce; 354ba282f50SJed Brown PetscFunctionReturn(0); 355ba282f50SJed Brown } 356ba282f50SJed Brown 357ba282f50SJed Brown /*@C 358ba282f50SJed Brown PetscMallocA - Allocate and optionally clear one or more objects, possibly using coalesced malloc 359ba282f50SJed Brown 360ba282f50SJed Brown Not Collective 361ba282f50SJed Brown 362ba282f50SJed Brown Input Parameters: 363ba282f50SJed Brown + n - number of objects to allocate (at least 1) 36489407d75SBarry Smith . clear - use calloc() to allocate space initialized to zero 365ba282f50SJed Brown . lineno - line number to attribute allocation (typically __LINE__) 366ba282f50SJed Brown . function - function to attribute allocation (typically PETSC_FUNCTION_NAME) 367ba282f50SJed Brown . filename - file name to attribute allocation (typically __FILE__) 368ba282f50SJed Brown - bytes0 - first of n object sizes 369ba282f50SJed Brown 370ba282f50SJed Brown Output Parameters: 371ba282f50SJed Brown . ptr0 - first of n pointers to allocate 372ba282f50SJed Brown 373*811af0c4SBarry Smith Notes 374*811af0c4SBarry Smith This function is not normally called directly by users, but rather via the macros `PetscMalloc1()`, `PetscMalloc2()`, or `PetscCalloc1()`, etc. 375ba282f50SJed Brown 376ba282f50SJed Brown Level: developer 377ba282f50SJed Brown 378db781477SPatrick Sanan .seealso: `PetscMallocAlign()`, `PetscMallocSet()`, `PetscMalloc1()`, `PetscMalloc2()`, `PetscMalloc3()`, `PetscMalloc4()`, `PetscMalloc5()`, `PetscMalloc6()`, `PetscMalloc7()`, `PetscCalloc1()`, `PetscCalloc2()`, `PetscCalloc3()`, `PetscCalloc4()`, `PetscCalloc5()`, `PetscCalloc6()`, `PetscCalloc7()`, `PetscFreeA()` 379ba282f50SJed Brown @*/ 3809371c9d4SSatish Balay PetscErrorCode PetscMallocA(int n, PetscBool clear, int lineno, const char *function, const char *filename, size_t bytes0, void *ptr0, ...) { 381ba282f50SJed Brown va_list Argp; 382ba282f50SJed Brown size_t bytes[8], sumbytes; 383ba282f50SJed Brown void **ptr[8]; 384ba282f50SJed Brown int i; 385ba282f50SJed Brown 386ba282f50SJed Brown PetscFunctionBegin; 3877f18b027SJacob Faibussowitsch PetscCheck(n <= 8, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Attempt to allocate %d objects but only 8 supported", n); 388ba282f50SJed Brown bytes[0] = bytes0; 389ba282f50SJed Brown ptr[0] = (void **)ptr0; 390ba282f50SJed Brown sumbytes = (bytes0 + PETSC_MEMALIGN - 1) & ~(PETSC_MEMALIGN - 1); 391ba282f50SJed Brown va_start(Argp, ptr0); 392ba282f50SJed Brown for (i = 1; i < n; i++) { 393ba282f50SJed Brown bytes[i] = va_arg(Argp, size_t); 394ba282f50SJed Brown ptr[i] = va_arg(Argp, void **); 395ba282f50SJed Brown sumbytes += (bytes[i] + PETSC_MEMALIGN - 1) & ~(PETSC_MEMALIGN - 1); 396ba282f50SJed Brown } 397ba282f50SJed Brown va_end(Argp); 398ba282f50SJed Brown if (petscmalloccoalesce) { 399ba282f50SJed Brown char *p; 4009566063dSJacob Faibussowitsch PetscCall((*PetscTrMalloc)(sumbytes, clear, lineno, function, filename, (void **)&p)); 401640c8569SMatthew Woehlke if (p == NULL) { 402ad540459SPierre Jolivet for (i = 0; i < n; i++) *ptr[i] = NULL; 403640c8569SMatthew Woehlke } else { 404ba282f50SJed Brown for (i = 0; i < n; i++) { 405ba282f50SJed Brown *ptr[i] = bytes[i] ? p : NULL; 406ba282f50SJed Brown p = (char *)PetscAddrAlign(p + bytes[i]); 407ba282f50SJed Brown } 408640c8569SMatthew Woehlke } 409ba282f50SJed Brown } else { 41048a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*PetscTrMalloc)(bytes[i], clear, lineno, function, filename, (void **)ptr[i])); 411ba282f50SJed Brown } 412ba282f50SJed Brown PetscFunctionReturn(0); 413ba282f50SJed Brown } 414ba282f50SJed Brown 415ba282f50SJed Brown /*@C 416ba282f50SJed Brown PetscFreeA - Free one or more objects, possibly allocated using coalesced malloc 417ba282f50SJed Brown 418ba282f50SJed Brown Not Collective 419ba282f50SJed Brown 420ba282f50SJed Brown Input Parameters: 421ba282f50SJed Brown + n - number of objects to free (at least 1) 422ba282f50SJed Brown . lineno - line number to attribute deallocation (typically __LINE__) 423ba282f50SJed Brown . function - function to attribute deallocation (typically PETSC_FUNCTION_NAME) 424ba282f50SJed Brown . filename - file name to attribute deallocation (typically __FILE__) 425ba282f50SJed Brown - ptr0 ... - first of n pointers to free 426ba282f50SJed Brown 427*811af0c4SBarry Smith Notes: 428*811af0c4SBarry Smith This function is not normally called directly by users, but rather via the macros `PetscFree()`, `PetscFree2()`, etc. 429ba282f50SJed Brown 430a5b23f4aSJose E. Roman The pointers are zeroed to prevent users from accidentally reusing space that has been freed. 43189407d75SBarry Smith 432ba282f50SJed Brown Level: developer 433ba282f50SJed Brown 434db781477SPatrick Sanan .seealso: `PetscMallocAlign()`, `PetscMallocSet()`, `PetscMallocA()`, `PetscFree1()`, `PetscFree2()`, `PetscFree3()`, `PetscFree4()`, `PetscFree5()`, `PetscFree6()`, `PetscFree7()` 435ba282f50SJed Brown @*/ 4369371c9d4SSatish Balay PetscErrorCode PetscFreeA(int n, int lineno, const char *function, const char *filename, void *ptr0, ...) { 437ba282f50SJed Brown va_list Argp; 438ba282f50SJed Brown void **ptr[8]; 439ba282f50SJed Brown int i; 440ba282f50SJed Brown 441ba282f50SJed Brown PetscFunctionBegin; 4427f18b027SJacob Faibussowitsch PetscCheck(n <= 8, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Attempt to allocate %d objects but only up to 8 supported", n); 443ba282f50SJed Brown ptr[0] = (void **)ptr0; 444ba282f50SJed Brown va_start(Argp, ptr0); 445ad540459SPierre Jolivet for (i = 1; i < n; i++) ptr[i] = va_arg(Argp, void **); 446ba282f50SJed Brown va_end(Argp); 447ba282f50SJed Brown if (petscmalloccoalesce) { 448ba282f50SJed Brown for (i = 0; i < n; i++) { /* Find first nonempty allocation */ 449ba282f50SJed Brown if (*ptr[i]) break; 450ba282f50SJed Brown } 451ad540459SPierre Jolivet while (--n > i) *ptr[n] = NULL; 4529566063dSJacob Faibussowitsch PetscCall((*PetscTrFree)(*ptr[n], lineno, function, filename)); 453ba282f50SJed Brown *ptr[n] = NULL; 454ba282f50SJed Brown } else { 455ba282f50SJed Brown while (--n >= 0) { 4569566063dSJacob Faibussowitsch PetscCall((*PetscTrFree)(*ptr[n], lineno, function, filename)); 457ba282f50SJed Brown *ptr[n] = NULL; 458ba282f50SJed Brown } 459ba282f50SJed Brown } 460ba282f50SJed Brown PetscFunctionReturn(0); 461ba282f50SJed Brown } 462