Math.Pow与乘法运算符(性能)

任何人都知道乘法运算符是否比使用Math.Pow方法更快? 喜欢:

n * n * n 

VS

 Math.Pow ( n, 3 ) 

基本上,你应该基准看看。

受过教育的猜测(不可靠):

如果一些编译器没有对同一件事进行优化……

x * x * x很可能比Math.Pow(x, 3)更快Math.Pow(x, 3)因为Math.Pow必须在一般情况下处理问题,处理分数幂和其他问题,而x * x * x会只需要几个乘法指令,所以它很可能会更快。

我只是重新安装了Windows,因此没有安装visual studio并且代码很难看

 using System; using System.Diagnostics; public static class test{ public static void Main(string[] args){ MyTest(); PowTest(); } static void PowTest(){ var sw = Stopwatch.StartNew(); double res = 0; for (int i = 0; i < 333333333; i++){ res = Math.Pow(i,30); //pow(i,30) } Console.WriteLine("Math.Pow: " + sw.ElapsedMilliseconds + " ms: " + res); } static void MyTest(){ var sw = Stopwatch.StartNew(); double res = 0; for (int i = 0; i < 333333333; i++){ res = MyPow(i,30); } Console.WriteLine("MyPow: " + sw.ElapsedMilliseconds + " ms: " + res); } static double MyPow(double num, int exp) { double result = 1.0; while (exp > 0) { if (exp % 2 == 1) result *= num; exp >>= 1; num *= num; } return result; } } 

结果:
csc / o test.cs

TEST.EXE

 MyPow: 6224 ms: 4.8569351667866E+255 Math.Pow: 43350 ms: 4.8569351667866E+255 

平方的指数(参见https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int )比Math.Pow快得多在我的测试中(我的CPU是2 Ghz的Pentium T3200)

编辑:.NET版本是3.5 SP1,操作系统是Vista SP1和电源计划是高性能。

我昨天碰巧测试了这个,然后现在看到了你的问题。

在我的机器上,运行1个测试线程的Core 2 Duo,使用倍数最多为9倍。在10,Math.Pow(b,e)更快。

然而,即使在2倍的情况下,结果通常也不相同。 存在舍入错误。

某些算法对舍入误差非常敏感。 在我发现这一点之前,我不得不进行超过一百万次随机测试。

从图像处理和科学计算的10多年优化中获得一些经验法则:

算法级别的优化在低级别上优于任何数量的优化。 尽管“写明显,然后优化”的传统智慧必须在一开始就完成。 不是之后。

手动编码数学运算(特别是SIMD SSE +类型)通常优于完全错误检查,广义内置算法。

编译器优化了编译器预先知道需要完成的任何操作。 这些包括:1。内存操作,如Array.Copy()2。对于给定数组长度的数组上的循环。 和for( ..; i )一样

总是设置不切实际的目标(如果你愿意)。

我查了一下, Math.Pow()被定义为两个双打。 这意味着它不能重复乘法,但必须使用更通用的方法。 如果有一个Math.Pow(double, int) ,它可能会更有效率。

话虽如此,性能差异几乎肯定是微不足道的,所以你应该使用哪个更清楚。 像这样的微优化几乎总是没有意义,几乎可以在任何时候引入,并且应该留在开发过程的最后阶段。 此时,您可以检查软件是否太慢,热点位于何处,并将您的微优化工作花在实际上会产生影响的地方。

这是微观的,您可能应该针对特定平台进行基准测试,我认为Pentium Pro的结果不一定与ARM或Pentium II相同。

总而言之,它最有可能完全无关紧要。

我们使用约定x ^ n。 我们假设n总是一个整数。

对于小的n值,无聊乘法会更快,因为Math.Pow(可能依赖于实现)使用花哨算法来允许n为非整数和/或负数。

对于较大的n值,Math.Pow可能会更快,但如果你的库不是很聪明,它将使用相同的算法,如果你知道n总是一个整数,这是不理想的。 为此,您可以通过平方或其他一些奇特的算法来编写求幂的实现。

当然,现代计算机速度非常快,您应该坚持使用最简单,最容易阅读,最不可能是错误的方法,直到您对程序进行基准测试,并确保通过使用不同的算法获得显着的加速。

以下是有关内联乘法与Math.pow主题的讨论

显然Math.pow比较慢,但不是很多……

我不同意手工构建的function总是更快。 余弦函数比我能编写的任何函数都更快,更准确。 至于pow()。 我做了一个快速测试,看看Math.pow()在javascript中有多慢,因为Mehrdad告诫不要猜测

  for (i3 = 0; i3 < 50000; ++i3) { for(n=0; n < 9000;n++){ x=x*Math.cos(i3); } } 

结果如下:

 Each function run 50000 times time for 50000 Math.cos(i) calls = 8 ms time for 50000 Math.pow(Math.cos(i),9000) calls = 21 ms time for 50000 Math.pow(Math.cos(i),9000000) calls = 16 ms time for 50000 homemade for loop calls 1065 ms 

如果您不同意, 请访问http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html

Math.Pow(x, y)通常在内部计算为Math.Exp(Math.Log(x) * y) 。 Evey幂方程需要找到一个自然对数,一个乘法,并将e提高到一个幂。

正如我在之前的回答中所提到的,只有10的幂才能使Math.Pow()变得更快,但如果使用一系列乘法,精度将会受到影响。