为什么平方根这么慢?

Are*_*res 7 c# vb.net math square-root operator-keyword

我被许多程序员警告不要使用平方根功能,而是将数字提升到半功率.我的问题是双重的:

  1. 这样做的感知/真实表现有什么好处?为什么它更快?

  2. 如果它真的更快,为什么平方根函数甚至存在?

Dmi*_*nko 15

我做了一个简单的测试:

  Stopwatch sw = new Stopwatch();

  sw.Start();

  Double s = 0.0;

  // compute 1e8 times either Sqrt(x) or its emulation as Pow(x, 0.5)
  for (Double d = 0; d < 1e8; d += 1)
    // s += Math.Sqrt(d);  // <- uncomment it to test Sqrt
    s += Math.Pow(d, 0.5); // <- uncomment it to test Pow

  sw.Stop();

  Console.Out.Write(sw.ElapsedMilliseconds);
Run Code Online (Sandbox Code Playgroud)

我的工作站(x64)的(平均)结果是

  Sqrt:  950 ms 
  Pow:  5500 ms
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,比其仿真速度快Sqrt(x) 5.5倍.所以它只是另一个传奇(至少在C#中),那个慢的人应该更喜欢替换Pow(x, 0.5)SqrtPow

  • 在测试(特别是)数学函数时,通常还需要声明目标平台或测试`x86`和`x64`.由于硬件实现通常非常不同,因此有时会出现令人惊讶的差异(尽管在这种情况下并不多).从时代的角度来看,我猜这个例子是`x64`.对于`x86`,`Pow`只是快一点(但仍然比`sqrt`慢*多*). (6认同)
  • @duffymo这有点不言而喻.瓶颈总是在"代码"的某个地方.但是,如果你碰巧在*性能瓶颈中用'Pow`*替换`sqrt`,那么你就可以通过不做而获益. (4认同)
  • +1用于演示测试此方案的容易程度 (3认同)
  • 注意:1亿次SLOWER操作需要5.5秒.1亿次FAST操作不到一秒钟.您的代码将成为瓶颈,而不是这些函数调用. (3认同)
  • 当然,瓶颈在于某人的代码。我的观点是,重要的更有可能出现在 OP 的代码中,而不是这些函数中。分析器不太可能说平方根函数正在扼杀性能。 (2认同)

duf*_*ymo 9

您必须了解每个函数如何实现以回答问题.

平方根函数使用牛顿方法迭代计算平方根.它以二次方式收敛.什么都不会加快速度.

其他函数exp()和ln(x)具有自己的收敛/复杂性问题的实现.例如,可以将两者都实现为序列和.需要一定数量的术语才能保持足够的准确性.

如果这些功能碰巧在本机代码中实现,那么所有的赌注都会被取消.那些可能比你写的任何东西都要快.

了解这些将让您做出明智的决定.我不会信仰它,因为那些程序员"知道"答案.

除非你正在进行密集的数字工作,否则我会说这个选择不会影响你的整体计划表现.除非你正在进行严肃的大规模科学编程,否则最好避免微观优化.

  • 如果你正在做严肃的科学编程,那么你的算法的数值稳定性和避免 [灾难性取消](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) 很可能是与速度一样(甚至更)重要。 (2认同)
  • 在这种情况下,`Sqrt` *是*在硬件中实现的,适用于 x87 FPU(`fsqrt` - 32 位)和 SSE/SSE2(`sqrtss`、`sqrtps`;`sqrtsd`、`sqrtpd` - 64 位) )。这些比`Pow`等的软件实现要快得多。即使在具有`f2xm1`、`fyl2x`等实现的x87硬件上,只需调用`f2xm1`(这只会让你开始实现` pow`) 几乎和完整的 `fsqrt` 一样昂贵,而 `fyl2x` 比 `fsqrt` 长三倍多。除非非常特定的边缘情况和聪明的算法,否则“Pow”不可能更快。 (2认同)