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

时间:2009-06-01 20:14:25

标签: c# .net performance pow

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

n * n * n

VS

Math.Pow ( n, 3 )

11 个答案:

答案 0 :(得分:37)

我刚刚重新安装了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 :(得分:28)

基本上,您应该基准来查看。

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

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

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

答案 2 :(得分:6)

图像处理优化10年以上的一些经验法则科学计算:

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

手动编码的数学运算(尤其是SIMD SSE +类型)通常会优于完整的错误检查,广义的内置运算。

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

一样

始终设定不切实际的目标(如果您愿意)。

答案 3 :(得分:6)

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

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

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

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

答案 4 :(得分:4)

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

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

答案 5 :(得分:4)

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

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

答案 6 :(得分:2)

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

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

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

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

答案 7 :(得分:1)

以下是关于inlined multiplication vs. Math.pow

主题的讨论

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

答案 8 :(得分:1)

我不同意手工构建的功能总是更快。余弦函数比我能编写的任何函数都更快,更准确。至于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

上的程序

答案 9 :(得分:0)

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

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

答案 10 :(得分:-2)

根据这个javascript基准Math.pow对于Math.pow(Math.rand(), 3);

https://jsbench.me/mokq80jj8i/1

但这些几乎没有区别:

Compare pow vs * * *, pow has 98 million ops/s and *** has 94 million ops/s