由于FPU或缓存是双重对齐到8字节边界?

时间:2015-01-10 17:40:13

标签: c++ x86 memory-alignment

我试图理解为什么double与8字节边界对齐而不仅仅是4字节边界。在article中,它说:

  
      
  1. 当内存读取在32位机器上一次读取4个字节时,为什么双字节应该在8字节边界上对齐?
  2.         

    重要的是要注意大多数处理器都有数学   协处理器,称为浮点单元(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字节边界上对齐双倍性能   原因。编译器知道这一点并且只是为你做。

那么哪一个是正确的答案?是两个吗?

2 个答案:

答案 0 :(得分:1)

  
    

值得注意的是,大多数处理器都有数学协处理器,称为浮点单元(FPU)。

  

所以,首先,这篇文章有点不对劲。在处理器中不再是FPU,因为算术指令基本上是在相同的指令管道中处理的。

  
    

主处理器与浮点执行无关。

  

这是2015年,我们不是在谈论英特尔486,所以这是完全错误的。

  
    

按照标准,double类型将占用8个字节。并且,在FPU中执行的每个浮点运算都将是64位长度。在执行之前,即使浮点类型也会被提升为64位。

  

据我所知,这是不对的;有一些指令适用于单精度浮点数,以及处理双精度的指令。

  
    

64位长度的FPU寄存器强制在8字节边界上分配double类型。

  

这根本不是真的。有一些指令只能用于特殊对齐的内存,有些指令更快,但通常符合其规范或各自的实现。像处理器代之间特定操作需要改变的循环一样!

所以,SO答案是正确的。相信你的编译器。如果你想拥有对齐的内存(例如你希望你的编译器使用SIMD指令的浮点数组等),那么就像posix_memalign这样的东西(当然,在unixes下,但我可以想象一下WindowsNT中的posix层,后来也实现了这个,它可以为你提供很好的对齐内存。

答案 1 :(得分:0)

通常,内存对齐问题主要由内存单元隐藏 - 执行单元将接收正确旋转的数据并具有正确的大小(同样的问题也可能适用于整数类型)。

因此,对齐主要涉及缓存此数据的能力,而不必担心必须将其分段(拆分)取出,这是一种引发各种一致性和原子性问题的棘手业务。

如果某些架构想要保存旋转逻辑并强制您相应地对齐某些数据,这当然可能会改变,但一般来说这是一个更难解决的问题,因此限制架构以满足此硬件考虑因素有点无意义(至少这几天)。