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

Pra*_*tic 29 c memory-management intel dynamic-memory-allocation

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

C11

void * aligned_alloc (size_t alignment, size_t size)
Run Code Online (Sandbox Code Playgroud)

POSIX

int posix_memalign (void **memptr, size_t alignment, size_t size)
Run Code Online (Sandbox Code Playgroud)

视窗

void * _aligned_malloc(size_t size, size_t alignment);
Run Code Online (Sandbox Code Playgroud)

当然,手动对齐也是一种选择.

英特尔提供另一种选择

英特尔

void* _mm_malloc (int size, int align)
void _mm_free (void *p)
Run Code Online (Sandbox Code Playgroud)

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

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_malloc必须被释放_mm_free.鉴于这些缺点,使用_mm_malloc?它的原因是什么?它有轻微的性能优势吗?历史事故?

Jef*_*eff 26

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

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

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

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

  • 哦,呵呵,其实很简单,很有道理!很容易对您自己的操作系统产生短视而没有意识到这些事情。 (3认同)

sup*_*cat 5

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

但是,如果允许对齐分配函数使用mallocfree函数的内部,则可以消除对额外的包装层的需要.可以编写_mm_alloc()/ _mm_free()函数包装malloc/ 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))
Run Code Online (Sandbox Code Playgroud)

在支持它的编译器上,或

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))
Run Code Online (Sandbox Code Playgroud)

在Posix系统等上.对于每个系统,应该可以定义将产生必要行为的宏或函数[我认为使用宏可能比使用宏有时更好,有时使用宏,有时候还有函数,以便#if defined macroname测试是否事情已定义].