C++内存对齐

C++ memory alignment

所以我读到,当在 C++ 中声明变量时,如果你想获得最佳的缓存读取,内存应该坚持其自然对齐。示例:

int a; // memory address should end in 0x0,0x4,0x8,0xC
int b[2]; // 8 bytes 0x0,0x8
int b[4]; // 16 bytes 0x0

但实际上这些变量并不遵循"natural alignment"规则,一个16字节的变量驻留在以0xC结尾的内存地址。这是为什么?

自然内存对齐一般是指单个变量的对齐,而不是变量数组。因此,一个 4 字节整数数组(正如您在上面显然拥有的)自然对齐到 4 字节边界而不是 16 字节边界。

自然内存对齐通常与 CPU 的 load/store 指令的架构和实现方式有关,而不是缓存行的大小。 CPU 不会一次加载整个数组(矢量加载除外)。因此 CPU 并不真正关心它加载的整数是否是数组的一部分。

同时加载小数组的矢量加载通常有更严格的对齐要求。例如,为了在 x86 上进行对齐矢量加载,项目必须对齐到 16 字节。

不保证对齐

C++ 不会对齐缓存行上的任何内容,因为无论出于何种意图和目的,它都不知道存在缓存。

如果您希望某些东西在 16 字节边界上对齐,请尝试 posix_memalign() 堆上的东西,或者(如果使用 GCC)堆栈上的东西,int x __attribute__ ((aligned (16)))。在 C++11 中有 alignas specifier.

不过我不知道如何调用 new() 并保证对齐。

根据英特尔® 64 位和 IA-32 架构优化参考手册(B.4.5.2 部分帮助),

32-byte AVX store instructions that span two pages require an assist that costs roughly 150 cycles.