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

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

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

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

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

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

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

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

你的第一个问题已在SO上回答了 。

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

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

从我在Java中进行的一些研究和实证测量:

  • 双重和浮点数的基本算术运算基本上在英特尔硬件上执行相同的操作,除了除法;
  • 另一方面,在iPhone 4和iPad上使用的Cortex-A8上,即使是双倍的“基本”算术也需要大约两倍于浮点数(浮点数上的寄存器FP增加约4ns而不是寄存器FP)双人约9ns);
  • 我已经在java.util.Math (三角函数等) 上做了一些方法的时间,这可能是有意义的 – 原则上,其中一些可能在浮点数上更快,因为需要更少的项来计算精度一个浮子; 另一方面,其中许多最终“没有你想象的那么糟糕”;

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

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

floatdouble转换是否更快取决于许多因素,并且必须针对给定的应用进行测量。

虽然在大多数系统中, double对于单个值的float速度与float速度相同,但你认为单精度计算函数如sqrtsin等应该比将它们计算为双精度要快得多。 在C99中,即使变量是double ,也可以使用sqrtfsinf等函数,并获得好处。

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

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