43

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

n * n * n

Math.Pow ( n, 3 )
4

9 に答える 9

46

Windowsを再インストールしただけなので、ビジュアルスタジオがインストールされておらず、コードが醜い

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-effective-way-to-implement-an-integer-based-power-function-powint-intを参照) は、Math.Pow よりもはるかに高速です。私のテストでは (私の CPU は 2 Ghz の Pentium T3200 です)

編集: .NET バージョンは 3.5 SP1、OS は Vista SP1、電源プランは高パフォーマンスです。

于 2009-06-01T21:33:54.510 に答える
36

基本的には、ベンチマークして確認する必要があります。

教育を受けた当て推量 (信頼できない):

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

一般的なケースで問題を処理する必要がある場合よりも高速である可能性が非常に高く、分数のべき乗やその他の問題を処理しますがx * x * x、乗算命令を数回実行するだけなので、高速になる可能性が非常に高くなります。Math.Pow(x, 3)Math.Powx * x * x

于 2009-06-01T20:16:41.623 に答える
11

画像処理と科学計算における 10 年以上の最適化から得られたいくつかの経験則:

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

ハンド コーディングされた数学演算 (特に SIMD SSE+ 型) は、通常、完全にエラー チェックされ、一般化された組み込み演算よりも優れています。

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

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

于 2011-06-08T03:07:08.040 に答える
8

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

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

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

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

于 2012-05-20T12:10:47.950 に答える
5

これは非常に小さいので、おそらく特定のプラットフォームでベンチマークする必要があります。Pentium Pro の結果が ARM や Pentium II の結果と必ずしも同じになるとは思いません。

全体として、まったく無関係である可能性が最も高いです。

于 2009-06-01T20:22:29.943 に答える
4

チェックしたところ、 Math.Pow()2 つの double を取るように定義されています。これは、繰り返し乗算を行うことはできませんが、より一般的なアプローチを使用する必要があることを意味します。があればMath.Pow(double, int)、おそらくより効率的になる可能性があります。

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

于 2009-06-01T20:29:30.617 に答える
2

慣例 x^n を使用しましょう。n が常に整数であると仮定しましょう。

n の値が小さい場合、Math.Pow (実装に依存する可能性が高い) は派手なアルゴリズムを使用して n が非整数および/または負になることを許可するため、退屈な乗算が高速になります。

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

もちろん、最新のコンピューターは非常に高速であり、プログラムのベンチマークを行い、別のアルゴリズムを使用することで大幅な高速化が得られることを確認するまでは、おそらく最も単純で読みやすく、バグの可能性が最も低い方法に固執する必要があります。

于 2009-06-01T20:39:22.797 に答える
0

手作りの関数が常に高速であることに同意しません。コサイン関数は、私が書いたものよりもはるかに高速で正確です。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でプログラムを試してください。

于 2011-11-20T18:31:37.077 に答える