为什么浮点数除法很慢?

23

浮点数除法算法的步骤是什么?

为什么它的结果比乘法慢?

它是否与我们手动进行的除法一样?通过反复除以除数,减去结果得到余数,再次对齐数字并继续直至余数小于特定值?

此外,如果我们使用牛顿-拉夫逊方法而不是传统的除法,为什么会提高性能?

a = b / c 

我们做什么

d = 1 / c
a = b * d

编辑: 基本上我的问题是因为有人要求我根据权重分配将一个值分配给参赛者。我用整数完成了所有操作,后来被要求转换为浮点数,这导致性能下降。我只是想知道C或C++如何执行这些操作会导致性能下降。


有关:浮点除法与浮点乘法,提供了现代x86的更详细数字。 - Peter Cordes
6个回答

25

浮点数除法通常基于Newton-Raphson(或其他算法)获取倒数,然后乘以该倒数。这就是为什么倒数操作略快于一般的除法操作。

这篇惠普公司的论文(实际上比我遇到的大多数讨论Newton-Raphson的论文更易懂)对浮点数除法有以下说明:

与加法和乘法相比,浮点数除法和平方根计算时间要长得多。前两个运算直接计算,而后者通常使用迭代算法进行计算。最常见的方法是使用无除法的Newton-Raphson迭代来获得分母(除法)或平方根的倒数近似值,然后乘以分子(除法)或输入参数(平方根)。


我并不是说HP的论文是错的,我对此一无所知,甚至都没有考虑过。然而,这篇论文最后修订于1994年,所以我猜流程设计至少在14年间有些变化 :-) 所以要对这篇论文持保留态度。 - Walden Leverich
1
@WaldenL 过程设计可能会发生变化(微型化),但算术几乎不会改变。 - Dimitar Slavchev

19

从硬件角度来看,除法是一种迭代算法,所需时间与位数成正比。目前最快的除法使用基数4算法,每次迭代生成4位结果。对于32位除法,至少需要8个步骤。

乘法可以在一定程度上并行计算。不详细介绍,您可以将大型乘法分解为多个较小且独立的乘法。这些乘法再次可以分解到位级别,或者更早停止并在硬件中使用小型查找表。这使得乘法硬件在硅芯片方面非常重,但速度也非常快。这是经典的大小/速度权衡。

您需要log2步骤来结合并行计算的结果,因此32位乘法需要5个逻辑步骤(如果最小化)。幸运的是,这5个步骤比除法步骤要简单得多(只涉及加法)。这意味着在实践中乘法甚至更快。


6

如维基百科文章除法算法所述,计算机中有两种主要的除法方法:

慢速除法

使用以下递归公式,每次迭代找到一个数字: partialRemainder[j+1] = radix * partialRemainder[j] - quotientDigit[n-(j+1)]*denominator

快速除法

从估计值开始并收敛于商。您的精度取决于迭代次数。

牛顿-拉弗森除法(简要介绍):

  1. 计算倒数的估计值。
  2. 计算更准确的倒数估计值。
  3. 通过将被除数乘以倒数来计算商。

1

做这个不会提高性能

d = 1 / c
a = b * d

您可能是指:

d = 1 / c
a1 = b1 * d
a2 = b2 * d

通过这种方式,除法只会执行一次。

除法本身比乘法要慢,但是我不知道细节。基本原因是,类似于sin或sqrt这样的函数,除法在数学上更加复杂。如果我没记错,在平均CPU上,乘法需要大约10个周期,而除法需要50个或更多。

John Mulder很好地解释了它的实际执行过程。


我一直想知道为什么,一个在循环中加,而另一个在减。也许是在循环中增加了while(x>=y)的额外测试,而不是直接迭代n...也许是为了将最终余数的十进制表示作为分数计算??? - Lawrence Dol
3
如果“c”是一个常数,通过乘以其倒数的方式可以确实节省时间。 - Nosredna
@软件猴子,ALU中的乘法是使用移位加法完成的,而不是添加n个被乘数,因此只需要k次迭代,其中k是您数字中的位数:http://en.wikipedia.org/wiki/Multiplication_ALU - Kothar

1
想一想所涉及的硬件,你就会更好地理解为什么除法比乘法需要花费更长的时间。这两个操作都是在浮点运算单元(FPU)级别下完成的,即使在整数ALU的世界中,除法电路也比乘法电路繁忙得多。我怀疑在浮点数的世界中,这只会更加痛苦,因为现在数据不仅按最不重要到最重要的数字顺序排列,而且还按照IEEE 754标准排序。
至于舍入,实际上是关于信号在门之间传输时焊接到地面的位置;当这种情况发生时,你会失去数字。不是舍入,而是截断。
或者你是在问如何使用整数模拟浮点算术?

0

浮点数除法比整数除法稍慢,但编译器可能无法进行相同的优化。

例如,编译器可以用乘法和二进制移位来替换3之间的整数除法。 同时,它可以用0.5的乘法来替换2.0之间的浮点除法,但是它不能用1/3.0的乘法来替换3.0之间的除法,因为在二进制数字中无法精确地表示1/3.0,因此舍入误差可能会改变除法的结果。由于编译器不知道您的应用程序对舍入误差的敏感程度如何(比如您正在进行天气模拟,请参见蝴蝶效应),因此它无法进行优化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接