Math.Pow と乗算演算子 (パフォーマンス)
-
06-09-2019 - |
質問
乗算演算子が Math.Pow メソッドを使用するよりも速いかどうかを知っている人はいますか?のように:
n * n * n
対
Math.Pow ( n, 3 )
解決
基本的に、あなたはをベンチマークを見てのはずます。
教養の当て推量(信頼できない):
...それはいくつかのコンパイラで同じことに最適化されていない場合には
これは、それがより速くなる可能性が非常に高いですのでx * x * x
だけで、カップル乗算命令を取るだろうが、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 テスト.cs
テスト.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、電源プランはハイパフォーマンスです。
画像処理&科学技術計算における最適化の10年以上から親指のいくつかのルールます:
アルゴリズムレベルでの最適化は、低レベルでの最適化の任意の量を打ちます。 「明白なことを書く、そして最適化する」社会通念にもかかわらず、これは開始時に行われなければなりません。ではないの後。
ハンドコーディングされた数学演算(特にSIMD SSE +タイプ)は、一般的に作り付けのものを一般化し、完全にエラーにチェックをアウトパフォームします。
コンパイラは何をすべきか、事前に知っている任意の操作は、コンパイラによって最適化されています。これらは、次のとおりです。
そのようなArray.Copy()のような1メモリ動作
配列の長さが指定された配列をループ2.。以下のためのように(..; i<array.Length;..
)
(あなたがしたい場合は)常に非現実的な目標を設定します。
私はちょうどそれから、今、あなたの質問を見て、この昨日をテストしているために起こっています。
私のマシンでは、1つのテストスレッドを実行しているCore 2 Duoプロセッサは、それは10で9倍までの乗算を使用する方が速い、Math.Pow(B、E)が速くなります。
しかし、2倍で、結果は、多くの場合、同一ではありません。丸め誤差があります。
いくつかのアルゴリズムは、丸め誤差に非常に敏感です。私は私がこれを発見するまで、文字通り万人以上のランダムなテストを実行する必要がありました。
私がチェックし、Math.Pow()
は2倍を取るように定義されています。これは、繰り返し乗算を行うことができないことを意味しますが、より一般的なアプローチを使用する必要があります。 Math.Pow(double, int)
があった場合、それはおそらく、より効率的な可能性があります。
言われていることは、パフォーマンスの違いは、ほぼ確実に絶対に簡単です、そしてあなたが明確方使用する必要があります。このようなマイクロ最適化は、事実上任意の時点で導入することができ、ほとんど常に無意味であり、開発プロセスの終了を残しておく必要があります。その時点で、あなたはホットスポットがどこにあるソフトウェアは、遅すぎるかどうかを確認し、それが実際に違いを生むだろう、あなたのマイクロ最適化の努力を過ごすことができます。
これは、おそらく、特定のプラットフォーム用のベンチマークそれは、私がペンティアムプロの結果は、ARMまたはPentium II用として必ずしも同じになるとは思わないはずですマイクロはそうです。
すべてのすべてで、それは完全に無関係である可能性が最も高いのです。
のは、大会のx ^ n個を使用してみましょう。 nは常に整数であると仮定しましょう。
Math.Powが(おそらく、実装に依存する)は、nが非整数及び/又は負であることを可能にするために、空想のアルゴリズムを使用しているため、は、nの値が小さいため、乗算を退屈する、速くなります。
は、nの値が大きいため、Math.Powはそう速くなりますが、あなたのライブラリーは非常にスマートではない場合、それはあなたが、nは常に整数であることを知っていれば理想的ではありません同じアルゴリズムを使用します。そのために、あなたはのか、他のいくつかの空想のアルゴリズムを二乗することにより、累乗の実装をコーディングすることができます。
もちろん、現代のコンピュータは非常に高速であり、あなたはおそらく、あなたのベンチマークプログラムまで、バギー方法である可能性が最も低い読んで、あなたは別のアルゴリズムを使用することにより、大幅なスピードアップを得ると確信していますし、最も簡単な、最も簡単に固執する必要があります。
私はhandbuilt機能は常に高速であることを同意しません。コサイン関数は、私が書くことができる何よりも方法より速く、より正確です。 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 / JavaScriptの/ speedtests / powSpeedTest.htmlする
Math.Pow(x, y)
は通常Math.Exp(Math.Log(x) * y)
として内部的に計算されます。 Evey電源式は自然対数、乗算を見つけ、そして電源にe
を上げる必要があります。
私は私の前の回答で述べたように、わずか10の電力でMath.Pow()
が速くなるんが、一連の乗算を使用している場合は精度が損なわれます。