C++ 双人还是浮动,哪个更快?

C++ 双人还是浮动,哪个更快?,c++,floating-point,double,C++,Floating Point,Double,我正在读《加速C++》。我发现有一句话说“有时double比C++中的float执行得更快”。读了这个句子后,我对float和double工作感到困惑。请给我解释一下这一点 您可以在本文中找到完整的答案: 这是对上一个堆栈溢出线程的引用,关于float和double变量如何影响内存带宽: 如果双人间需要 比浮点数更多的存储空间,那么 读取数据将花费更长的时间。 这是天真的回答。论现代社会 IA32,这完全取决于数据的位置 是从哪里来的。如果它在一级缓存中, 如果 数据来自单个缓存线。 如果它跨

我正在读《加速C++》。我发现有一句话说“有时
double
比C++中的
float
执行得更快”。读了这个句子后,我对
float
double
工作感到困惑。请给我解释一下这一点

您可以在本文中找到完整的答案:

这是对上一个堆栈溢出线程的引用,关于
float
double
变量如何影响内存带宽:

如果双人间需要 比浮点数更多的存储空间,那么 读取数据将花费更长的时间。 这是天真的回答。论现代社会 IA32,这完全取决于数据的位置 是从哪里来的。如果它在一级缓存中, 如果 数据来自单个缓存线。 如果它跨越多个缓存线 头顶上有一个小洞。如果是从 L2,如果它是 在RAM中,它会变得更长、更稳定 最后,如果它在磁盘上,它是一个巨大的 时间所以选择浮动还是双精度 比数据的方式更重要 使用。如果你想做一个小游戏 大量连续数据的计算 数据,最好是小数据类型。 在小型计算机上进行大量计算 数据集将允许您使用更大的 具有任何重要属性的数据类型 效果。如果你正在访问数据 非常随机,然后选择数据 大小不重要-数据已加载 在页/缓存行中。所以即使你 只需要RAM中的一个字节,就可以了 传输32字节(这是非常重要的 取决于 系统)。最重要的是 CPU/FPU可以是超标量(也称为 管道)。因此,即使可能会出现负载 需要几个周期,CPU/FPU可以 忙于做别的事情 (例如,乘法)隐藏 加载时间达到一定程度


我可以想到两种基本情况,即双倍比浮点数快:

  • 您的硬件支持双重操作,但不支持浮点操作,因此软件将模拟浮点操作,因此速度较慢

  • 你真的需要双打的精准度。现在,如果使用浮点数,则必须使用两个浮点数才能达到与double类似的精度。使用浮点数模拟真正的双精度将比首先使用浮点数慢

  • 您不一定需要双精度,但由于双精度的提高,数值算法收敛速度更快。此外,Double可能提供足够的精度,以使用速度更快但数值稳定性较差的算法
  • 为了完整起见,我也给出了一些相反情况下浮动更快的原因。你可以亲眼看到,在你的案例中,哪些原因占主导地位:

  • 当你不需要双倍时,浮动比双倍快 精确性和内存带宽限制以及硬件 对浮点数不进行处罚

  • 它们节省了内存带宽,因为它们占用了一半的空间 每个号码

  • 还有一些平台可以处理比双倍多的浮动 同时


  • 浮动通常更快。双精度提供更高的精度。但是,如果使用3dNow或SSE等特殊处理器扩展,在某些情况下性能可能会有所不同。

    取决于本机硬件的功能

    • 如果硬件是(或类似于)具有传统x87数学的x86,则float和double都将(免费)扩展为内部80位格式,因此它们都具有相同的性能(缓存占用空间/内存带宽除外)

    • 如果硬件以本机方式实现这两种操作,如大多数现代ISA(包括x86-64,其中SSE2是标量FP数学的默认值),则通常大多数FPU操作的速度都相同,当然也比乘法或加法慢得多。(浮点值越小,缓存未命中的次数就越少。对于SIMD,对于向量化的循环,每个向量的元素数是原来的两倍)

    • 如果硬件只实现了double,那么如果在float load和float store指令中不能自由地进行与本机double格式的转换,则float的速度会变慢

    • 如果硬件只实现float,那么使用它模拟double将花费更多的时间。在这种情况下,float将更快

    • 如果硬件两者都没有实现,那么两者都必须在软件中实现。在这种情况下,两者都会很慢,但double会稍微慢一点(至少会有更多的加载和存储操作)

    您提到的这句话可能是指x86平台,这里给出了第一个案例。但这并不适用于一般情况

    还要注意的是,对于浮点x,y将触发两个变量的升级为双倍。这不是硬件的错,你应该通过编写
    3.3f
    来避免它,让你的编译器生成高效的asm,如果你想要的话,它可以将数字保持为浮点数。

    在英特尔上,协处理器(现在集成的)将以同样快的速度处理这两个问题,但正如其他一些人所指出的,加倍会导致更高的内存带宽,这可能会导致瓶颈。如果您使用的是标量SSE指令(大多数64位编译器的默认指令),同样适用。因此,一般来说,除非您处理的是大量数据,否则这并不重要


    然而,并行SSE指令将允许在一条指令中处理四个浮点,但只有两个浮点,因此这里的浮点可以明显更快。

    简短的回答是:这取决于

    使用x87的CPU将以同样快的速度处理浮动和加倍。矢量化代码在使用浮点运算时会运行得更快,因为SSE可以在一次运算中处理4个浮点运算或2个双倍运算

    另一件需要考虑的是记忆速度。根据您的算法,您的CPU在等待数据时可能会大量空闲。内存密集型代码将受益于使用浮动,但ALU有限型代码不会(除非它是矢量化的)。

    Summation time in s: 2.82 summed value: 6.71089e+07 // float
    Summation time in s: 2.78585 summed value: 6.6e+09 // double
    Summation time in s: 2.76812 summed value: 6.6e+09 // long double