为什么要使用_mm_malloc? (与_aligned_malloc,alligned_alloc或posix_memalign相对)

获取对齐的内存块有几个选项,但它们非常相似,问题主要归结为您所针对的语言标准和平台。

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) 

根据英特尔发布的源代码,这似乎是分配工程师喜欢的对齐内存的方法,但我找不到任何将其与其他方法进行比较的文档。 我发现的最接近的只是承认存在其他对齐的内存分配例程。

https://software.intel.com/en-us/articles/memory-management-for-optimal-performance-on-intel-xeon-phi-coprocessor-alignment-and

要动态分配一块对齐的内存,请使用posix_memalign,它由GCC和Intel Compiler支持。 使用它的好处是您不必更改内存处理API。 您可以像往常一样使用free()。 但要注意参数配置文件:

int posix_memalign(void ** memptr,size_t align,size_t size);

英特尔编译器还提供另一组内存分配API。 C / C ++程序员可以使用_mm_malloc和_mm_free来分配和释放对齐的内存块。 例如,以下语句为8个浮点元素请求64字节对齐的内存块。

farray =(float *)__ mm_malloc(8 * sizeof(float),64);

必须使用_mm_free释放使用_mm_malloc分配的内存。 在使用_mm_malloc分配的内存上调用free或在使用malloc分配的内存上调用_mm_free将导致不可预测的行为。

从用户的角度来看,明显的区别是_mm_malloc需要直接的CPU和编译器支持,并且必须使用_mm_free释放使用_mm_free分配的内存。 鉴于这些缺点,使用_mm_malloc?的原因是什么_mm_malloc? 它有轻微的性能优势吗? 历史事故?

英特尔编译器支持POSIX(Linux)和非POSIX(Windows)操作系统,因此不能依赖POSIX或Windowsfunction。 因此,选择了特定于编译器但与OS无关的解决方案。

C11是一个很好的解决方案,但微软甚至还不支持C99,所以谁知道他们是否会支持C11。

更新:与C11 / POSIX / Windows分配function不同,ICC内在函数包括释放function。 这允许此API使用默认的单独的堆管理器。 我不知道它是否/何时确实这样做,但支持这个模型会很有用。

免责声明:我为英特尔工作,但对这些决定没有特别的了解,这些决定早在我加入公司之前就已经发生了。

可以使用现在不会使用标识符_mm_alloc_mm_free的现有C编译器,并使用将根据需要运行的名称定义函数。 这可以通过将_mm_alloc函数作为malloc()的包装器来完成,该函数要求稍微过大的分配,并构造指向其中第一个适当对齐的地址的指针,该地址距离开头至少有一个字节,并存储数字在该地址之前立即跳过的字节数,或者让_mm_mallocmalloc()请求大块内存然后_mm_malloc分配它们。 在任何情况下, _mm_malloc()返回的指针都不是free()通常知道如何做任何事情的指针; 调用_mm_free将使用紧接在分配之前的字节作为辅助来查找从malloc接收的分配的真正开始,然后传递它是free

但是,如果允许对齐分配函数使用mallocfree函数的内部,则可以省去额外的包装层。 编写包含malloc / free _mm_alloc() / _mm_free()函数是可能的,而不知道它们的内部结构,但它要求_mm_alloc()保留与malloc / free使用的信息分开的簿记信息。

如果对齐分配函数的作者知道如何实现mallocfree ,则通常可以协调所有分配/自由函数的设计,以便free可以区分所有类型的分配并适当地处理它们。 但是,没有单个对齐分配实现可用于所有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来测试事物是否已定义]。

似乎在有标准的aligned_alloc函数之前已经创建了_mm_malloc,并且需要使用_mm_free是实现的一个怪癖。

我的猜测是,与使用posix_memalign不同,它不需要过度分配以保证对齐,而是使用单独的对齐感知分配器。 这将在分配具有与默认对齐方式不同的对齐类型(通常为8或16个字节)时节省内存。