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