16

如果您觉得这已被多次回答,请原谅我,但我需要以下问题的答案!

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

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

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

4

7 回答 7

16

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

Intel CPU 可以对许多指令执行非字边界的访问,但是会降低性能,因为 CPU 在内部执行两次内存访问和一次数学运算来加载一个字。如果您正在执行字节读取,则不适用对齐方式。

某些 CPU(ARM 或 Intel SSE 指令)需要对齐的内存,并且在执行未对齐的访问(或引发异常)时具有未定义的操作。通过不实施更复杂的加载/存储子系统,它们节省了大量的芯片空间。

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

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

于 2010-06-11T18:21:04.187 回答
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

于 2010-06-11T18:22:00.580 回答
4

1.) 有些架构根本没有这个要求,有些架构鼓励对齐(访问非对齐数据项时会降低速度),有些架构可能会严格执行(未对齐导致处理器异常)。
当今许多流行的架构都属于速度惩罚类别。CPU 设计人员必须在灵活性/性能和成本(硅面积/总线周期所需的控制信号数量)之间进行权衡。

2.) 什么语言,什么架构?请查阅您的编译器手册和/或 CPU 架构文档。

3.)这完全取决于架构(某些架构可能根本不允许访问字节大小的项目,或者总线宽度甚至不是 8 位的倍数)。因此,除非您询问特定架构,否则您不会得到任何有用的答案。

于 2010-06-11T18:28:38.367 回答
2

一般来说,这三个问题的唯一答案是“这取决于您的系统”。更多细节:

  1. 您的内存系统可能无法按字节寻址。除此之外,您可能会因让处理器访问未对齐的数据而导致性能损失。一些处理器(例如较旧的 ARM 芯片)根本无法做到这一点。

  2. 阅读您的处理器的手册以及为您生成代码的任何 ABI 规范,

  3. 通常当人们提到数据处于某种对齐方式时,它只指第一个字节。因此,如果 ABI 规范说“数据结构 X 必须是 4 字节对齐”,这意味着 X 应该放在内存中可被 4 整除的地址。该声明并未暗示结构 X 的大小或内部布局.

    就您的特定示例而言,如果数据从地址 1004 开始以 4 字节对齐,则下一个字节将位于 1005。

于 2010-06-11T18:18:21.303 回答
2

它完全取决于您使用的 CPU!

一些体系结构只处理 32(或 36!)位字,您需要特殊指令来加载单个字符或半个字。

一些 CPU(特别是 PowerPC 和其他 IBM RISC 芯片)不关心对齐,并且会从奇数地址加载整数。

对于大多数现代架构,您需要将整数与字边界对齐,将长整数与双字边界对齐。这简化了加载寄存器的电路并大大加快了速度。

于 2010-10-11T01:54:53.187 回答
1

出于性能原因,CPU 需要数据对齐。英特尔网站详细介绍了如何对齐内存中的数据

迁移到 64 位英特尔® 架构时的数据对齐

其中之一是数据项的对齐——它们在内存中的位置与 4、8 或 16 字节的倍数地址相关。在 16 位 Intel 架构下,数据对齐对性能的影响很小,它的使用完全是可选的。在 IA-32 下,正确对齐数据可能是一项重要的优化,尽管它的使用仍然是可选的,除了极少数例外,正确对齐是强制性的。然而,64 位环境对数据项提出了更严格的要求。未对齐的对象会导致程序异常。要正确对齐项目,它必须满足 64 位 Intel 架构(稍后讨论)以及用于构建应用程序的链接器的要求。

数据对齐的基本规则是最安全(也是最广泛支持)的方法依赖于英特尔所说的“自然边界”。当您将数据项的大小四舍五入到下一个最大大小(2、4、8 或 16 个字节)时,就会出现这些情况。例如,10 字节浮点数应与 16 字节地址对齐,而 64 位整数应与 8 字节地址对齐。因为这是一个 64 位架构,指针大小都是 8 字节宽,所以它们也应该在 8 字节边界上对齐。

建议所有大于 16 字节的结构在 16 字节边界上对齐。通常,为了获得最佳性能,请按如下方式对齐数据:

  • 在任意地址对齐 8 位数据
  • 对齐 16 位数据以包含在对齐的四字节字中
  • 对齐 32 位数据,使其基地址为 4 的倍数
  • 对齐 64 位数据,使其基地址为 8 的倍数
  • 对齐 80 位数据,使其基地址为 16 的倍数
  • 对齐 128 位数据,使其基地址为 16 的倍数

应对齐 64 字节或更大的数据结构或数组,使其基地址是 64 的倍数。按大小递减顺序对数据进行排序是帮助自然对齐的一种启发式方法。只要 16 字节边界(和高速缓存行)从未跨越,自然对齐就不是绝对必要的,尽管它是强制遵守一般对齐建议的简单方法。

在结构中正确对齐数据可能会导致数据膨胀(由于正确放置字段所需的填充),因此在必要和可能的情况下,重组结构是有用的,以便需要最广泛对齐的字段在结构中首先出现。有关解决此问题的更多信息,请参阅文章“为 IA-64 架构准备代码(代码清理)”。

于 2013-08-18T00:57:59.893 回答
1

对于英特尔架构,英特尔 64 和 IA-32 架构软件开发人员手册的第 4 章数据类型回答了您的问题 1。

于 2013-12-21T02:56:13.860 回答