是否有 linux 相当于 _aligned_realloc
Is there a linux equivalent of _aligned_realloc
是否有 _aligned_realloc 的 linux 等价物?
我想使用 realloc,这样我就不必每次调整数据大小时都 memcpy 数据。我被mmap困住了吗?我只使用过一次 mmap 是否有推荐的实现内存大小的方法?我假设我不能将 mmap 与 aligned_alloc 混合使用,并且我必须在第一次调整大小时执行 memcpy? (或始终使用 mmap)
下面的 realloc 并不总是对齐的。我使用 gcc 和 clang
在(64 位)linux 下进行了测试
#include<cstdlib>
#include<cstdio>
#define ALIGNSIZE 64
int main()
{
for(int i = 0; i<10; i++)
{
void *p = aligned_alloc(ALIGNSIZE, 4096);
void *p2 = realloc(p, 4096+2048); //This doesn't always align
//void *p3 = aligned_alloc(ALIGNSIZE, 4096/24); //Doesn't need this line to make it unaligned.
if (((long)p & (ALIGNSIZE-1)) != 0 || ((long)p2 & (ALIGNSIZE-1)) != 0)
printf("%d %d %d\n", i, ((long)p & (ALIGNSIZE-1)) != 0, ((long)p2 & (ALIGNSIZE-1)) != 0);
}
}
不,C++、POSIX 标准和 GNU C 库中都没有标准替代方案。
这是仅使用标准函数的概念证明:
void*
aligned_realloc_optimistic(
void* ptr, std::size_t new_size, std::size_t alignment)
{
void* reallocated = std::realloc(ptr, new_size);
return is_aligned(reallocated, alignment) // see below
? reallocated
: aligned_realloc_pessimistic(reallocated, new_size, new_size, alignment);
// see below
}
正如评论中所指出的:这有一个警告,即在最坏的情况下 std::realloc
可能无法重用分配并且也恰好 return 一个未对齐的指针,然后我们分配两次。
我们可以通过无条件分配、复制和释放来跳过重新分配的尝试,这消除了双重分配的最坏情况和没有分配的最佳情况:
void*
aligned_realloc_pessimistic(
void* ptr, std::size_t new_size, std::size_t old_size, std::size_t alignment)
{
void* aligned = std::aligned_alloc(alignment, new_size);
std::memcpy(aligned, ptr, old_size);
std::free(ptr);
return aligned;
}
这样做的明显问题是我们必须知道常规重新分配不需要的旧大小。
依靠系统特定的功能,我们可以保持避免分配的最佳情况,避免双重分配,也不需要知道旧的大小:
void*
aligned_realloc_glibc(
void* ptr, std::size_t new_size, std::size_t alignment)
{
auto old_size = malloc_usable_size(ptr); // GNU extension
return old_size >= new_size && is_aligned(ptr, alignment)
? ptr
: aligned_realloc_pessimistic(ptr, new_size, old_size, alignment);
}
上面用到的辅助函数:
bool is_aligned(void* ptr, std::size_t alignment)
{
std::size_t space = 1;
return std::align(alignment, space, ptr, space);
}
Am I stuck with mmap?
如果你想要最大的灵活性,没有比使用平台的低级分配机制更好的方法了。
在这种情况下,您需要 mremap()
,可能需要 MREMAP_MAYMOVE
。它完全满足您的需求(如果您需要比页面更大的对齐方式,则需要手动处理)。
是否有 _aligned_realloc 的 linux 等价物?
我想使用 realloc,这样我就不必每次调整数据大小时都 memcpy 数据。我被mmap困住了吗?我只使用过一次 mmap 是否有推荐的实现内存大小的方法?我假设我不能将 mmap 与 aligned_alloc 混合使用,并且我必须在第一次调整大小时执行 memcpy? (或始终使用 mmap)
下面的 realloc 并不总是对齐的。我使用 gcc 和 clang
在(64 位)linux 下进行了测试#include<cstdlib>
#include<cstdio>
#define ALIGNSIZE 64
int main()
{
for(int i = 0; i<10; i++)
{
void *p = aligned_alloc(ALIGNSIZE, 4096);
void *p2 = realloc(p, 4096+2048); //This doesn't always align
//void *p3 = aligned_alloc(ALIGNSIZE, 4096/24); //Doesn't need this line to make it unaligned.
if (((long)p & (ALIGNSIZE-1)) != 0 || ((long)p2 & (ALIGNSIZE-1)) != 0)
printf("%d %d %d\n", i, ((long)p & (ALIGNSIZE-1)) != 0, ((long)p2 & (ALIGNSIZE-1)) != 0);
}
}
不,C++、POSIX 标准和 GNU C 库中都没有标准替代方案。
这是仅使用标准函数的概念证明:
void*
aligned_realloc_optimistic(
void* ptr, std::size_t new_size, std::size_t alignment)
{
void* reallocated = std::realloc(ptr, new_size);
return is_aligned(reallocated, alignment) // see below
? reallocated
: aligned_realloc_pessimistic(reallocated, new_size, new_size, alignment);
// see below
}
正如评论中所指出的:这有一个警告,即在最坏的情况下 std::realloc
可能无法重用分配并且也恰好 return 一个未对齐的指针,然后我们分配两次。
我们可以通过无条件分配、复制和释放来跳过重新分配的尝试,这消除了双重分配的最坏情况和没有分配的最佳情况:
void*
aligned_realloc_pessimistic(
void* ptr, std::size_t new_size, std::size_t old_size, std::size_t alignment)
{
void* aligned = std::aligned_alloc(alignment, new_size);
std::memcpy(aligned, ptr, old_size);
std::free(ptr);
return aligned;
}
这样做的明显问题是我们必须知道常规重新分配不需要的旧大小。
依靠系统特定的功能,我们可以保持避免分配的最佳情况,避免双重分配,也不需要知道旧的大小:
void*
aligned_realloc_glibc(
void* ptr, std::size_t new_size, std::size_t alignment)
{
auto old_size = malloc_usable_size(ptr); // GNU extension
return old_size >= new_size && is_aligned(ptr, alignment)
? ptr
: aligned_realloc_pessimistic(ptr, new_size, old_size, alignment);
}
上面用到的辅助函数:
bool is_aligned(void* ptr, std::size_t alignment)
{
std::size_t space = 1;
return std::align(alignment, space, ptr, space);
}
Am I stuck with mmap?
如果你想要最大的灵活性,没有比使用平台的低级分配机制更好的方法了。
在这种情况下,您需要 mremap()
,可能需要 MREMAP_MAYMOVE
。它完全满足您的需求(如果您需要比页面更大的对齐方式,则需要手动处理)。