在我看到的大多数代码中,double
是float
的最爱,即使不需要高精度。
由于在使用双重类型(CPU / GPU /内存/总线/缓存/ ...)时有performance penalties,这种双重过度使用的原因是什么?
示例:在计算流体动力学中,我使用的所有软件都使用了双打。在这种情况下,高精度是无用的(因为数学模型中的近似引起的误差),并且有大量的数据需要移动,使用浮点数可以减少一半。
今天的计算机功能强大这一事实毫无意义,因为它们被用来解决越来越复杂的问题。
答案 0 :(得分:22)
其中:
但最后,YMMV:衡量,测试并自行决定你的具体情况。
BTW:对性能狂热者来说还有更多:使用IEEE半精度类型。它存在很少的硬件或编译器支持,但它再次将你的带宽需求减半。答案 1 :(得分:11)
double
是C语言中的“自然”浮点类型,它也会影响C ++。考虑一下:
13.9
,其类型为double
。要使其浮动,我们必须添加额外的后缀f
或F
。float
函数参数 * 转换为double
:当没有参数声明时会发生这种情况,例如当一个函数被声明为variadic(例如printf
)或者没有声明时(旧式C,C ++中不允许)。%f
的{{1}}转换说明符需要printf
个参数,而不是double
。没有专门的方式来打印float
- s; float
参数默认 - 提升为float
,因此匹配double
。在现代硬件上,%f
和float
通常分别映射到32位和64位IEEE 754类型。硬件“本机”使用64位值:浮点寄存器为64位宽,操作围绕更精确的类型构建(或者内部可能比这更精确)。由于double
映射到该类型,因此它是“自然”浮点类型。
double
的精度对于任何严肃的数值工作来说都很差,而且范围缩小也可能是一个问题。 IEEE 32位类型只有23位尾数(指数字段消耗8位,符号消耗1位)。 float类型对于在大型浮点值数组中保存存储非常有用,前提是精度和范围的损失在给定的应用程序中不是问题。例如,有时在音频中使用32位浮点值来表示样本。
确实,使用32位类型的64位类型会使原始内存带宽加倍。但是,这只影响具有大量数据的程序,这些程序以显示不良局部性的模式访问。 64位浮点类型的卓越精度胜过优化问题。数值结果的质量比剃须周期的运行时间更重要,按照“先把它做好,然后再做快”的原则。
* 但请注意,float
表达式到float
没有通用的自动升级功能。唯一的推广是整体推广:double
,char
和位域转到short
。
答案 2 :(得分:9)
在我看来,到目前为止,答案并没有真正得到正确的观点,所以这是我对它的抨击。
简短的回答是C ++开发人员在浮点数上使用双打:
对于单个计算,它的真正双倍可能与浮点一样快,因为大多数FPU具有比32位浮点或64位双重表示更宽的内部表示。
然而,这只是图片的一小部分。如果您在缓存/内存带宽上存在瓶颈,那么现在的运营优化并不意味着什么。
这就是为什么一些寻求优化代码的开发人员应该考虑使用32位浮点数而不是64位双精度数据:
一般来说,我所遇到的大多数开发人员都缺乏对浮点数如何真正起作用的了解。所以我并不感到惊讶,大多数开发人员盲目地使用双倍。
答案 3 :(得分:7)
这主要取决于硬件,但考虑到最常见的CPU(基于x86 / x87)具有内部FPU,它以80位浮点精度(超过浮点数和双精度数)运行。
如果必须在内存中存储一些中间计算,则double是内部精度和外部空间的良好平均值。在单个值上,性能或多或少相同。它可能受到大型数字管道上的内存带宽的影响(因为它们具有双倍长度)。
考虑浮点数的精度约为6位小数。在N立方复杂性问题(如矩阵求逆或变换)上,您在mul
和div
中丢失了两到三个,只剩下3个有意义的数字。在1920像素宽的显示器上,它们是不够的(您需要至少5个才能正确匹配像素)。
这大致是双倍的优选。
答案 4 :(得分:4)
通常相对容易确定double是足够的,即使在需要进行大量数值分析以显示浮点数足够的情况下也是如此。这样可以节省开发成本,并且如果分析没有正确完成,则会产生错误结果的风险。
使用float的任何性能提升通常都比使用double更轻微,这是因为大多数流行的处理器都以一种格式进行所有浮点运算,甚至比双倍更宽。
答案 5 :(得分:3)
我认为更高的精确度是唯一的原因。实际上大多数人都不会想太多,他们只是使用双倍。
我认为如果浮点精度对于特定任务来说足够好,则没有理由使用double。