web-dev-qa-db-ja.com

Math.Pow vs乗算演算子(パフォーマンス)

乗算演算子がMath.Powメソッドを使用するよりも速いかどうかは誰でも知っていますか?お気に入り:

n * n * n

Math.Pow ( n, 3 )
34
Joan Venge

基本的に、あなたはbenchmarkを見るべきです。

経験に基づく推測(信頼できない):

コンパイラによって同じものに最適化されていない場合...

x * x * xは一般的な場合の問題、小数のべき乗やその他の問題を処理する必要があるため、Math.Powは乗算命令を2つ取るだけなので、x * x * xMath.Pow(x, 3)よりも高速である可能性が高く、より速くなるために。

32
Mehrdad Afshari

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、OSはVista SP1、電源プランは高パフォーマンスです。

42
ggf31416

画像処理と科学計算における10年以上の最適化の経験則:

アルゴリズムレベルでの最適化は、低レベルでのあらゆる最適化に勝るものです。 「明白なものを書き、それから最適化する」従来の知恵にもかかわらず、これは最初に行わなければなりません。後ではない。

手動でコード化された数学演算(特にSIMD SSE +タイプ)は、通常、完全にエラーチェックされた、組み込みの演算よりも性能が優れています。

コンパイラーが実行する必要があることをコンパイラーが事前に知っている操作は、コンパイラーによって最適化されます。これらには以下が含まれます。1. Array.Copy()などのメモリ操作2.配列の長さが指定されている配列に対するforループ。 (..; i<array.Length;..

常に非現実的な目標を設定します(必要な場合)。

8
Doug

私はたまたまこれを昨日テストしたので、今あなたの質問を見ました。

私のマシンでは、1つのテストスレッドを実行するCore 2 Duoで、9倍までの乗算を使用する方が高速です。10では、Math.Pow(b、e)が高速です。

ただし、係数が2であっても、結果はしばしば同じではありません。丸め誤差があります。

一部のアルゴリズムは、丸め誤差に非常に敏感です。文字通り100万回以上のランダムテストを実行する必要がありました。

7
IamIC

これは非常に微小なので、特定のプラットフォームでベンチマークする必要があります。PentiumProの結果がARMまたはPentium IIの場合)と必ずしも同じになるとは思いません。

全体として、それは全く無関係である可能性が最も高いです。

4
Henk Holterman

私がチェックしたところ、Math.Pow()は2つのdoubleを取るように定義されています。つまり、乗算を繰り返すことはできませんが、より一般的な方法を使用する必要があります。 Math.Pow(double, int)があった場合、おそらくより効率的です。

そうは言っても、パフォーマンスの違いはほぼ確実に取るに足らないものなので、どちらか明確な方を使用する必要があります。このようなマイクロ最適化はほとんどの場合無意味であり、事実上いつでも導入することができ、開発プロセスの最後に残す必要があります。その時点で、ソフトウェアが遅すぎるかどうか、ホットスポットがどこにあるかを確認し、マイクロ最適化に費やして、実際に違いを生むことができます。

4
David Thornley

規則x ^ nを使用してみましょう。 nは常に整数であると仮定しましょう。

Nの値が小さい場合、Math.Pow(実装に依存する可能性が高い)はファンシーアルゴリズムを使用してnを非整数または負にできるため、退屈な乗算がより速くなります。

Nの値が大きい場合、Math.Powの方が高速になる可能性がありますが、ライブラリがあまりスマートでない場合は、同じアルゴリズムを使用します。これは、nが常に整数であることがわかっている場合は理想的ではありません。そのためには、 二乗による累乗 の実装または他の洗練されたアルゴリズムをコード化できます。

もちろん、最近のコンピューターは非常に高速であり、プログラムをベンチマークして、別のアルゴリズムを使用することで大幅なスピードアップが得られると確信できるまで、おそらく最もシンプルで読みやすい、バグの多い方法に固執する必要があります。

2
David

Math.Pow(x, y)は通常、Math.Exp(Math.Log(x) * y)として内部的に計算されます。 Eveyのべき乗方程式では、自然対数、乗算、およびeをべき乗する必要があります。

以前の回答で述べたように、10の累乗でのみMath.Pow()が速くなりますが、一連の乗算を使用すると精度が低下します。

0
IamIC

手作りの関数の方が常に速いとは思いません。コサイン関数は、私が書くことができるものよりもはるかに高速で正確です。 pow()と同様。 Mehrdadが推測に警告したため、私は簡単なテストを行って、Math.pow()がJavaScriptでどれほど遅いかを確認しました

    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 で試してください。

0
dooder duderama