结构与高速缓存行的 x86 内存对齐?
x86 Memory Alignment of struct vs. cache line?
最近我正在开发一个“搜索系统”,memory/cache 性能方面的一些事情让我很困惑。
假设我的机器信息:x86 arch(L1-3 缓存,64 字节缓存行),linux OS
CPU每次读取64字节(缓存行),那么CPU从内存地址(到缓存)读取数据总是64倍数吗?比如0x00(到0x3F),0x40(到 0x7f)。如果我需要位于 0x20 的数据(int32_t),那么系统仍然需要加载 0x00--0x3F。
这个案例怎么样:
struct Obj{int64_t a[5];char b[2];};
然后定义
int64_t c[5]; Obj obj; int64_t d;
虚拟内存(还是物理内存?)会这样组织吗?
我认为您可能遗漏的部分是编译器对各种类型强加的对齐要求。
整数类型通常对齐到它们自身大小的倍数(例如 64 位整数将对齐到 8 个字节);所谓的“自然对齐”。这不是 x86 的严格架构要求;未对齐的加载和存储仍然有效,但由于它们效率较低,编译器更愿意避免它们。
聚合,如 struct
,根据其成员的最高对齐要求进行对齐,如果需要,将在成员之间插入填充以确保每个成员都正确对齐。还将在末尾添加填充,以便 struct
的整体大小是其所需对齐方式的倍数。
因此在您的示例中,struct Obj
的对齐方式为 8,其大小将四舍五入为 48(末尾有 6 个字节的填充)。所以不需要在 c[4]
之后插入 24 个字节的填充(我认为你的意思是在地址 40-63 处写入填充);您的obj
可以放在地址40。d
然后可以放在地址88。
请注意,其中 none 与缓存行大小有关。默认情况下,对象不会与缓存行对齐,但“自然对齐”将确保没有整数加载或存储必须跨越缓存行。
最近我正在开发一个“搜索系统”,memory/cache 性能方面的一些事情让我很困惑。 假设我的机器信息:x86 arch(L1-3 缓存,64 字节缓存行),linux OS
CPU每次读取64字节(缓存行),那么CPU从内存地址(到缓存)读取数据总是64倍数吗?比如0x00(到0x3F),0x40(到 0x7f)。如果我需要位于 0x20 的数据(int32_t),那么系统仍然需要加载 0x00--0x3F。
这个案例怎么样:
struct Obj{int64_t a[5];char b[2];};
然后定义
int64_t c[5]; Obj obj; int64_t d;
虚拟内存(还是物理内存?)会这样组织吗?
我认为您可能遗漏的部分是编译器对各种类型强加的对齐要求。
整数类型通常对齐到它们自身大小的倍数(例如 64 位整数将对齐到 8 个字节);所谓的“自然对齐”。这不是 x86 的严格架构要求;未对齐的加载和存储仍然有效,但由于它们效率较低,编译器更愿意避免它们。
聚合,如 struct
,根据其成员的最高对齐要求进行对齐,如果需要,将在成员之间插入填充以确保每个成员都正确对齐。还将在末尾添加填充,以便 struct
的整体大小是其所需对齐方式的倍数。
因此在您的示例中,struct Obj
的对齐方式为 8,其大小将四舍五入为 48(末尾有 6 个字节的填充)。所以不需要在 c[4]
之后插入 24 个字节的填充(我认为你的意思是在地址 40-63 处写入填充);您的obj
可以放在地址40。d
然后可以放在地址88。
请注意,其中 none 与缓存行大小有关。默认情况下,对象不会与缓存行对齐,但“自然对齐”将确保没有整数加载或存储必须跨越缓存行。