有一些选项可用于获取对齐的内存块,但它们非常相似,问题主要归结为您所针对的语言标准和平台。
C11
void * aligned_alloc (size_t alignment, size_t size)
POSIX
int posix_memalign (void **memptr, size_t alignment, size_t size)
窗
void * _aligned_malloc(size_t size, size_t alignment);
当然,它也总是可以手动对齐。
英特尔提供另一种选择。
英特尔
void* _mm_malloc (int size, int align)
void _mm_free (void *p)
根据英特尔发布的源代码,这似乎是分配工程师喜欢的对齐内存的方法,但我找不到任何将其与其他方法进行比较的文档。我发现的最接近的只是承认存在其他对齐的内存分配例程。
要动态分配一段对齐的内存,请使用posix_memalign, 这是由GCC和英特尔编译器支持的。好处 使用它是因为您不必更改内存处理API。 您可以像往常一样使用free()。但要注意 参数配置文件:
int posix_memalign(void ** memptr,size_t align,size_t size);
英特尔编译器还提供另一组内存分配 蜜蜂。 C / C ++程序员可以使用_mm_malloc和_mm_free进行分配 和自由对齐的内存块。例如,以下内容 语句请求一个64字节对齐的内存块,用于8个浮点 元件。
farray =(float *)__ mm_malloc(8 * sizeof(float),64);
必须使用_mm_malloc分配的内存 _mm_free。在使用_mm_malloc分配的内存上调用free或在使用malloc分配的内存上调用_mm_free将导致不可预测的行为。
与用户的观点明显不同的是_mm_malloc
需要直接的CPU和编译器支持,并且_mm_malloc
分配的内存必须使用_mm_free
释放。鉴于这些缺点,使用_mm_malloc?
的原因是什么?它有轻微的性能优势吗?历史事故?
答案 0 :(得分:25)
英特尔编译器支持POSIX(Linux)和非POSIX(Windows)操作系统,因此不能依赖POSIX或Windows功能。因此,选择了特定于编译器但与OS无关的解决方案。
C11是一个很好的解决方案,但微软甚至还不支持C99,所以谁知道他们是否会支持C11。
更新:与C11 / POSIX / Windows分配功能不同,ICC内在函数包括释放功能。这允许此API使用默认的单独的堆管理器。我不知道是否/何时确实这样做,但支持这种模式会很有用。
免责声明:我为英特尔工作但对这些决定没有特别的了解,这些决定早在我加入公司之前就已经发生了。
答案 1 :(得分:5)
可以使用现在不会使用标识符_mm_alloc
和_mm_free
的现有C编译器,并使用将根据需要运行的名称定义函数。这可以通过将_mm_alloc
函数作为malloc()
上的包装器来完成,该函数要求稍微超大的分配,并构造一个指针,指向其中至少一个字节的第一个适当对齐的地址。开始,并存储紧接在该地址之前跳过的字节数,或者让_mm_malloc
从malloc()
请求大块内存,然后逐个分配它们。在任何情况下,_mm_malloc()
返回的指针都不是free()
通常知道如何做任何事情的指针;调用_mm_free
会使用紧接在分配之前的字节,以帮助查找从malloc
收到的分配的真正开始,然后传递free
。
如果允许对齐分配函数使用malloc
和free
函数的内部,则可以省去额外的包装层。可以编写包含_mm_alloc()
/ _mm_free()
malloc
/ free
的{{1}} / _mm_alloc()
函数而不了解其内部信息,但它要求malloc
保留簿记信息与free
/ malloc
使用的内容分开。
如果对齐分配函数的作者知道如何实现free
和free
,则通常可以协调所有分配/自由函数的设计,以便{{1} }可以区分各种分配并适当地处理它们。但是,没有单个对齐分配实现可用于所有malloc
/ free
实现。
我建议最便携的编写代码的方法可能是选择一些其他地方没有使用的符号用于你自己的分配和自由函数,这样你就可以说,例如。
#define a_alloc(align,sz) _mm_alloc((align),(sz))
#define a_free(ptr) _mm_free((ptr))
支持该编译器,或
static inline void *aa_alloc(int align, int size)
{
void *ret=0;
posix_memalign(&ret, align, size); // Guessing here
return ret;
}
#define a_alloc(align,sz) aa_alloc((align),(sz))
#define a_free(ptr) free((ptr))
在Posix系统等上对于每个系统,应该可以定义将产生必要行为的宏或函数[我认为使用宏可能比使用宏有时更好,有时使用宏,有时候是函数,以便允许#if defined macroname
来测试事物是否已定义]。
答案 2 :(得分:4)
_mm_malloc似乎是在有标准的aligned_alloc函数之前创建的,需要使用_mm_free是实现的一个怪癖。
我的猜测是,与使用posix_memalign不同,它不需要过度分配以保证对齐,而是使用单独的对齐感知分配器。这将在分配具有与默认对齐方式不同的对齐类型(通常为8或16个字节)时节省内存。