我试图理解为什么double与8字节边界对齐而不仅仅是4字节边界。在article中,它说:
- 当内存读取在32位机器上一次读取4个字节时,为什么双字节应该在8字节边界上对齐?
醇>重要的是要注意大多数处理器都有数学 协处理器,称为浮点单元(FPU)。任何浮点 代码中的操作将被翻译成FPU指令。该 主处理器与浮点执行无关。所有 这将在幕后完成。
按照标准,double类型将占用8个字节。而且,每一次浮动 在FPU中执行的点操作将是64位长度。甚至漂浮 在执行之前,类型将被提升为64位。
FPU寄存器的64位长度强制分配双类型 在8字节边界上。我假设(我没有具体信息) 在FPU操作的情况下,数据提取可能会有所不同,我的意思是 数据总线,因为它去了FPU。因此,地址解码将是 双重类型不同(预计为8字节 边界)。它意味着,浮点的地址解码电路 单位不会有最后3个针脚。
在此SO question中,它说:
在2 ^ N的边界上对齐大小为2 ^ N的数据值的原因是 避免值将在缓存中拆分的可能性 线边界。
x86-32处理器可以从任何字边界获取一个double(8字节 对齐或不对齐)最多两个32位内存读取。但如果价值 在缓存行边界分割,然后是获取第二个的时间 字可能很长,因为需要获取第二个缓存行 从记忆里。这会不必要地产生差的处理器性能。 (实际上,当前的处理器不能获取32位 从记忆中一次;他们往往会获得更大的价值 更宽的总线,以实现真正高的数据带宽;实际上 如果它们在同一个缓存行中,则获取两个单词的时间 已缓存,可能只有1个时钟。
这种对齐方案的自由结果也是这样的值 不要越过页面边界。这避免了页面的可能性 数据提取过程中的错误。
因此,您应该在8字节边界上对齐双倍性能 原因。编译器知道这一点并且只是为你做。
那么哪一个是正确的答案?是两个吗?
答案 0 :(得分:1)
值得注意的是,大多数处理器都有数学协处理器,称为浮点单元(FPU)。
所以,首先,这篇文章有点不对劲。在处理器中不再是FPU,因为算术指令基本上是在相同的指令管道中处理的。
主处理器与浮点执行无关。
这是2015年,我们不是在谈论英特尔486,所以这是完全错误的。
按照标准,double类型将占用8个字节。并且,在FPU中执行的每个浮点运算都将是64位长度。在执行之前,即使浮点类型也会被提升为64位。
据我所知,这是不对的;有一些指令适用于单精度浮点数,以及处理双精度的指令。
64位长度的FPU寄存器强制在8字节边界上分配double类型。
这根本不是真的。有一些指令只能用于特殊对齐的内存,有些指令更快,但通常符合其规范或各自的实现。像处理器代之间特定操作需要改变的循环一样!
所以,SO答案是正确的。相信你的编译器。如果你想拥有对齐的内存(例如你希望你的编译器使用SIMD指令的浮点数组等),那么就像posix_memalign
这样的东西(当然,在unixes下,但我可以想象一下WindowsNT中的posix层,后来也实现了这个,它可以为你提供很好的对齐内存。
答案 1 :(得分:0)
通常,内存对齐问题主要由内存单元隐藏 - 执行单元将接收正确旋转的数据并具有正确的大小(同样的问题也可能适用于整数类型)。
因此,对齐主要涉及缓存此数据的能力,而不必担心必须将其分段(拆分)取出,这是一种引发各种一致性和原子性问题的棘手业务。如果某些架构想要保存旋转逻辑并强制您相应地对齐某些数据,这当然可能会改变,但一般来说这是一个更难解决的问题,因此限制架构以满足此硬件考虑因素有点无意义(至少这几天)。