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

Inf*_*ite 4 c cpu memory-alignment

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

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

Eri*_*hil 9

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

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

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

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

在某些系统中,硬件可能具有多个加载-存储执行单元,它们可以像一个单元执行对齐访问操作一样快地执行未对齐访问所需的两种操作。因此,未对齐访问不会直接降低性能。然而,由于多个执行单元因未对齐的访问而处于忙碌状态,因此它们无法执行其他操作。因此,执行许多加载-存储操作(通常是并行的)的程序在使用未对齐访问时比使用对齐访问时执行得更慢。


Din*_*esh 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/