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