使用比浮动更快的双倍?

问题描述 投票:63回答:7

双值存储更高的精度并且是浮点数的两倍,但英特尔CPU是否针对浮点数进行了优化?

也就是说,双重操作与+, - ,*和/的浮点运算一样快或快。

对于64位架构,答案是否会改变?

c++ performance x86 intel osx-snow-leopard
7个回答
72
投票

没有一个“intel CPU”,特别是在哪些操作相对于其他操作进行优化方面!但是大多数,在CPU级别(特别是在FPU内),都是这样的问题的答案:

对于+, - ,*和/?的浮点运算是快速还是快速的双重操作?

是“是” - 在CPU内,除了分区和sqrt是somewhat slower for double than for float。 (假设您的编译器使用SSE2进行标量FP数学运算,就像所有x86-64编译器一样,以及一些32位编译器,具体取决于选项。旧版x87在寄存器中没有不同的宽度,仅在内存中(它在加载/存储时转换) ),所以历史上甚至sqrt和分区对double来说都很慢)。

例如,Haswell的divsd吞吐量为每8到14个循环一个(数据相关),但divss(标量单个)吞吐量为每7个循环一个。 x87 fdiv的循环吞吐量为8到18。 (来自https://agner.org/optimize/的数字。延迟与除法的吞吐量相关,但高于吞吐量数字。)

floatlogf(float)这样的许多库函数的sinf(float)版本也将比log(double)sin(double)更快,因为它们具有更少的精度来实现。他们可以使用更少项的多项式近似来获得floatdouble的完全精度


但是,为每个数字占用两倍的内存显然意味着缓存上的负载更重,并且需要更多的内存带宽来填充和溢出RAM中的缓存行;您关心浮点运算性能的时间是在执行大量此类运算时,因此内存和缓存注意事项至关重要。

@ Richard的答案指出还有其他方法可以执行FP操作(SSE / SSE2指令;好的旧MMX只有整数),特别适用于大量数据的简单操作(“SIMD”,单指令/多数据) )其中每个向量寄存器可以包含4个单精度浮点数或仅包含2个双精度浮点数,因此这种效果将更加明显。

最后,你必须进行基准测试,但我的预测是,对于合理的(即大的;-)基准测试,你会发现坚持单一精度的优势(当然假设你不需要额外的位数)精确!-)。


24
投票

如果在FPU内执行所有浮点计算,那么,不,double计算和float计算之间没有差异,因为浮点运算实际上是在FPU堆栈中以80位精度执行的。 FPU堆栈的条目根据需要进行舍入,以将80位浮点格式转换为doublefloat浮点格式。将sizeof(double)字节移入/移出RAM与sizeof(float)字节是唯一的速度差异。

但是,如果你有一个可矢量化的计算,那么你可以使用SSE扩展在两次float计算的同时运行四个double计算。因此,巧妙地使用SSE指令和XMM寄存器可以在仅使用floats的计算中实现更高的吞吐量。


11
投票

另一点需要考虑的是你是否使用GPU(显卡)。我在一个数字密集的项目中工作,但我们不需要双重提供的精确度。我们使用GPU卡来帮助进一步加快处理速度。 CUDA GPU需要一个特殊的软件包才能支持double,GPU上的本地RAM数量非常快,但非常稀缺。因此,使用float也会使我们可以存储在GPU上的数据量翻倍。

另一点是记忆。浮点数占用RAM的一半。如果您正在处理非常大的数据集,这可能是一个非常重要的因素。如果使用双重意味着你必须缓存到磁盘与纯ram,你的差异将是巨大的。

因此,对于我正在使用的应用程序,差异非常重要。


10
投票

我只想补充已经存在的伟大答案,__m256?系列的同一指令多数据(SIMD)C ++内在函数并行运行4个double(例如_mm256_add_pd),或并行运行8个floats(例如_mm256_add_ps) )。

我不确定这是否可以转化为实际的加速,但是当使用SIMD时,每条指令可以处理2倍的浮点数。


9
投票

在添加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个字节。


7
投票

唯一真正有用的答案是:只有你能说出来。您需要对场景进行基准测试。指令和内存模式的微小变化可能会产生重大影响。

如果你使用的是FPU或SSE类型的硬件,那将无关紧要(以前的所有工作都是80位扩展精度,所以double会更接近;后来本身是32位,即浮点数)。

更新:s / MMX / SSE /,如另一个答案所述。


2
投票

浮点通常是一个通用CPU的扩展。因此,速度取决于所使用的硬件平台。如果平台有浮点支持,如果有任何不同,我会感到惊讶。

© www.soinside.com 2019 - 2024. All rights reserved.