为什么 malloc 是 16 字节对齐的?

Why is malloc 16 byte aligned?

GNU 文档指出 malloc 在 64 位系统上与 16 字节的倍数对齐。这是为什么?

如果我的理解是正确的,寄存器和所有指令都对最大 8 字节宽的值进行操作。因此,似乎需要 8 字节对齐。

备注:

x86_64 使用 xmm 寄存器(大量使用 -- 所有 fp 内容都在 xmm 寄存器中完成,因为 8087 fp 寄存器已弃用),并且 xmm 寄存器需要 16 字节对齐才能(高效)访问。

所以 x86_64 中的大部分内容(包括由 malloc 分配的堆栈和堆)都组织为始终 16 字节对齐,因此编译器始终可以自由使用 'aligned' 指令涉及 xmm 寄存器,不需要使用(可能较慢)未对齐指令。

在较新的硬件上,编译器甚至不需要麻烦使用对齐指令——当内存对齐时,未对齐指令与对齐指令一样快。

x86-64 System V 使用 x87 作为 long double,80 位类型。并将其填充为 16 字节,使用 alignof(long double) == 16 因此 long double 永远不会跨越缓存行边界。 (无论是否值得,IDK;SSE2 可能是廉价支持 16 字节对齐的动机之一)。

但是无论如何,SSE 的东西并不是对 alignof(max_align_t) == 16 的唯一贡献(它设置了允许 malloc return 的最小对齐)。

__m128i 的存在根本不会直接max_align_t 有贡献,例如 32 位 C 实现以较低的 malloc 保证支持它.当然,支持 AVX 的系统上 __m256i 的存在并没有增加分配器的对齐保证。 ()。但对于自动和手动矢量化来说,malloced 内存对于 movaps 来说足够对齐,尤其是在较旧的 CPU 上,当 x86-64 是新的并且 movups 即使内存对齐时也会受到惩罚。如果编译器只看到 float*,则很难利用该保证,您可以将指针传递到分配的中间。但是,如果它可以看到输出数组的 malloc,它就知道如果自动向量化写入新分配的 space.

的循环,它将对齐

顺便说一句,ISO C 会让 malloc 用于小分配(比如 1 到 15 个字节)return 对齐较少 space,因为 space 仍然可以用于容纳任何适合的类型。在 C 语言中,对象不能要求比其大小更多的对齐方式。 (例如,你不能 typedef 一个 int 总是必须在缓存行的开头,或者如果你做 sizeof 用填充扩展。)