memory - 内存对齐的目的

标签 memory alignment memory-alignment

诚然,我不明白。假设您有一个长度为 1 字节的内存字的内存。为什么不能在未对齐地址(即不能被 4 整除)上的单个内存访问中访问 4 字节长的变量,就像对齐地址的情况一样?

最佳答案

现代处理器上的内存子系统仅限于以字长的粒度和对齐方式访问内存;原因有很多。

速度

现代处理器具有多个级别的高速缓存,必须通过这些高速缓存来提取数据;支持单字节读取将使内存子系统的吞吐量与执行单元的吞吐量紧密绑定(bind)(又名 cpu-bound);这一切都让人想起 PIO mode was surpassed by DMA硬盘驱动器中的许多相同原因。

CPU总是读取它的字长(在 32 位处理器上为 4 个字节),因此当您在支持它的处理器上执行未对齐的地址访问时,处理器将读多个单词。 CPU 将读取您请求的地址跨越的每个内存字。这导致访问请求的数据所需的内存事务数量最多增加 2 倍。

因此,读取两个字节很容易比读取四个字节慢。例如,假设您在内存中有一个如下所示的结构:

struct mystruct {
    char c;  // one byte
    int i;   // four bytes
    short s; // two bytes
}

在 32 位处理器上,它很可能会如下所示对齐:

Struct Layout

处理器可以在一个事务中读取这些成员中的每一个。

假设你有一个打包版本的结构,可能来自网络,它是为了传输效率而打包的;它可能看起来像这样:

Packed Struct

读取第一个字节将是相同的。

当您要求处理器从 0x0005 给您 16 位时,它必须从 0x0004 读取一个字并左移 1 个字节以将其放入 16 位寄存器;一些额外的工作,但大多数人可以在一个周期内完成。

当您从 0x0001 请求 32 位时,您将获得 2X 放大。处理器将从 0x0000 读取到结果寄存器并左移 1 个字节,然后再次从 0x0004 读取到临时寄存器,右移 3 个字节,然后与结果寄存器进行 OR

范围

对于任何给定的地址空间,如果架构可以假设 2 个 LSB 始终为 0(例如,32 位机器),那么它可以访问 4 倍的内存(2 个保存的位可以代表 4 个不同的状态),或者相同数量的内存与 2 位用于标志之类的东西。从地址中取出 2 个 LSB 将使您获得 4 字节对齐;也称为 stride 4字节。每次增加地址时,它实际上是在增加第 2 位,而不是第 0 位,即最后 2 位将始终继续为 00

这甚至会影响系统的物理设计。如果地址总线需要少 2 位,CPU 上的引脚可以少 2 个,电路板上的走线也可以少 2 个。

原子性

CPU 可以原子地对对齐的内存字进行操作,这意味着没有其他指令可以中断该操作。这对许多 lock-free data structures 的正确操作至关重要。和其他 concurrency范式。

结论

处理器的内存系统比这里描述的要复杂得多。关于 how an x86 processor actually addresses memory 的讨论可以提供帮助(许多处理器的工作方式类似)。

坚持内存对齐还有很多好处,您可以在 this IBM article 阅读。 .

计算机的主要用途是转换数据。几十年来,现代内存架构和技术已经过优化,以促进以高度可靠的方式在更多更快的执行单元之间获取更多数据。

奖励:缓存

我之前提到的另一个性能对齐是缓存行上的对齐(例如,在某些 CPU 上)64B。

有关利用缓存可以获得多少性能的更多信息,请查看 Gallery of Processor Cache Effects ;从此question on cache-line sizes

Understanding of cache lines can be important for certain types of program optimizations. For example, the alignment of data may determine whether an operation touches one or two cache lines. As we saw in the example above, this can easily mean that in the misaligned case, the operation will be twice slower.

关于memory - 内存对齐的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/381244/

相关文章:

css - 在 HTML 中对齐表格

css - Bootstrap 验证错误导致表单对齐问题

c++ - 为什么在我的实现中所有数组都对齐到 16 字节?

Android:光标窗口已满

java - 如何*实时*检查 VPS 中可用的总 RAM 内存..?

php - 当返回的数据小于10k时,什么会导致mysqli语句使用4GB内存?

assembly - 将局部变量与 16 字节边界对齐 (x86 asm)

C++:很少改变大小的大型动态结构数组,是否需要 Vector?

javascript - 如何沿着 svg 中的路径对齐组(而不是文本)?

linux - 不同缓冲区大小的不同内存对齐方式