1. ホーム
  2. python

[解決済み】リスト変換や関数型は「forループ」よりも速い?

2022-04-23 11:23:44

質問

Pythonのパフォーマンスという点では、リストコンプリヘンション、または、以下のような関数は有効でしょうか? map() , filter()reduce() forループより速い?なぜかというと、技術的には、それらは Cのスピードで走る , while forループはPython仮想マシンの速度で実行されます。 ?.

私が開発しているゲームで、複雑で巨大なマップをforループで描画する必要があるとします。この質問は間違いなく関連性があります。例えば、リスト内包が本当に高速であれば、(コードの視覚的複雑さにもかかわらず)遅延を避けるためにはるかに良い選択肢となるでしょう。

どのように解決するのか?

以下は、経験則に基づく大まかなガイドラインと推測です。あなたは timeit また、具体的なユースケースをプロファイリングすることで、正確な数値を得ることができます。

リスト内包は、通常、正確に等価である for ループ(実際にリストを作成するループ)は、リストとその中の append メソッドを繰り返し実行します。しかし、リスト内包はバイトコードレベルのループを行うことに変わりはありません。

>>> dis.dis(<the code object for `[x for x in range(10)]`>)
 1           0 BUILD_LIST               0
             3 LOAD_FAST                0 (.0)
       >>    6 FOR_ITER                12 (to 21)
             9 STORE_FAST               1 (x)
            12 LOAD_FAST                1 (x)
            15 LIST_APPEND              2
            18 JUMP_ABSOLUTE            6
       >>   21 RETURN_VALUE

というループの代わりにリスト内包を使用する。 はありません。 を構築し、無意味に値のリストを蓄積し、そのリストを捨てることはよくあることです。 遅くなる なぜなら、リストを作成し、拡張するためのオーバーヘッドがあるからです。リスト内包は、古き良きループより本質的に高速な魔法ではないのです。

関数型リスト処理関数については。これらはC言語で書かれており、おそらくPythonで書かれた同等の関数を凌駕していますが ではなく 必ずしも最速のオプションではありません。ある程度のスピードアップが期待できる もし この関数もCで書かれています。しかし、ほとんどの場合 lambda (または他のPython関数)の場合、Pythonのスタックフレームを繰り返し設定するオーバーヘッドが、節約分を食いつぶしてしまうのです。同じ作業を関数呼び出しなしにインラインで行うだけで、(例えば、リスト内包を map または filter )の方が若干速いことが多い。

例えば、私が開発しているゲームで、複雑で巨大なマップをforループで描画する必要があるとします。この質問は間違いなく関連性があります。例えば、リストコンパージョンが本当に高速であれば、(コードの視覚的な複雑さにもかかわらず)遅延を避けるために、より良い選択肢となるでしょう。

このようなコードは、非"最適化" Pythonで書かれたときにすでに十分に速くない場合、Pythonレベルのマイクロ最適化をいくら行っても十分に速くならないので、Cに落とすことを考え始める必要があります。さらに、その限界に達する前であっても、その弾丸を食い止め、いくつかのCを書く方が単純にコスト効率が良くなります(同じ努力で15%のスピードアップと300%のスピードアップ)。