CPU和数据对齐

MS.*_*MS. 14 c processor alignment cpu-architecture

请原谅我,如果你觉得这已被无数次回答,但我需要回答以下问题!

  1. 为什么数据必须对齐(在4字节/ 8字节/ 2字节边界上)?这里我怀疑的是当CPU具有地址线Ax Ax-1 Ax-2 ... A2 A1 A0时,很可能顺序地寻址存储器位置.那么为什么需要在特定边界对齐数据呢?

  2. 在编译代码和生成可执行代码时如何找到对齐要求?

  3. 如果例如数据对齐是4字节边界,那是否意味着每个连续字节位于模4偏移处?我怀疑的是,如果数据是4字节对齐,那意味着如果一个字节是1004那么下一个字节是1008(或1005)?

Yan*_*min 14

CPU是面向字的,而不是面向字节的.在简单的CPU中,存储器通常被配置为每个地址选通返回一个(32位,64位等),其中底部的两个(或更多)地址线通常是无关位.

对于许多指令,Intel CPU可以对非字边界执行访问,但是由于内部CPU执行两次存储器访问和一个数学运算来加载一个字,因此存在性能损失.如果您正在执行字节读取,则不应用对齐.

某些CPU(ARM或Intel SSE指令)需要对齐的内存,并且在进行未对齐访问(或抛出异常)时具有未定义的操作.它们通过不实现更复杂的加载/存储子系统来节省大量的硅空间.

对齐取决于CPU字大小(16,32,64位),或者在SSE的情况下取决于SSE寄存器大小(128位).

对于您的上一个问题,如果您一次只加载一个数据字节,则大多数CPU都没有对齐限制(某些DSP没有字节级指令,但可能您不会碰到一个).

  • 英特尔CPU不会因缓存行内未对齐的访问而降低性能。对齐数据对于避免高速缓存行拆分非常有用,在高速缓存行拆分中,有些字节在一行中,有些字节在另一行中,但是所有字节都在同一64字节行中,例如从“ [0x4000007]”或其他内容加载DWORD,一次访问缓存。(在旧的CPU上,即使使用对齐的地址,SSE`movdqu`也很慢,但是在Nehalem和更高版本中,跨越64字节边界(尤其是页面边界)只会受到惩罚。AMD的x86 CPU在32字节边界(也许16 ) (3认同)
  • 请参阅[为什么对x86上的自然对齐变量原子进行整数赋值?](/sf/ask/2563741701/):自然是原子的加载/存储之所以​​这样,是因为CPU将它们作为单个操作来完成,对于高速缓存的访问,复制高速缓存行时不会发生撕裂。另请参阅[选择对齐的x86 SIMD与未对齐的x86 SIMD指令](/sf/ask/3650316491/)以了解SSE / AVX未对齐。对齐数据通常是一件好事,但是您的推理并不完全正确,这仅在AVX512的现代x86上非常关键(每个向量都是一个完整的行)。 (2认同)

Tim*_*dge 6

很少有数据"有"对齐.更多的是某些类型的数据可能表现更好或某些cpu操作需要特定的数据对齐.

首先,假设您一次读取4个字节的数据.我们还说你的CPU有32位数据总线.我们还假设您的数据存储在系统内存中的字节2处.

既然你可以一次加载4个字节的数据,那么让你的地址寄存器指向一个字节并没有多大意义.通过使地址寄存器指向每4个字节,您可以操作4倍的数据.换句话说,您的CPU可能只能读取从字节0,4,8,12,16等开始的数据.

所以这就是问题所在.如果您希望数据从字节2开始并且您正在读取4个字节,则数据的一半将位于地址位置0而另一半位于位置1.

所以基本上你最终会打两次内存来读取你的一个4字节数据元素.某些CPU不支持此类操作(或强制您手动加载和组合这两种结果).

请访问此处了解更多详情:http://en.wikipedia.org/wiki/Data_structure_alignment

  • 链接为+1,但您应注意只有部分处理器可以容忍未对齐的数据.英特尔适用于IA32和IA64架构,但不适用于安腾.您的解释仅适用于容忍未对齐数据的处理器,例如IA32/IA64.Alpha AXP会产生错误,我认为MIPS也是如此.一些操作系统会处理错误处理程序中的错位数据,但性能损失很大.如果操作系统没有处理它,那么未对齐的数据对于那些系统来说并不起作用. (6认同)