浮动慢于双倍? 64位程序运行速度比32位程序快吗?

时间:2011-04-21 01:14:50

标签: c# java c++ c static-typing

使用float类型比使用double类型慢吗?

我听说现代的英特尔和AMD CPU可以比使用浮点数更快地进行双倍计算。

标准数学函数(sqrtpowlogsincos等等?以单精度计算它们应该相当快,因为​​它应该需要更少的浮点运算。例如,单精度sqrt可以使用比双精度sqrt更简单的数学公式。另外,我听说标准数学函数在64位模式下更快(在64位操作系统上编译和运行时)。对此有何明确答案?

6 个答案:

答案 0 :(得分:11)

经典的x86架构使用浮点单元(FPU)来执行浮点计算。 FPU在其内部寄存器中执行所有计算,每个寄存器具有80位精度。每次尝试使用floatdouble时,变量首先从内存加载到FPU的内部寄存器中。这意味着实际计算的速度绝对没有差异,因为在任何情况下,计算都以完全80位精度执行。唯一可能不同的是从内存加载值并将结果存储回内存的速度。当然,与double相比,在32位平台上加载/存储float可能需要更长时间。在64位平台上应该没有任何区别。

现代x86架构支持带有新指令的扩展指令集(SSE / SSE2),这些指令可以执行完全相同的浮点计算,而不涉及“旧的”FPU指令。但是,我再也不希望看到floatdouble的计算速度有任何差异。由于这些现代平台是64位的,因此加载/存储速度应该是相同的。

在不同的硬件平台上,情况可能会有所不同。但通常较小的浮点类型不应提供任何性能优势。较小的浮点类型的主要目的是节省内存,而不是提高性能。

编辑:(解决@MSalters评论) 我上面所说的适用于基​​本的算术运算。说到库函数,答案取决于几个实现细节。如果平台的浮点指令集包含实现给定库函数功能的指令,那么我上面所说的通常也适用于该函数(通常包括sin,{{1 },cos)。对于FP指令集中不立即支持其功能的其他功能,情况可能会有很大差异。这些函数的sqrt版本很可能比float版本更有效地实现。

答案 1 :(得分:6)

您的第一个问题已经回答here on SO

您的第二个问题完全取决于您正在使用的数据的“大小”。这一切都归结为系统的低级架构以及它如何处理大值。 32位系统中的64位数据需要2个周期才能访问2个寄存器。 64位系统上的相同数据只需1个周期即可访问1个寄存器。

一切都取决于你在做什么。我发现没有快速和严格的规则,因此您需要分析当前任务并选择最适合您特定任务需求的任务。

答案 2 :(得分:2)

我在Java中做过的一些研究和实证测量:

  • 对双打和浮点数的基本算术运算基本上在英特尔硬件上执行相同的操作,除了除法;
  • 另一方面,在iPhone 4和iPad上使用的Cortex-A8上,即使对双打的“基本”算术也需要大约两倍于浮点数(浮点数上的寄存器FP增加约4ns对比a在一个双重注册FP约9ns);
  • 我已经制作了一些可能感兴趣的timings of methods on java.util.Math(三角函数等) - 原则上,其中一些可能在浮点数上更快,因为需要更少的项来计算a的精度浮动;另一方面,其中许多最终“没有你想象的那么糟糕”;

也可能存在特殊情况,例如:内存带宽问题超过“原始”计算时间。

答案 3 :(得分:1)

x86 FPU中的“本机”内部浮点表示为80位宽。这与float(32位)和double(64位)不同。每当值移入或移出FPU时,都会执行转换。只有一条FPU指令执行 sin 操作,它适用于内部80位表示。

floatdouble的转化速度是否更快取决于许多因素,必须针对给定的应用进行衡量。

答案 4 :(得分:1)

虽然在大多数系统上double与单个值的float速度相同,但您在sqrtsin等计算功能方面是正确的。单精度应该比将它们计算到双精度要快很多。在C99中,即使您的变量为sqrtf,也可以使用sinfdouble等函数,并获得好处。

我看到的另一个问题是内存(以及存储设备)带宽。如果您有数百万或数十亿的值要处理,float几乎肯定会是double的两倍,因为一切都将受内存限制或受限制。在某些情况下,这是使用float作为数组或磁盘存储中的类型的一个很好的理由,但我不认为将float用于计算变量是一个很好的理由用。

答案 5 :(得分:0)

这取决于处理器。如果处理器具有本机双精度指令,那么执行双精度算术通常比给定浮点数更快,将其转换为double,执行双精度算术,然后将其转换回浮点数