为什么访问非自然对齐内存的执行效率更低?
内存自然对齐规则答疑
假设我们使用的是每次固定读取8字节内存的64bit CPU,当前需要存储一个4 bytes的int变量。根据自然对齐的定义,4字节对象需要对齐到4的倍数地址(例如0x0000、0x0004)。那为什么不能将该int存储在0x0001这类地址呢?按照我的理解,CPU一次读取8字节的情况下,从0x0000地址读取一次就能拿到存储在0x0001的int,这种场景下为什么还需要遵循自然对齐规则?
你提到的单一场景确实存在:存在0x0001地址的4字节int刚好完全落在0x0000~0x0007这8字节的单次读取块中,仅需一次读操作就能拿到全部数据。但对齐规则的必要性远不止单次读取次数这一点,核心原因包括以下几点:
- 数据提取的额外开销:即便一次读入了完整的8字节,不对齐存储的int也不会刚好落在CPU可直接使用的低4位或高4位区间,需要额外做移位、掩码操作才能把分散的4个字节拼接成合法的int值,这部分操作会额外消耗时钟周期。对齐存储的int无需额外处理,读取后可直接使用,效率更高。
- 避免跨访问块的二次读取:你举的例子属于幸运场景,如果4字节int存储在
0x0006这类地址,2个字节落在0x0000~0x0007块,剩下2个字节落在0x0008~0x000F块,CPU必须执行两次8字节读取才能拿到完整的int。要是这两个块刚好属于不同的缓存行甚至不同内存页,开销会被进一步放大,极端情况还可能触发缺页异常。自然对齐可以保证所有4字节int永远不会跨两个8字节访问块,从根源上杜绝了这类问题。 - 原子性保证与架构兼容性:绝大多数CPU架构默认只对对齐的内存访问提供原子性保障,比如要原子修改这个4字节int,对齐场景下一次写操作就能完成且不会被打断。不对齐的访问哪怕数据落在同一个8字节块中,很多架构也不保证原子性,多线程场景下容易出现数据竞争问题。另外部分RISC架构直接不支持不对齐的内存访问,碰到这类地址直接抛出异常终止程序,遵循对齐规则能保证代码的跨架构兼容性。
- 复合类型布局一致性:对于数组、结构体这类包含多个元素的复合类型,遵循对齐规则可以保证每个元素都默认落在合法的对齐地址上,编译器不需要动态计算偏移,既方便编译优化,也能避免手动操作内存时出现偏移计算错误。
内容的提问来源于stack exchange,提问作者user12599964
相关产品推荐
相关产品推荐

