在进行一个项目时,我看到内存数据是“8 字节对齐的”。谁能解释一下这是什么意思?
4 回答
“8 字节对齐”的对象存储在 8 的倍数的内存地址中。
许多 CPU 只会从对齐的位置加载某些数据类型;在其他 CPU 上,这种访问速度更快。使用内存对齐还有其他几个可能的原因 - 没有看到代码很难说出原因。
对齐访问更快,因为到内存的外部总线不是单字节宽 - 它通常是 4 或 8 字节宽(甚至更宽)。这意味着 CPU 不会一次获取一个字节 - 它从请求的地址开始获取 4 或 8 个字节。因此,内存地址的 2 或 3 个最低有效位实际上不是由 CPU 发送的 - 外部存储器只能在总线宽度的倍数的地址处读取或写入。如果您在地址“9”请求一个字节,CPU 实际上会向内存请求从地址 8 开始的字节块,并将第二个字节加载到您的寄存器中(丢弃其他字节)。
这意味着未对齐的访问可能需要从内存中读取两次:如果您要求从地址 9 开始的 8 个字节,CPU 必须获取从地址 8 开始的 8 个字节以及从地址 16 开始的 8 个字节,然后屏蔽掉你想要的字节。另一方面,如果您要求从地址 8 开始的 8 个字节,则只需要一次提取。一些 CPU 甚至不会执行这种未对齐的加载——它们只会引发异常(或者甚至默默地加载错误的数据!)。
内存对齐以不同的方式对性能很重要。它有一个硬件相关的原因。自 80 年代以来,CPU 和内存之间的访问时间存在差异。处理器速度的增长速度超过了内存的速度。随着时间的推移,这种差异越来越大(举个例子:在 Apple II 上,CPU 为 1.023 MHz,内存是该频率的两倍,CPU 为 1 个周期,视频为 1 个周期。现代 PC 可以工作CPU 上大约 3GHz,内存只有 400MHz)。解决内存变慢问题的一种方法是在更宽的总线上访问它,而不是一次访问 1 个字节,CPU 将从内存中读取一个 64 位宽的字。这意味着即使您从内存中读取 1 个字节,总线也会提供整个 64 位(8 字节字)。内存将在地址 0、8、16、24、32、40 等处具有这 8 个字节单元。是 8 的倍数。例如,如果您访问地址 4 处的 8 字节字,则硬件必须读取该字在地址 0 处,屏蔽该字的高 4 个字节,然后读取地址 8 处的字,屏蔽该字的低位部分,将其与前半部分组合并将其提供给寄存器。如您所见,操作非常复杂(因此很慢)。这是人们喜欢对齐内存访问的第一个原因。我会在 2 小时后给出另一个理由。如您所见,操作非常复杂(因此很慢)。这是人们喜欢对齐内存访问的第一个原因。我会在 2 小时后给出另一个理由。如您所见,操作非常复杂(因此很慢)。这是人们喜欢对齐内存访问的第一个原因。我会在 2 小时后给出另一个理由。
“X 字节对齐”意味着数据的基地址必须是 X 的倍数。它可以用于在某些特殊硬件中使用某些特殊硬件,例如 DMA,以便 cpu 更快地访问等...
单元处理器就是这种情况,其中数据必须对齐 16 个字节才能复制到协处理器或从协处理器复制。
如果内存数据是 8 字节对齐的,则意味着:
sizeof(the_data) % 8 == 0
.
一般在 C 语言中,如果一个结构被提议为 8 字节对齐,它的大小必须是 8 的乘积,如果不是,则需要手动或编译器进行填充。一些编译器提供指令来使结构与 n 字节对齐,对于 VC,它是#prgama pack(8)
,而对于 gcc,它是__attribute__((aligned(8)))
.