双或浮,哪个更快?

com*_*oid 47 c++ floating-point double

我正在阅读"加速C++".我发现一句话说"有时double执行速度比floatC++ 快".读完句子后,我感到困惑floatdouble工作.请向我解释这一点.

foo*_*foo 51

取决于本机硬件的功能.

  • 如果硬件实现了double(就像x86那样),那么通过在那里扩展它来模拟float,转换将花费时间.在这种情况下,double会更快.

  • 如果硬件只实现浮动,那么用它模拟双倍将花费更多的时间.在这种情况下,浮动将更快.

  • 如果硬件不实现,则两者都必须在软件中实现.在这种情况下,两者都会很慢,但是double会稍慢一些(至少会有更多的加载和存储操作).

你提到的引用可能是指x86平台,第一个案例就是在这个平台上.但总的来说这并不成立.

  • AFAIK x86实际上有80位寄存器,不是浮点数也不是双精度数. (22认同)
  • 即使在x86上,也不是那么简单.旧的x87 FPU内部使用80位寄存器,这意味着*浮点数和双精度数都需要转换.但是如果使用SSE/SSE2,CPU内部不再使用80位精度,因此浮点数和双精度数都以其原始精度计算. (7认同)
  • @foo:x86-64有SIMD`float'(SSE)和`double`(SSE2).SSE2是x86-64的基线.现代x86 CPU具有SIMD,每个向量的性能与浮动或双加/ mul/FMA相同(因为每次向量的元素是两倍,因此浮点数的两倍于FLOPS).Mysticial有一个详细的答案[如何实现每个周期4个FLOP的理论最大值?](/sf/ask/587275391/).`double` division/sqrt比`float`慢[浮点除法与浮点乘法](/sf/answers/3212944171/) (5认同)
  • 关于80位支持附录:"英特尔开始劝阻,推出了P4的使用的x87在2000年底AMD在2003年弃用的x87自K8,如X86-64与支持SSE2定义;自2005年威盛的C7已经支持SSE2在64位版本的Windows中,x87不推荐用于用户模式,并且在内核模式下完全被禁止." 引自http://www.realworldtech.com/physx87/4/ (4认同)
  • 实际上是否可以使用80位扩展寄存器取决于您的操作系统(Windows专门让您跳过一些环节).我建议忘记这方面,并按照其他标准选择数据类型,例如:您实际需要什么精度*?将实现的详细信息留给编译器和优化器,除非你有一个*非常好的理由自己手动优化这些东西.(我曾经遇到的唯一情况是嵌入式硬件上的速度优化FFT). (2认同)

Die*_*ias 29

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

每个计算机科学家应该知道的浮点运算

这是关于内存带宽的前一个浮点x双栈溢出线程的引用

如果double需要比float更多的存储空间,那么读取数据需要更长的时间.这是天真的答案.在现代的IA32上,这一切都取决于数据的来源.如果它在L1高速缓存中,则只要数据来自单个高速缓存行,负载就可以忽略不计.如果它跨越多个缓存行,那么开销很小.如果它来自L2,它需要一段时间,如果它在RAM中那么它仍然更长,最后,如果它在磁盘上是一个巨大的时间.因此,浮点数或双精度数的选择不如数据的使用方式那么重要.如果要对大量顺序数据进行小型计算,则最好使用小数据类型.在小型数据集上进行大量计算将允许您使用具有任何显着效果的更大数据类型.如果您非常随机地访问数据,那么数据大小的选择并不重要 - 数据会加载到页面/缓存行中.因此,即使您只想从RAM中获取一个字节,也可以传输32个字节(这非常依赖于系统的体系结构).除此之外,CPU/FPU可以是超标量(也称为流水线).因此,即使负载可能需要几个周期,CPU/FPU也可能忙于做其他事情(例如乘法),将负载时间隐藏到一定程度


wat*_*180 13

简短的回答是:这取决于.

带有x87的CPU将会同时快速地处理浮动并加倍.矢量化代码将使用浮点运行得更快,因为SSE可以在一次通过中处理4个浮点数或2个双打.

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


Fre*_*man 6

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

但是,并行 SSE 指令将允许在一条指令中处理四个浮点数,但只能处理两个双精度数,因此这里的浮点速度可以明显更快。


Pet*_* G. 5

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

  1. 您的硬件支持双重操作,但不支持浮动操作,因此浮动将由软件模拟,因此速度较慢。

  2. 您确实需要双精度。现在,如果仍然使用浮点数,则必须使用两个浮点数才能达到类似的精度,从而翻倍。用浮点数模拟真正的double会比首先使用浮点数慢。

    1. 您不一定需要加倍,但由于加倍精度提高,因此数值算法的收敛速度更快。同样,双精度可能会提供足够的精度,以完全使用更快但数值不稳定的算法。

为了完整起见,我还给出了相反的浮点数更快的一些原因。您可以亲自了解在您的情况下占主导地位的原因:

  1. 当您不需要double的精度并且内存带宽受限制并且您的硬件不会对float造成损失时,float的速度比double快。

  2. 它们节省内存带宽,因为它们每个数字占用一半的空间。

  3. 还有一些平台可以并行处理多个浮点数。


Aka*_*wal 5

在20亿次加3.3的实验中,结果为:

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
Run Code Online (Sandbox Code Playgroud)

所以 double 更快,并且在 C 和 C++ 中是默认的。它更具可移植性,并且是所有 C 和 C++ 库函数的默认值。Alos double 的精度明显高于 float。

甚至 Stroustrup 也推荐双倍浮动:

“单精度、双精度和扩展精度的确切含义是实现定义的。为选择很重要的问题选择正确的精度需要对浮点计算有深入的了解。如果您不了解,请获取建议,花点时间学习,或者使用双倍并希望最好。”

也许您应该使用 float 而不是 double 的唯一情况是在具有现代 gcc 的 64 位硬件上。因为浮动更小;double 是 8 个字节,float 是 4 个字节。

  • 那么让我们期待最好的 (3认同)