[解決済み] Python 3でx**4.0がx**4より速いのはなぜですか?
質問
なぜ
x**4.0
よりも高速に
x**4
? CPython 3.5.2を使っています。
$ python -m timeit "for x in range(100):" " x**4.0"
10000 loops, best of 3: 24.2 usec per loop
$ python -m timeit "for x in range(100):" " x**4"
10000 loops, best of 3: 30.6 usec per loop
上げるパワーを変えて挙動を見てみましたが、例えばxを10の累乗や16の累乗で上げると30から35に飛びますが、もし 10.0 をfloatにすると、24.1~4あたりを移動しているだけです。
浮動小数点数の変換と2の累乗が関係してるんだろうけど、よくわかんないんだよね。
どちらの場合も2の累乗の方が速いことに気づきました。これらの計算はインタープリタやコンピュータにとってよりネイティブで簡単だからでしょう。それにしても、floatだとほとんど動きませんね。
2.0 => 24.1~4 & 128.0 => 24.1~4
しかし
2 => 29 & 128 => 62
タイガーホークT3 は、ループの外では起きないとのご指摘をいただきました。調べてみたところ、この状況は(私が見た限りでは)ループの外側で ベース が上がってきています。それについて何か心当たりはありますか?
解決方法を教えてください。
<ブロッククオート
なぜ
x**4.0
より速く
より
x**4
Python 3 では
*
?
パイソン3
int
オブジェクトは、任意のサイズに対応するように設計された本格的なオブジェクトです。
Cレベルではそのように扱われます。
(として宣言されます(すべての変数が
PyLongObject *
タイプで
long_pow
). また、これによって、その指数関数がより多くの
トリッキー
と
面倒くさい
を弄る必要があるため
ob_digit
という配列で、その値を表現しています。(
ブレイブのソース
-- 参照してください。
Pythonで大きな整数のためのメモリ割り当てを理解する
の詳細については
PyLongObject
s.)
パイソン
float
オブジェクトは、逆に
は変換することができます
をC
double
型を使用します。
PyFloat_AsDouble
)、演算を行うことができます。
これらのネイティブな型を使って
.
これはすごい
なぜなら、関連するエッジケースをチェックした後、Pythonが
プラットフォームの
pow
(
Cの
pow
ということです。
) を使って、実際の指数計算を処理します。
/* Now iv and iw are finite, iw is nonzero, and iv is
* positive and not equal to 1.0. We finally allow
* the platform pow to step in and do the rest.
*/
errno = 0;
PyFPE_START_PROTECT("pow", return NULL)
ix = pow(iv, iw);
ここで
iv
と
iw
は、私たちのオリジナルの
PyFloatObject
をCとして
double
s.
何はともあれ Python
2.7.13
私にとっての要因2~3
が速くなり、逆の挙動を示しています。
前事実 も説明しています。 Python 2 と 3 の間の不一致は、興味深いので、このコメントも取り上げようと思いました。
Python 2では、旧来の
int
オブジェクトとは異なります。
int
オブジェクトは、Python 3では(すべて
int
オブジェクトは、3.xでは
PyLongObject
型)。Python 2 では、オブジェクトの値に依存する区別があります(あるいは、接尾辞である
L/l
):
# Python 2
type(30) # <type 'int'>
type(30L) # <type 'long'>
は
<type 'int'>
ご覧の通り
は同じことをする
float
する
に変換され、安全にC
long
指数関数が実行されたとき
(その
int_pow
は、コンパイラがそれらをレジスタに格納できる場合は格納するようヒントも与えます。
かもしれない
を作成します)。
static PyObject *
int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
{
register long iv, iw, iz=0, ix, temp, prev;
/* Snipped for brevity */
これにより、良好な速度向上が可能になります。
の遅さを確認するために
<type 'long'>
との比較では
<type 'int'>
をラップした場合、その
x
の名前を
long
の呼び出しは、Python 2で(実質的に強制的に
long_pow
Python 3 と同様に)、速度向上がなくなります。
# <type 'int'>
(python2) ➜ python -m timeit "for x in range(1000):" " x**2"
10000 loops, best of 3: 116 usec per loop
# <type 'long'>
(python2) ➜ python -m timeit "for x in range(1000):" " long(x)**2"
100 loops, best of 3: 2.12 msec per loop
1つのスニペットで
int
から
long
このキャストは、(@pydsinger が指摘したように) 遅くなる要因ではありません。の実装は
long_pow
です。(ステートメントを単独で
long(x)
を見てください)。
[...] ループの外では起こりません。[...] 何か心当たりはありますか?
これはCPythonのpeepholeオプティマイザが定数を折り曲げてくれているのです。指数計算の結果を見つけるための実際の計算はなく、値の読み込みだけなので、どちらの場合でも同じ正確なタイミングになります。
dis.dis(compile('4 ** 4', '', 'exec'))
1 0 LOAD_CONST 2 (256)
3 POP_TOP
4 LOAD_CONST 1 (None)
7 RETURN_VALUE
には同じバイトコードが生成されます。
'4 ** 4.'
唯一の違いは
LOAD_CONST
をロードし、フロート
256.0
の代わりに、int 型の
256
:
dis.dis(compile('4 ** 4.', '', 'exec'))
1 0 LOAD_CONST 3 (256.0)
2 POP_TOP
4 LOAD_CONST 2 (None)
6 RETURN_VALUE
つまり、時間は同じなんですね。
*上記はすべて、Pythonのリファレンス実装であるCPythonにのみ適用されます。他の実装では異なる動作をするかもしれません。
関連
-
Python百行で韓服サークルの画像クロールを実現する
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
Python カメの描画コマンドとその例
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
パッケージングツールPyinstallerの使用と落とし穴の回避
-
PythonでECDSAを実装する方法 知っていますか?
-
[解決済み】TypeError: unhashable type: 'numpy.ndarray'.
-
[解決済み】pygame.error: ビデオシステムが初期化されていない
-
[解決済み】ImportError: PILという名前のモジュールがない
-
[解決済み】インポートエラー。モジュール名 urllib2 がない
-
[解決済み】LogisticRegression: Pythonでsklearnを使用して、未知のラベルタイプ: '連続'を使用しています。