我正在阅读“加速C ++”。我发现一句话说“有时double
的执行速度比C ++中的float
快”。读完句子后,我对float
和double
工作感到困惑。请向我解释这一点。
答案 0 :(得分:46)
取决于本机硬件的功能。
如果硬件实现了double(就像x86那样),那么通过在那里扩展它来模拟float,转换将花费时间。在这种情况下,double会更快。
如果硬件只实现浮动,那么用它模拟双倍将花费更多的时间。在这种情况下,浮动会更快。
如果硬件没有实现,两者都必须用软件实现。在这种情况下,两者都会很慢,但是double会稍慢一些(至少会有更多的加载和存储操作)。
你提到的引用可能是指x86平台,第一个案例是。但这一般不成立。
答案 1 :(得分:28)
您可以在本文中找到完整的答案:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
这是前一个Stack Overflow线程的引用,关于float
和double
变量如何影响内存带宽:
如果双重要求 比浮动更多的存储,然后它 将需要更长时间来读取数据。 这是天真的答案。在现代 IA32,这一切都取决于数据的位置 是来自。如果它在L1缓存中, 如果负载可以忽略不计 数据来自单个缓存行。 如果它跨越多个缓存行 这是一个很小的开销。如果它来自 L2,它需要一段时间,如果是的话 在RAM中然后它仍然更长 最后,如果它在磁盘上是一个巨大的 时间。所以浮动或双重的选择 比数据的方式更不重要 用来。如果你想做一个小的 大量顺序计算 数据,小数据类型是优选的。 做了很多小的计算 数据集可以让你使用更大的 任何重要的数据类型 影响。如果您正在访问数据 随机,然后选择数据 大小不重要 - 加载数据 在页面/缓存行中。所以即使你 只想从RAM中获取一个字节,你可以 获得32个字节的转移(这是非常的 取决于的架构 系统)。除此之外,还有 CPU / FPU可能是超标量(也就是说 流水线)。所以,即使负载可能 需要几个周期,CPU / FPU可以 忙着做别的事情(a 例如,乘以隐藏的 加载时间到一定程度
答案 2 :(得分:13)
简短回答是:取决于。
带有x87的CPU将会同时快速地处理浮动并加倍。矢量化代码将使用浮点运行得更快,因为SSE可以在一次通过中处理4个浮点数或2个双打。
要考虑的另一件事是内存速度。根据您的算法,您的CPU在等待数据时可能会闲置很多。内存密集型代码将受益于使用浮点数,但ALU有限代码不会(除非它是矢量化的)。
答案 3 :(得分:4)
当双打比浮点数快时,我可以想到两个基本情况:
您的硬件支持双操作但不支持浮点操作,因此浮点数将由软件模拟,因此速度较慢。
你真的需要双精度。现在,如果你使用浮子,你将不得不使用两个浮点数达到相似的精度加倍。使用浮点数模拟真正的双精度比首先使用浮点数慢。
为了完整起见,我还给出了浮动更快的相反情况的一些原因。您可以自己查看哪些理由在您的案例中占主导地位:
当你不需要双倍时,浮动速度比双精度快 精度和你的内存带宽和你的硬件 不会对花车进行处罚。
它们可以节省内存带宽,因为它们占用了一半的空间 每个号码。
还有一些平台可以处理比双打更多的浮动 并行。
答案 4 :(得分:3)
在英特尔,协处理器(现在集成)将同样快速处理,但正如其他一些人所指出的那样,双倍会导致更高的内存带宽,从而导致瓶颈。如果您正在使用标量SSE指令(64位大多数编译器的默认值),则同样适用。因此,一般情况下,除非您正在处理大量数据,否则无关紧要。
然而,并行SSE指令将允许在一条指令中处理四个浮点数,但只有两个双精度数,所以这里浮点数可以明显更快。
答案 5 :(得分:3)
只有一个原因是32位浮点数比64位双精度数(或80位80x87)慢。这是一致的。除此之外,浮点数占用的内存较少,通常意味着访问速度更快,缓存性能更好。处理32位指令也需要更少的周期。即使(共)处理器没有32位指令,它也可以以相同的速度在64位寄存器上执行它们。它可能会创建一个测试用例,其中双精度比浮点数更快,而v.v.,但我对真实统计算法的测量结果没有显示出明显的差异。
答案 6 :(得分:1)
浮动通常更快。 double提供更高的精度。但是,如果使用特殊处理器扩展(如3dNow或SSE),性能可能会有所不同。
答案 7 :(得分:1)
在添加3.3次200万次的实验中,结果是:
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
因此,在C和C ++中,double更快且默认。它更易于移植,是所有C和C ++库函数的默认值。 Alos double的精度明显高于float。
即使Stroustrup建议翻倍浮动:
“单精度,双精度和扩展精度的确切含义是实现定义的。为选择重要的问题选择合适的精度需要对浮点计算有重要的理解。如果你没有那个理解,获得建议,花时间学习,或使用双重和希望最好。“
也许唯一一种你应该使用float而不是double的情况是64位硬件和现代gcc。因为浮子较小; double是8个字节,float是4个字节。