为什么双重优先于浮动?

时间:2014-04-02 17:09:29

标签: c++ performance floating-point double

在我看到的大多数代码中,doublefloat的最爱,即使不需要高精度。

由于在使用双重类型(CPU / GPU /内存/总线/缓存/ ...)时有performance penalties,这种双重过度使用的原因是什么?

示例:在计算流体动力学中,我使用的所有软件都使用了双打。在这种情况下,高精度是无用的(因为数学模型中的近似引起的误差),并且有大量的数据需要移动,使用浮点数可以减少一半。

今天的计算机功能强大这一事实毫无意义,因为它们被用来解决越来越复杂的问题。

6 个答案:

答案 0 :(得分:22)

其中:

  • 节省的费用几乎不值得(数字运算不典型)。
  • 舍入错误累积,因此从一开始就更好地达到比所需更高的精度(专家可能知道它无论如何都足够精确,并且可以进行精确的计算)。
  • 无论如何,在内部使用fpu的常见浮动操作通常会以双倍或更高的精度工作。
  • C和C ++可以隐式地从float转换为double,另一种方式需要显式转换。
  • Variadic和no-prototype函数总是变为double,而不是float。 (第二个只在古代C中并且积极劝阻)
  • 您通常可以以超过所需的精度进行操作,但很少用较少的操作,因此库通常也支持更高的精度。

但最后,YMMV:衡量,测试并自行决定你的具体情况。

BTW:对性能狂热者来说还有更多:使用IEEE半精度类型。它存在很少的硬件或编译器支持,但它再次将你的带宽需求减半。

答案 1 :(得分:11)

在某些方面,

double是C语言中的“自然”浮点类型,它也会影响C ++。考虑一下:

  • 一个朴素的普通浮点常量,如13.9,其类型为double。要使其浮动,我们必须添加额外的后缀fF
  • C中的
  • 默认参数提升float函数参数 * 转换为double:当没有参数声明时会发生这种情况,例如当一个函数被声明为variadic(例如printf)或者没有声明时(旧式C,C ++中不允许)。
  • %f的{​​{1}}转换说明符需要printf个参数,而不是double。没有专门的方式来打印float - s; float参数默认 - 提升为float,因此匹配double

在现代硬件上,%ffloat通常分别映射到32位和64位IEEE 754类型。硬件“本机”使用64位值:浮点寄存器为64位宽,操作围绕更精确的类型构建(或者内部可能比这更精确)。由于double映射到该类型,因此它是“自然”浮点类型。

double的精度对于任何严肃的数值工作来说都很差,而且范围缩小也可能是一个问题。 IEEE 32位类型只有23位尾数(指数字段消耗8位,符号消耗1位)。 float类型对于在大型浮点值数组中保存存储非常有用,前提是精度和范围的损失在给定的应用程序中不是问题。例如,有时在音频中使用32位浮点值来表示样本。

确实,使用32位类型的64位类型会使原始内存带宽加倍。但是,这只影响具有大量数据的程序,这些程序以显示不良局部性的模式访问。 64位浮点类型的卓越精度胜过优化问题。数值结果的质量比剃须周期的运行时间更重要,按照“先把它做好,然后再做快”的原则。


* 但请注意,float表达式到float没有通用的自动升级功能。唯一的推广是整体推广:doublechar和位域转到short

答案 2 :(得分:9)

在我看来,到目前为止,答案并没有真正得到正确的观点,所以这是我对它的抨击。

简短的回答是C ++开发人员在浮点数上使用双打:

  • 当他们不能很好地理解性能权衡时避免过早优化(“他们有更高的精度,为什么不呢?”是思想过程)
  • 习惯
  • 文化
  • 匹配库函数签名
  • 匹配简单到写的浮点文字(你可以写0.0而不是0.0f)

对于单个计算,它的真正双倍可能与浮点一样快,因为大多数FPU具有比32位浮点或64位双重表示更宽的内部表示。

然而,这只是图片的一小部分。如果您在缓存/内存带宽上存在瓶颈,那么现在的运营优化并不意味着什么。

这就是为什么一些寻求优化代码的开发人员应该考虑使用32位浮点数而不是64位双精度数据:

  • 他们只有一半的记忆力。这就像让你的所有缓存都大两倍。 (大赢!!!)
  • 如果您真的关心性能,您将使用SSE说明。对浮点值进行操作的SSE指令对32位和64位浮点表示具有不同的指令。 32位版本可以在128位寄存器操作数中容纳4个值,但64位版本只能容纳2个值。在这种情况下,您可以通过使用浮点数超过双倍来使您的FLOPS加倍,因为每条指令的运行数据是两倍。

一般来说,我所遇到的大多数开发人员都缺乏对浮点数如何真正起作用的了解。所以我并不感到惊讶,大多数开发人员盲目地使用双倍。

答案 3 :(得分:7)

这主要取决于硬件,但考虑到最常见的CPU(基于x86 / x87)具有内部FPU,它以80位浮点精度(超过浮点数和双精度数)运行。

如果必须在内存中存储一​​些中间计算,则double是内部精度和外部空间的良好平均值。在单个值上,性能或多或少相同。它可能受到大型数字管道上的内存带宽的影响(因为它们具有双倍长度)。

考虑浮点数的精度约为6位小数。在N立方复杂性问题(如矩阵求逆或变换)上,您在muldiv中丢失了两到三个,只剩下3个有意义的数字。在1920像素宽的显示器上,它们是不够的(您需要至少5个才能正确匹配像素)。

这大致是双倍的优选。

答案 4 :(得分:4)

通常相对容易确定double是足够的,即使在需要进行大量数值分析以显示浮点数足够的情况下也是如此。这样可以节省开发成本,并且如果分析没有正确完成,则会产生错误结果的风险。

使用float的任何性能提升通常都比使用double更轻微,这是因为大多数流行的处理器都以一种格式进行所有浮点运算,甚至比双倍更宽。

答案 5 :(得分:3)

我认为更高的精确度是唯一的原因。实际上大多数人都不会想太多,他们只是使用双倍。

我认为如果浮点精度对于特定任务来说足够好,则没有理由使用double。