【问题标题】:Confused about data alignment对数据对齐感到困惑
【发布时间】:2013-05-09 10:42:58
【问题描述】:

我试图弄清楚为什么需要数据对齐/填充。来自维基百科:

“当现代计算机读取或写入内存地址时,它将以字大小的块执行此操作”

但我可以使用 x86 的 movb 指令以字节分辨率清晰地往返移动数据。我在这里错过了什么?

【问题讨论】:

    标签: architecture x86 x86-64


    【解决方案1】:

    字对齐的内存访问比字节对齐的快得多。这使得传输大块数据的速度更快。您可以寻址单个字节,但可能会从内存中读取一个字并在内部减少为一个字节。这会使访问速度变慢。

    【讨论】:

    • 啊,好吧——所以它不是强制计算机以字块读/写的硬件限制——这是一个优化问题。这有很大帮助。谢谢!
    • 不,单字节加载并不比字加载慢。并且不必访问包含的单词。您可以通过对将[buf + 0] 复制到[buf + 1] 的asm 循环进行基准测试来证明这一点:字节加载旁边的字节存储。如果加载必须等待存储,则循环将成为存储转发延迟的瓶颈(在 Haswell 上约为 5 个周期),因为副本使其循环承载。但是字节加载独立于同一个字中的字节存储,因此循环仅在每个时钟一次存储上出现瓶颈,而不是每 5 个时钟一次。
    • 可能很慢的是未对齐的字访问,而不是字节访问。
    【解决方案2】:

    这是一个常见的误解。 字节访问需要对该缓存行的包含 32 位或 64 位块(或用于未缓存访问的内存)进行读取-修改-写入。见Can modern x86 hardware not store a single byte to memory?

    单字节访问自动为naturally aligned。这意味着与访问的宽度对齐,因此它不会跨越任何比自身更宽的边界。


    一个字加载或存储仍然是一个单一的事务,除非它跨越缓存线边界(在这种情况下,CPU 内部必须访问两个缓存线的相关部分)。因此,该引用仅适用于机器字大小的访问。 (注意,英特尔术语中的word 是 16 位,而不是现代 x86 CPU 的寄存器或总线宽度。这就是我在上一句中说“机器字”的原因。)

    因此向 C 中的结构添加填充不是因为字节访问对于字节大小的字段效率低下,而是为了宽于一个字节的对象自然对齐(例如,int 跟随char 在结构中)。

    与字节访问不同,一些相对常见的平台支持或不支持直接非对齐访问,在那些支持的平台上,非对齐访问可能效率较低,尤其是在跨越缓存行时。 C 编译器将结构视为对其最对齐的成员具有对齐要求。例如由于 double 成员,intchardouble 的结构将具有 64 位对齐,因此相对于结构对齐 double 的填充也将在绝对意义上对齐它,所以结构成员总是保持自然对齐。

    即使在没有未对齐访问惩罚的假设平台上,具有未对齐对象也会使依赖原子读写的memory models 的实现大大复杂化,因为许多平台保证这些操作only if they are aligned 的原子性。


    现代 CPU 以高速缓存行大小的块传输数据,而不仅仅是 32 位或 64 位字。除非您正在访问不可缓存的内存区域(例如,设备驱动程序中的内存映射 I/O),在这种情况下,您实际上会通过外部获得字节、16 位、32 位或 64 位访问巴士。

    只要不跨越 64 位边界,现代 x86 CPU 上的非对齐访问就不会受到任何惩罚。 (特别是在 Intel 上,除非您越过缓存线边界,否则未对齐的加载/存储不会受到惩罚)。

    另请参阅How can I accurately benchmark unaligned access speed on x86_64,以及 标签 wiki 中的性能调整链接。

    【讨论】:

    • 对,那么为什么需要填充呢?即,应该出现在维基百科中的真实文本是什么?
    • @BeeOnRope:我在一段的末尾有一句话,但你说得对,我应该扩展它。完毕。至于维基百科,我想只是填充以避免单词元素或对象相对于单词边界的错位?我没有看上下文的其余部分,要弄清楚如何用通用的解释来表达需要做很多工作。
    • 是的,基本上为什么需要填充?因为对齐访问(a)有时是唯一直接支持的访问,否则通常(b)更有效。另请注意,只有在最近的英特尔上,只有缓存线拆分受到了伤害——在其他各种未对齐的访问也较慢之前。对齐的另一个原因是线程间相邻元素的独立性。
    • @BeeOnRope:我不记得在 Core2 和更早版本上未对齐整数访问的成本是多少。我知道movdqu 很贵,但即使地址对齐也很贵。如果您知道要添加什么来回答该部分问题,请对此答案进行编辑;我的回答主要是为了纠正对字节加载/存储的误解。
    • 我尽力回答了这部分问题:您已经回答了“为什么填充会导致自然对齐”部分,我只是尝试添加“为什么您会关心自然对齐” “我认为这完成了这一点。顺便说一句,我编辑了导致混乱的problematic article。文章的后面部分还可以,但介绍刚刚结束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2021-11-28
    • 2019-09-13
    • 2012-07-22
    • 2013-05-13
    • 2020-04-16
    • 2023-03-08
    相关资源
    最近更新 更多