【问题标题】:Stop double division before decimals (low precision, fast division; getting only the 'quotient')停止小数前的双除(低精度,快速除法;只得到“商”)
【发布时间】:2017-02-01 13:28:36
【问题描述】:

基本上是一个与性能相关的问题:

我只想从双除法中得到整数商,例如,对于除法88.3/12.7 = 6.9527559055118110236220472440945,我只想得到“6”作为结果。 一个可能的实现当然是:floor(x/y),但在这里,首先完成了性能密集型双除法,然后 floor 丢弃了双除法所做的大部分“工作”。

所以基本上我想要一个双精度除法,它在计算所有这些小数点之前“停止”,只给我正确的除法整数结果,而不用舍入或截断初始双精度参数。有谁知道这个的优雅实现(我搜索了这个主题但没有找到太多)?

我能想象的另一个实现是: int(x*1000)/int(y*1000) 可以使用所需的“精度”而不是 1000。一个非常简单的实现也是简单地从 x 中减去 y,直到结果小于零。但是,是的,我想知道最好的方法是什么。

另外,简单地使用int(x)/int(y) 是不行的,因为它很容易导致错误的结果。

顺便说一句,我知道这可能又是这些“微优化”问题之一,它处理一个在新机器上并不重要的问题,但是,我仍然对这个主题有点好奇! :-)

【问题讨论】:

  • 整数和浮点除法时间相同。 32 位除法比 64 位除法快。如果分母足够有限,您可以使用查找表来获得倒数,那么乘法会快得多。
  • 问题是你不能真的只做除法的“一部分”来获得非小数。至少我是这么认为的,因为我不擅长高等数学。除非您绝对想要代码,否则也许可以在 math.stackexchange.com 上询问如何仅获得除法的非小数部分?

标签: c++ performance division


【解决方案1】:

没有办法提前停止,使用整数除法可能会更慢。

例如,在 Skylake 上:

idiv r/m32 L: 26-27 T: 6
divsd xmm, xmm L: 13-14 T: 4

(source)

因此,双除法的速度是原来的两倍,并且吞吐量明显提高。那是你考虑额外的乘法和额外的演员。

在较旧的 µarchs 上,32 位整数除法通常比双除法列出的延迟数更低,它们变化更多(除法过去更串行),(对于浮点数)圆形除数更快然而对于整数除法,它的小结果更快。这种特性上的差异可以让它左右摇摆,这取决于你除以什么。

如您所见,在这种情况下,在没有考虑特定目标的情况下进行优化是很危险的,但我认为新机器比旧机器更有可能成为目标,这意味着双除法或多或少是您能做的最好的(除非适用其他优化)。除单精度浮点数本身更快,但会产生转换成本,如果将它们相加,实际上最终会损失 (5+10)。

【讨论】:

  • 感谢您的好回答。作为比编程更接近数学/物理的人,我很惊讶整数除法比浮点/双除法要慢。
  • @kushy 准备更加惊讶:64 位整数除法通常(如在大多数 µarchs 中)需要多达 90 个周期。完全出乎意料。无论如何,我想这主要是一个焦点问题,我相对确定他们 可以 使 32 位整数除法至少与双除法一样快(我的意思是,要除的位数更少,有点。 . 取决于您查看的操作数。至少,它不需要慢两倍),但选择不这样做。
猜你喜欢
  • 2011-12-04
  • 2018-11-14
  • 1970-01-01
  • 2018-08-09
  • 2017-12-18
  • 1970-01-01
  • 2012-05-13
  • 2013-09-26
  • 1970-01-01
相关资源
最近更新 更多