【问题标题】:Why is natural alignment used in most processor architectures over processor-word alignment?为什么在大多数处理器架构中使用自然对齐而不是处理器字对齐?
【发布时间】:2022-02-05 23:01:57
【问题描述】:

大多数处理器架构更喜欢自然对齐作为默认对齐要求,但我认为处理器字对齐是一种更有效的对齐要求,它可以节省内存,而不会比自然对齐带来任何性能开销。

例如,根据自然对齐,双精度数的对齐方式为 8,但在 32 位处理器上,如果双精度数的对齐方式为 4,它将没有性能开销,并且可以节省内存。 source#3.6.4 声明 double 在 32 位处理器上对齐为 8:

对齐 64 位数据,使其基地址为 8 的倍数。

类似的例子可以在 64 位处理器中看到,16 字节大小的数据类型(int128)的对齐为 16,而保持对齐等于处理器字的大小(即 8 字节)可能是有益的long 在 64 位处理器中)。

我的猜测是创建这个自然对齐标准是因为当直接从网络中读取数据时,机器可以默认为自然对齐,而不必根据 CPU 架构来处理相同数据类型的不同对齐。数据的发送者。

当数据结构的所有字段都存储在单个 CPU 字中时,由于自然对齐,它们内部仍然有填充,而我认为当所有字段都存储在单个 CPU 字中时不需要填充,因为结构的任何字段都需要相同数量的字节移位来访问它,而不管它存储在 CPU 字的哪个位置(如果我错了,请纠正我)。

例如,考虑这个结构:

struct example {
   char i; // 1 byte
   // 1 byte padding
   short j; // 2 bytes
   int k; // 4 bytes
   char l; // 1 byte
   // 3 bytes trailing padding
} foo;

我认为foo.ifoo.j 之间不需要填充,因为foo.j 仍然需要6 字节移位才能访问。

总结一下我的问题,我想知道自然对齐相对于基于处理器字的对齐有什么好处。

我还想知道在存储所有数据的 CPU 字之间插入填充是否比在没有任何填充的情况下存储这些字段更好。还有,同一个CPU word中字段的位置有区别吗?

【问题讨论】:

    标签: struct cpu padding cpu-architecture memory-alignment


    【解决方案1】:

    所有 64 位 CPU 都具有原生 4 字节负载,除 Alpha 之外的所有 CPU 都具有 2 字节和字节负载。在某些 CPU 上,这些窄负载需要使用自然对齐的数据,或者更有效。

    我认为您假设窄数据是通过实际加载包含的 8 字节块并手动(?)使用位移或字节位移进行提取来加载的,而不是只需要选择两个之一的逻辑从缓存中提取 8 字节的 4 字节块,仅基于一个地址位。

    CPU 的设计可能不同,允许在 8 字节块内的任何偏移处加载 2 字节,包括奇数地址,但这将需要加载端口中的更多门和更长的门延迟。在屏蔽写入缓存方面,对于商店来说可能更糟?

    此外,允许或不允许的规则变得更加复杂;硬件检查强制对齐要求的 CPU 稍微困难一些。 (允许未对齐加载的 CPU 已经需要这么多逻辑来检测加载/存储何时跨缓存行拆分,或者如果它只能获取小块,则跨同一行的块。)

    但更重要的是,人类程序员和编译器可能更难以有效利用。也许这不是什么大问题,也许这是计算机体系结构可能采取的合理路径,在这种情况下,我们现在都已经习惯了。

    (Intel/AMD CPU 实际上确实有rules like this for atomicity guarantees;对包含在 8 字节块中的可缓存内存的任何 2 次幂访问都保证是原子的。甚至对于 32 字节块中的 16 位访问的不可缓存内存-bit dword。但是由于有些 ISA 只需要对齐,并且因为 C alignof / alignas 没有办法描述它,所以像 C 这样的语言选择最小的公分母,并且需要自然对齐 @987654325 @ 类型。)


    顺便说一句,许多 SIMD 指令集比未对齐的负载更有效,尤其是在 10 或 20 年前,因此如果您想用一条指令复制整个 16 字节结构,则相关宽度是 SIMD 向量宽度,而不是通用整数 reg 的宽度。例如x86 movupsmovaps xmm, mem(需要 16 字节对齐)。

    但通常你不会过度对齐包含较小成员的结构。


    对齐比 CPU 位数更多确实很重要

    例如,根据自然对齐,双精度数的对齐方式为 8,但在 32 位处理器上,如果双精度数的对齐方式为 4,它将没有性能开销,并且会节省内存。

    在现代 CPU 上是错误的。自 P5 Pentium 以来,Intel CPU 上的 FPU 可以对缓存进行 8 字节访问,而不管整数寄存器宽度仅为 32 位这一事实。 MMX 单元也可以。

    现代 32 位 ARM CPU 与之类似,首选对齐的 8 字节 FPU 加载/存储。

    在 Pentium 4 上,SIMD 加载/存储可以在一次操作中访问 16 个字节。 (P6 系列将 SSE/SSE2 操作分成 8 字节的两半,直到 Core2,第一个支持 x86-64 的 P6 系列。)

    32 位仅描述地址和/或整数寄存器宽度,而不是 FPU 或加载对/存储对指令的最大缓存访问宽度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2010-12-23
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多