15

exp()より一般的な よりも速いかどうか疑問に思っていpow()ました。JsPerf http://jsperf.com/pow-vs-expで高速ベンチマークを実行したところ、興味深い結果が得られました。

Math.exp(logBase * exponent);  // fastest
Math.exp(Math.log(base) * exponent);  // middle
Math.pow(base, exponent);  // slowest

アーキテクチャや言語によって結果が大きく異なることは承知していますが、理論的な観点にも興味があります。pow(a, b)として実装されているか、exp(log(a) * b)または電力を「直接」(C++、C#、またはJavaScriptで)計算するより賢い方法があります。一部のアーキテクチャで exp、log、または pow の CPU 命令はありますか?

私の知る限り、exp()log()はテイラー級数を使用して計算され、計算にかなりのコストがかかります。これは、一定の権力基盤のために、このコードが

double logBase = log(123.456);
for (int i = 0; i < 1024; ++i) {
    exp(logBase * 654.321);
}

これよりも優れています

for (int i = 0; i < 1024; ++i) {
    pow(123.456, 654.321);
}

それは正しい仮定ですか?

4

3 に答える 3

17

はい、一般expよりも高速になります。pow

および関数はexplogターゲット プラットフォーム用に最適化されます。パデ近似、線形またはバイナリ削減とそれに続く近似など、多くの手法を使用できます。

pow関数は通常、あなたが言うように実装されるため、単独exp(log(a) * b)よりも明らかに遅くなります。exp負の指数、整数指数、1/2 または 1/3 に等しい指数など、多くの特殊なケースがあります。これらのテストはコストがかかるため、一般的なケースではさらにpow遅くなります。pow

でこの SO の質問をpow参照してください。

于 2013-07-26T23:06:24.260 に答える
4

アーキテクチャの詳細に関係なく、Math.powエラー チェックに関してさらに多くのことを行う必要があります (たとえば、基数が負の場合はどうなるでしょうか?)。よりも(したがって、遅くなると思います)Math.exppow

仕様の関連部分:

http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.8

15.8.2.8 指数 (x)

x の指数関数 (e を x 乗、e は自然対数の底) の実装依存の近似値を返します。

x が NaN の場合、結果は NaN になります。x が +0 の場合、結果は 1 です。x が -0 の場合、結果は 1 です。x が +∞ の場合、結果は +∞ です。x が −∞ の場合、結果は +0 です。

http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.13

15.8.2.13 pow (x, y)

x を y 乗した結果に対する実装依存の近似値を返します。

y が NaN の場合、結果は NaN になります。y が +0 の場合、x が NaN であっても結果は 1 になります。y が −0 の場合、x が NaN であっても、結果は 1 になります。x が NaN で y が非ゼロの場合、結果は NaN になります。abs(x)>1 で y が +∞ の場合、結果は +∞ になります。abs(x)>1 で y が −∞ の場合、結果は +0 です。abs(x)==1 で y が +∞ の場合、結果は NaN になります。abs(x)==1 で y が −∞ の場合、結果は NaN になります。abs(x)<1 で y が +∞ の場合、結果は +0 です。abs(x)<1 で y が −∞ の場合、結果は +∞ になります。x が +∞ で y>0 の場合、結果は +∞ になります。x が +∞ で y<0 の場合、結果は +0 です。x が −∞ で y>0 で、y が奇数の整数の場合、結果は −∞ になります。x が −∞ で y>0 で、y が奇数でない場合、結果は +∞ になります。x が −∞ かつ y<0 で、y が奇数の整数の場合、結果は −0 です。x が −∞ かつ y<0 で、y が奇数でない場合、結果は +0 です。x が +0 で y>0 の場合、結果は +0 です。x が +0 で y<0 の場合、結果は +∞ になります。x が -0 かつ y>0 で、y が奇数の整数の場合、結果は -0 です。x が −0 で y>0 で、y が奇数でない場合、結果は +0 になります。x が −0 かつ y<0 で、y が奇数の整数の場合、結果は −∞ になります。x が −0 かつ y<0 で、y が奇数でない場合、結果は +∞ になります。x<0 で x が有限で y が有限で y が整数でない場合、結果は NaN になります。

于 2013-07-26T23:29:01.363 に答える
1

部分的な回答として、一部のアーキテクチャでは exp、log、または pow の指示があります。ただし、それは必ずしも多くのことを意味するわけではありません。

たとえば、x86 には

  • f2xm12 x - 1を計算します
  • fscaley * 2 (int)xを計算します
  • fyl2xy * log 2 xを計算します
  • fyl2xp1y * log 2 (x + 1) を計算します (入力範囲に制限があります)

しかし、それらはあまり使用されていません。アーキテクチャによって異なりますが、決して高速ではありません。より極端な例として、fyl2xSandy Bridge で 724 のレイテンシがあり (かなり最近です!)、同じプロセッサで約 700 の独立した浮動小数点の追加、または約 240 の従属浮動小数点の追加、または約 2000 の独立した単純な浮動小数点を実行できます。整数演算。

それはそれと同じくらい悪いことですが、通常は遅いです。手動の実装がそれらを打ち負かすか、少なくとも大幅に失われないほど十分に遅い.

また、FPU コードは、SSE コードを支持して徐々に姿を消しつつあります。これらの命令に相当する SSE はありません。

于 2013-07-26T22:45:58.670 に答える