CPU和数据对齐

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

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

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

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

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

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

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

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

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

很少有数据“有”对齐。 更多的是某些类型的数据可能表现更好或某些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.)有些架构根本没有这个要求,有些架构鼓励对齐(访问非alignet数据项时存在速度损失),有些架构可能会严格执行(错误导致处理器exception)。
当今许多流行的架构都属于速度惩罚类别。 CPU设计人员必须在灵活性/性能和成本(硅片面积/总线周期所需的控制信号数量)之间进行交易。

2.)什么语言,哪种架构? 请参阅编译器手册和/或CPU体系结构文档。

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

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

  1. 您的内存系统可能不是字节可寻址的。 除此之外,您可能会因处理器访问未对齐数据而导致性能下降。 某些处理器(例如旧的ARM芯片)根本无法完成。

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

  3. 通常当人们引用处于特定对齐的数据时,它仅指第一个字节。 因此,如果ABI规范说“数据结构X必须是4字节对齐”,则意味着X应该放在内存中可被4整除的地址。关于结构X的大小或内部布局,该规则没有暗示任何内容。

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

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

有些架构只处理32个(或36个)位字,你需要特殊的指令来加载单个字符或haalf字。

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

对于大多数现代体系结构,您需要将整数与单词边界和长整数对齐以使单词边界加倍。 这简化了加载寄存器的电路,并且速度非常快。

出于性能原因,CPU需要数据对齐。 英特尔网站提供了有关如何对齐内存中数据的详细信息

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

其中之一是数据项的对齐 – 它们在内存中的位置与四倍,八倍或16字节的倍数相关。 在16位英特尔架构下,数据对齐对性能几乎没有影响,它的使用完全是可选的。 在IA-32下,正确对齐数据可能是一个重要的优化,尽管它的使用仍然是可选的,只有极少数例外,其中必须正确对齐。 但是,64位环境对数据项提出了更严格的要求。 未对齐的对象会导致程序exception。 要使项目正确对齐,它必须满足64位英特尔架构(稍后讨论)以及用于构建应用程序的链接器的要求。

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

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

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

应该对齐64字节或更大的数据结构或数组,使其基址是64的倍数。按递减大小顺序排序数据是一种用于辅助自然对齐的启发式算法。 只要16字节边界(和缓存行)永远不会交叉,自然对齐就不是必需的,尽管这是一种强制遵守一般对齐建议的简单方法。

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

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