是否需要“双”型的8字节对齐?

时间:2014-01-19 16:04:49

标签: c cpu memory-alignment

我理解字对齐,这使得cpu只需要在将整数读入寄存器时读取一次。

8-byte alignment(我们假设是32位系统)是否需要“双倍”?有什么好处?如果用于存储“double”的空间只是4字节对齐,会发生什么?

5 个答案:

答案 0 :(得分:4)

有多个硬件组件可能会受到未对齐的加载或存储的不利影响。

  • 内存接口可能是8个字节宽,只能以8个字节的倍数访问内存。加载一个未对齐的八字节双,然后需要在总线上读取两次。存储更糟糕,因为对齐的8字节存储可以简单地将8个字节写入存储器,但是未对齐的8字节存储必须读取两个8字节的片段,将新数据与旧数据合并,并写入两个8字节的片段
  • 缓存行通常为32或64字节。如果八字节对象与八个字节的倍数对齐,则每个对象只在一个高速缓存行中。如果它们未对齐,则某些对象部分位于一个缓存行中,部分位于另一个缓存行中。然后,加载或存储这些对象需要使用两个缓存行而不是一个。这种影响发生在所有级别的缓存中(在现代处理器中,三个级别并不罕见)。
  • 内存系统页面通常为512字节或更多。同样,每个对齐的对象只在一个页面中,但是一些未对齐的对象在多个页面中。访问的每个页面都需要硬件资源:必须将虚拟地址转换为物理地址,这可能需要访问转换表,并且必须检测地址冲突。 (处理器可能同时运行多个加载和存储操作。即使您的程序可能看起来是单线程的,处理器也会提前读取指令并尝试执行它们。因此处理器可以在之前启动加载指令说明已经完成。但是,为了确保这不会导致错误,处理器会检查每个加载指令以确保它不是从先前存储指令正在改变的地址加载。如果访问跨越页边界,则两者必须单独检查加载数据的一部分。)

系统对未对齐操作的响应因系统而异。某些系统旨在仅支持对齐的访问。在这些情况下,未对齐访问会导致导致程序终止的异常或导致执行模拟软件中未对齐操作的特殊处理程序的异常(通过执行对齐操作并根据需要合并数据)。像这样的软件处理程序比硬件操作慢得多。

某些系统支持未对齐访问,但这通常比对齐访问消耗更多硬件资源。在最好的情况下,硬件执行两个操作而不是一个操作。但是一些硬件被设计为开始操作,就像它们被对齐一样,然后,在发现操作未对齐时,中止它并重新开始使用硬件中的不同路径来处理未对齐的操作。在这样的系统中,未对齐访问会显着降低性能,但不如软件处理未对齐访问的系统那么大。

在某些系统中,硬件可能有多个加载 - 存储执行单元,可以执行未对齐访问所需的两个操作,就像一个单元可以执行对齐访问的操作一样快。因此,未对齐访问不会直接降低性能。但是,由于多个执行单元由于未对齐访问而保持繁忙,因此它们无法执行其他操作。因此,执行许多加载 - 存储操作的程序(通常是并行的)在未对齐访问时的执行速度会比对齐访问的执行速度慢。

答案 1 :(得分:3)

在许多体系结构中,任何加载/存储单元(short,int,long)的未对齐访问只是一个例外。编译器负责通过发出较小的访问指令并在无法证明给定指针正常的情况下重新组装寄存器来确保它不会发生在可能存在错位的数据上。

在性能方面,32位系统上的双字节8字节对齐可能有一些原因。最明显的是,8字节双精度的4字节对齐意味着一个元素可以跨越两个高速缓存行的边界。内存访问以整个缓存行为单位进行,因此错位会使访问成本加倍。

答案 2 :(得分:0)

编辑:

字节对齐的优点是减少了检索数据的内存周期数。例如,一个8字节,如果它被对齐可能需要一个周期,现在可能需要2个周期,因为它的一部分是第一次获得而第二部分是在下一个存储周期中获得的。

我遇到了这个: "对齐访问更快,因为外部总线到内存不是单字节宽 - 通常是4或8字节宽(甚至更宽)。因此,CPU一次不取一个字节 - 从请求的地址开始取出4或8个字节。因此,存储器地址的2或3个最低有效位实际上不是由CPU发送的 - 外部存储器只能在总线宽度的倍数的地址上读取或写入。如果您在地址" 9"处请求了一个字节,则CPU实际上会向存储器询问从地址8开始的字节块,并将第二个字节加载到您的寄存器中(丢弃其他寄存器)。

这意味着未对齐的访问可能需要从内存中读取两次:如果要求从地址9开始的8个字节,CPU必须从地址8开始获取8个字节以及从地址16开始的8个字节,然后掩盖你想要的字节。另一方面,如果要求从地址8开始的8个字节,则只需要一次提取。有些CPU甚至不会执行这样的错位负载 - 它们只会引发异常(甚至无声地加载错误的数据!)。"

您可能会看到此链接以获取更多详细信息。 http://www.ibm.com/developerworks/library/pa-dalign/

答案 3 :(得分:0)

我刚刚找到the answer:

“6。当内存读取在32位机器上一次读取4个字节时,为什么双字节应该在8字节边界上对齐?

值得注意的是,大多数处理器都有数学协处理器,称为浮点单元(FPU)。代码中的任何浮点运算都将转换为FPU指令。主处理器与浮点执行无关。所有这些都将在幕后完成。

按照标准,double类型将占用8个字节。并且,在FPU中执行的每个浮点运算都将是64位长度。在执行之前,即使浮点类型也会被提升为64位。

64位长度的FPU寄存器强制在8字节边界上分配double类型。我假设(我没有具体信息)在FPU操作的情况下,数据提取可能不同,我的意思是数据总线,因为它转到FPU。因此,对于双类型(预期在8字节边界上),地址解码将是不同的。这意味着,浮点单元的地址解码电路不会有最后3个引脚。“

答案 4 :(得分:0)

  • 我似乎记得486的建议是在32位边界上对齐,因此要求64位对齐不是强制性的。

  • 您似乎认为数据总线宽度与处理器位数之间存在关系。虽然经常出现这种情况,但您可以找到两个方向的变化。例如,Pentium是一个32位处理器,但其数据总线大小为64位。

  • 缓存提供了一些其他功能,可以解释为64位类型进行64位对齐的有用性。这里外部总线不是一个因素,重要的是缓存行大小。跨越行缓存的数据比不跨越它的数据更昂贵(即使在两种情况下都是未对齐的)。只要缓存行大小是类型大小的倍数,就可以确保它们的大小对齐类型,确保它们不会跨越缓存行。