使用float
类型比使用类型慢double
吗?
我听说现代 Intel 和 AMD CPU 可以比浮点数更快地进行双精度计算。
标准数学函数(sqrt
、pow
、log
、sin
、cos
等)呢?以单精度计算它们应该会快得多,因为它应该需要更少的浮点运算。例如,单精度sqrt
可以使用比双精度更简单的数学公式sqrt
。另外,我听说标准数学函数在 64 位模式下更快(在 64 位操作系统上编译和运行时)。这个问题的最终答案是什么?
使用float
类型比使用类型慢double
吗?
我听说现代 Intel 和 AMD CPU 可以比浮点数更快地进行双精度计算。
标准数学函数(sqrt
、pow
、log
、sin
、cos
等)呢?以单精度计算它们应该会快得多,因为它应该需要更少的浮点运算。例如,单精度sqrt
可以使用比双精度更简单的数学公式sqrt
。另外,我听说标准数学函数在 64 位模式下更快(在 64 位操作系统上编译和运行时)。这个问题的最终答案是什么?
经典的 x86 架构使用浮点单元 (FPU) 来执行浮点计算。FPU 在其内部寄存器中执行所有计算,每个寄存器都有 80 位精度。每次尝试使用float
ordouble
时,首先将变量从内存加载到 FPU 的内部寄存器中。这意味着实际计算的速度绝对没有差异,因为在任何情况下,计算都是以完全 80 位精度执行的。唯一可能不同的是从内存加载值并将结果存储回内存的速度。自然,在 32 位平台上double
,与float
. 在 64 位平台上应该没有任何区别。
现代 x86 架构通过新指令支持扩展指令集 (SSE/SSE2),这些指令可以在不涉及“旧”FPU 指令的情况下执行完全相同的浮点计算。但是,我不希望看到float
和的计算速度有任何差异double
。由于这些现代平台是 64 位的,因此加载/存储速度也应该是相同的。
在不同的硬件平台上,情况可能会有所不同。但通常较小的浮点类型不应提供任何性能优势。较小的浮点类型的主要目的是节省内存,而不是提高性能。
编辑:(解决@MSalters 评论)我上面所说的适用于基本算术运算。当谈到库函数时,答案将取决于几个实现细节。如果平台的浮点指令集包含实现给定库函数功能的指令,那么我上面所说的通常也适用于该函数(通常包括函数,如sin
, cos
, sqrt
)。对于其他功能,其功能在 FP 指令集中没有立即得到支持,情况可能会大不相同。很有可能float
这些功能的版本可以比它们的double
版本更有效地实现。
您的第一个问题已经在 SO 上得到了回答。
您的第二个问题完全取决于您正在使用的数据的“大小”。这一切都归结为系统的低级架构以及它如何处理大值。32 位系统中的 64 位数据需要 2 个周期才能访问 2 个寄存器。64 位系统上的相同数据应该只需要 1 个周期来访问 1 个寄存器。
一切总是取决于你在做什么。我发现没有快速而硬性的规则,因此您需要分析当前任务并选择最适合您对该特定任务的需求的方法。
根据我在 Java 中所做的一些研究和经验测量:
在某些特殊情况下,例如内存带宽问题超过“原始”计算时间也是事实。
虽然在大多数系统上与单个值double
的速度相同float
,但您说得对,单精度计算函数(如sqrt
,sin
等)应该比双精度计算快得多。在 C99 中,即使您的变量是 ,您也可以使用 、 等函数sqrtf
,并从中受益。sinf
double
我看到的另一个问题是内存(以及存储设备)带宽。如果您有数百万或数十亿的值要处理,几乎肯定会比所有内容都受内存限制或 io 限制float
快两倍。double
在某些情况下,这是float
用作数组或磁盘存储中的类型的一个很好的理由,但我认为这不是float
用于计算变量的一个很好的理由。
x86 FPU 中的“本机”内部浮点表示为 80 位宽。这与float
(32 位)和double
(64 位)都不同。每次值移入或移出 FPU 时,都会执行一次转换。只有一条 FPU 指令执行sin操作,它适用于内部 80 位表示。
这种转换是否更快取决于许多因素,并且必须针对给定的应用程序进行测量float
。double
这取决于处理器。如果处理器具有本机双精度指令,通常只执行双精度运算比给定一个浮点数,将其转换为双精度,执行双精度运算,然后将其转换回浮点数更快.