2 ** xはexp(x)よりも計算が速いですか?


12

私がこの質問をする方法で明らかになるであろう素朴さ、そして私がそれを求めているという事実を許してください。

数学者は、通常、expを使用します(理論により)理論上最も単純な/最も基本的なものです。しかし、コンピューターはすべてをバイナリで実行するように見えるので、コンピューター上で計算する2**xよりも高速Math::exp(x)ですか?


7
どんな種類の数字を言っていますか?任意のサイズの整数?固定サイズの浮動小数点?任意精度の浮動小数点?
ジル 'SO-悪であるのをやめる' 14年

@Gillesそれは良い点です。違いが重要であることに気づきませんでした。
同型14年

3
私は、非電子数のログとパワーが非常に遅いことを、いくつかのカシオの電卓に見てきたよりもLN / EXP
phuclv

2
鈍ることを防ぐために、両方のタイミングを計り、どちらが速いかを試してみましたか?または、複雑さの意味で速度について話していますか?Ofn
jmite 14年

1
言語は最速の方法を選択する責任があり、それで良い仕事をします。のみの場合には最大限の速度が必要とされ、測定値は、これがパフォーマンスに関連しているあなたが原料のこの種のを心配する必要があることを示している
vonbrand

回答:


18

これはStackoverflowではなくCSであるため、数値解析、および(物事を簡単にするために)IEEE-754浮動小数点について質問していると想定します。その場合、あなたの質問への答えは、「より簡単」という意味と、システムの詳細に一部依存します。

私が知っている最新のCPUには、操作(以降、Cの通常の名前と呼ぶ)または2 x()のどちらかで、期待どおりの動作を行う命令が組み込まれていません。どちらもライブラリ関数を使用して実装されます。eバツexp2xexp2

超越演算のすべての数値メソッドの場合と同様に、考慮すべき特別なケースがいくつかあります。

exp(NaN) = NaN
exp(+Inf) = +Inf
exp(-Inf) = 0

ただし、問題をもう少し複雑にする別のことがあります:有用なドメインは非常に小さいです。binary32のexp(x)場合、程度であればアンダーフローし、x > 88.7程度であればオーバーフローします。以来、珍しく超越操作のために、我々はまた、非正規のケースを無視することができると区別がつかない場合は正常以下です。ドメインがわずかに異なることを除いて、上記のすべてもに当てはまります。バツ<104バツ>88.7exp(x)1.0xexp2

ほとんどの実装が計算するという点で、あなたの直感は正しいです。ただし、その乗算のコストは1eバツ=2バツ/ln2は、他のコンピューティングと比べると些細なことです。典型的な方法は、K個の要素を持つ事前計算されたテーブルを使用します。1ln2exp2K

exp2バツ=2n×T[j]×Py

ここで、xの整数部であり、テーブルTは、範囲[ 0 K )のすべてのjに対して2 j / Kの値を含み、Pは、範囲内の2 x(binary32には4次で十分)の多項式近似です[ 0 1nバツT2j/Kj[0KP2バツ2nはそれだけで指数を操作していますので、一部には、安いです。Tはルックアップテーブルです。したがって、Pは操作のコストの高い部分になる可能性があります。[01K2nTP

私は、Intelのx86のFPUことを完全にするために指摘すべきであると呼ばれる命令含むf2xm1計算し、ためのxの範囲で、[ - 1 1 ]。ただし、最新のCPUでは、これはかなり高価でパイプライン化されていない命令であり、使用することは非常に推奨されません。インテル最適化リファレンスマニュアルのセクション3.8.5当然の注意事項:2バツ1バツ[11]

x87は超越命令をサポートしていますが、多くの場合、超越関数のソフトウェアライブラリ実装はより高速です。

編集: IEEE 754-2008で使用されている新しい用語のいくつかを説明する必要があるというコメントで指摘されています。言語の一部は1985年と1987年以降に変更されており、ほとんどの人は古い専門用語にはるかに精通しています。

「binary32」および「binary64」という用語は、32ビットおよび64ビットの2進浮動小数点数の新しい名前であり、古い標準ではそれぞれ「single」および「double」と呼ばれていました。

用語「非正規数」は、前の用語「非正規数」または「非正規化数」を置き換えます。


「非正規」と言うときは、明らかに「準ガウス」を意味しません。「(典型的なベンチマーク)より悪い」という意味ですか?
同型14年

2
@isomorphismesここで、「非正規」はフロートの実装方法に関するものです。ウィキペディアで非正規数を参照してください。
ポールマンタ14年

ちなみに、「典型的な方法」を少し単純化しすぎました。ここに示されているメソッドの1つの小さな(そして非常に理解しやすい)拡張を使用して、ulp精度でexp2()およびexp()を実装することは可能ですが、小さな理解しやすい拡張の説明はおそらく2倍の長さになります答え!
仮名

6

もし2 x2**xを意味するなら、はい。左シフト演算子を使用できます。つまり、を計算できます。これは私が知っているすべてのプロセッサでの原始的な機械命令であるため、非常に高速です。これは、2以外の基数では実行できません。さらに、浮動小数点数の乗算に時間がかかるため、整数のべき乗は常に実際のべき乗よりも高速になります。2バツ<<1 << x


4
実際はそうではなくて。x多分浮動小数点型
phuclv 14年

1
バツ

xが整数でない場合(たとえば、20.75)、仮数部2と指数部を丸めた値にx最も正確な推定値として設定します(正確な表現は不可能です)。これも、「パウ」よりもはるかに高速です。
デイモン14年

1

場合は2**x、整数の機能があり、その後、私はスティーブンの答えで、シフトが安価であることに同意します。しかし、私は通常、浮動小数点のべき乗を示している2^xと見てい**ます。この場合、私は同様のパフォーマンスを期待します** andと(の基になる演算)は両方とも超越近似演算である^ため、expとのでます。pow**


興味深いことに、私は**浮動小数点バージョンの同義語と見なされることを知りませんでした(そして、愚かなことに、2つが異なることを忘れていました)。
同型14年

1

2 ^ x = e ^(x * ln 2)およびe ^ x = 2 ^(x * log2(e))なので、大きな違いは期待できないでしょう。

xがゼロに近い場合は、通常、多項式e ^ x = 1 + x + x ^ 2/2 + x ^ 3/6 ...を使用します。 。明らかに、2 ^ xは非常に小さく、計算が少し遅くなります。「0に近いx」は通常、sqrt(1/2)<= e ^ x <= sqrt(2)のxの値になります。xの範囲を制限することにより、多項式の次数をあまり高く選択する必要がなくなります。

より大きなxの場合、通常はx = x '+ x' 'として2 ^ xを計算します。ここで、x'は整数で、-0.5 <= x '' <= 0.5です。2 ^ x 'は、正しいビットパターンで浮動小数点数を構成することによって計算され、2 ^ x' 'は小さなxに対してe ^ xメソッドを使用して計算されます。ここで、2 ^ xはほんの少し高速です。さらに、xが大きければ(たとえば、x = 100.3)、xにlog2(e)を掛けると、許容できない丸め誤差が発生し(小数ビットが少ないため)、さらに注意する必要があります。

そして、うまくいけば、優れたライブラリ関数が、丸め誤差が何であろうと、x <= y、e ^ x <= e ^ yおよび2 ^ x <= 2 ^ yであることに注意してください。そのようなことを達成するのは難しい場合があります。


0

コンピューターでの計算は、ソフトウェアごとに異なる方法で行われ、一貫した答えが得られることを理解する必要があります。ほとんどのソフトウェアを見ると、コンピューターはうまく振る舞うと思います。コンピューターは、0 ^ 0のような場合でも、長い道のりで答えを計算します。問題は、特殊なケースには「認識」が関係することであり、これはデジタルコンピューターでは無料では発生しません。これは、答えが「最も」速くなる場合にのみ最適化が発生することを意味します。しかし、それらの場合、それは非常によく起こります。また、正しい答えを得るには、いくつかの異なる認識が必要になる場合があることに注意してください。これは速度最適化レベルと呼ばれ、GNU「C」と呼ばれるほとんどのソフトウェアに基づいて、最大の専門的範囲で発生しました。これは、ここではソフトウェアからソフトウェアへの実行時間のわずかな違いと、マシンからマシンへの品質の差が品質の許容値として使用されるためです。他のインタープリターでは、通常、以前の計算の副作用として「ゼロフラグ」が発生した場合にのみ、認識の実行が高速化されます。0 * x => C0など。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.