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

发布于 2024-07-23 11:30:06 字数 135 浏览 5 评论 0 原文

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

n * n * n

vs

Math.Pow ( n, 3 )

Anyone knows if multiply operator is faster than using the Math.Pow method? Like:

n * n * n

vs

Math.Pow ( n, 3 )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

九八野马 2024-07-30 11:30:06

我刚刚重新安装了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 是 Pentium T3200,2 Ghz)

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

I just reinstalled windows so visual studio is not installed and the code is ugly

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;
}
}

The results:
csc /o test.cs

test.exe

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

Exponentiation by squaring (see https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int) is much faster than Math.Pow in my test (my CPU is a Pentium T3200 at 2 Ghz)

EDIT: .NET version is 3.5 SP1, OS is Vista SP1 and power plan is high performance.

黎歌 2024-07-30 11:30:06

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

有根据的猜测(不可靠):

如果某些编译器没有针对相同的事情进行优化...

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

Basically, you should benchmark to see.

Educated Guesswork (unreliable):

In case it's not optimized to the same thing by some compiler...

It's very likely that x * x * x is faster than Math.Pow(x, 3) as Math.Pow has to deal with the problem in its general case, dealing with fractional powers and other issues, while x * x * x would just take a couple multiply instructions, so it's very likely to be faster.

套路撩心 2024-07-30 11:30:06

十多年来图像处理和图像优化的一些经验法则 科学计算:

算法级别的优化胜过任何低级别的优化。 尽管有“写出显而易见的内容,然后进行优化”的传统观念,但这必须从一开始就完成。 不是之后。

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

编译器预先知道需要做什么的任何操作都会被编译器优化。 这些包括:
1.Array.Copy()等内存操作
2. 对于给定数组长度的数组进行 For 循环。 就像 for (...; i) 一样,

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

A few rules of thumb from 10+ years of optimization in image processing & scientific computing:

Optimizations at an algorithmic level beat any amount of optimization at a low level. Despite the "Write the obvious, then optimize" conventional wisdom this must be done at the start. Not after.

Hand coded math operations (especially SIMD SSE+ types) will generally outperform the fully error checked, generalized inbuilt ones.

Any operation where the compiler knows beforehand what needs to be done are optimized by the compiler. These include:
1. Memory operations such as Array.Copy()
2. For loops over arrays where the array length is given. As in for (..; i<array.Length;..)

Always set unrealistic goals (if you want to).

三月梨花 2024-07-30 11:30:06

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

在我的机器上,Core 2 Duo 运行 1 个测试线程,使用乘以 9 倍的速度更快。在 10 倍时,Math.Pow(b, e) 更快。

然而,即使是 2 倍,结果也常常不相同。 存在舍入误差。

一些算法对舍入误差高度敏感。 在我发现这一点之前,我实际上必须进行超过一百万次随机测试。

I just happened to have tested this yesterday, then saw your question now.

On my machine, a Core 2 Duo running 1 test thread, it is faster to use multiply up to a factor of 9. At 10, Math.Pow(b, e) is faster.

However, even at a factor of 2, the results are often not identical. There are rounding errors.

Some algorithms are highly sensitive to rounding errors. I had to literally run over a million random tests until I discovered this.

一束光,穿透我孤独的魂 2024-07-30 11:30:06

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

总而言之,这很可能是完全无关的。

This is so micro that you should probably benchmark it for specific platforms, I don't think the results for a Pentium Pro will be necessarily the same as for an ARM or Pentium II.

All in all, it's most likely to be totally irrelevant.

堇年纸鸢 2024-07-30 11:30:06

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

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

I checked, and Math.Pow() is defined to take two doubles. This means that it can't do repeated multiplications, but has to use a more general approach. If there were a Math.Pow(double, int), it could probably be more efficient.

That being said, the performance difference is almost certainly absolutely trivial, and so you should use whichever is clearer. Micro-optimizations like this are almost always pointless, can be introduced at virtually any time, and should be left for the end of the development process. At that point, you can check if the software is too slow, where the hot spots are, and spend your micro-optimization effort where it will actually make a difference.

極樂鬼 2024-07-30 11:30:06

让我们使用约定 x^n。 假设 n 始终是整数。

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

对于较大的 n 值,Math.Pow 可能会更快,但如果您的库不是很智能,它将使用相同的算法,如果您知道 n 始终是整数,则这并不理想。 为此,您可以编写平方取幂或其他一些奇特算法的实现。

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

Let's use the convention x^n. Let's assume n is always an integer.

For small values of n, boring multiplication will be faster, because Math.Pow (likely, implementation dependent) uses fancy algorithms to allow for n to be non-integral and/or negative.

For large values of n, Math.Pow will likely be faster, but if your library isn't very smart it will use the same algorithm, which is not ideal if you know that n is always an integer. For that you could code up an implementation of exponentiation by squaring or some other fancy algorithm.

Of course modern computers are very fast and you should probably stick to the simplest, easiest to read, least likely to be buggy method until you benchmark your program and are sure that you will get a significant speedup by using a different algorithm.

笑叹一世浮沉 2024-07-30 11:30:06

Math.Pow(x, y) 通常在内部计算为 Math.Exp(Math.Log(x) * y)。 每个幂方程都需要求自然对数、乘法,并将 e 求幂。

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

Math.Pow(x, y) is typically calculated internally as Math.Exp(Math.Log(x) * y). Evey power equation requires finding a natural log, a multiplication, and raising e to a power.

As I mentioned in my previous answer, only at a power of 10 does Math.Pow() become faster, but accuracy will be compromised if using a series of multiplications.

書生途 2024-07-30 11:30:06

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

I disagree that handbuilt functions are always faster. The cosine functions are way faster and more accurate than anything i could write. As for pow(). I did a quick test to see how slow Math.pow() was in javascript, because Mehrdad cautioned against guesswork

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

here are the results:

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

if you don't agree try the program at http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文