web-dev-qa-db-ja.com

スピードアップPython

これは実際には2つの質問ですが、それらは非常に似ているので、簡単にするために、それらをまとめるだけだと思いました。

  • 最初に:確立されたpythonプロジェクトを考えると、単なるコード内最適化を超えてそれをスピードアップするためのいくつかの適切な方法は何ですか?

  • Secondly:Pythonでプログラムを最初から作成する場合、パフォーマンスを大幅に向上させるための良い方法は何ですか?

最初の質問では、きちんと書かれたプロジェクトが渡され、パフォーマンスを改善する必要があると想像してください。しかし、リファクタリング/最適化によって多くの利益を得ることができないようです。この場合、Cのようなものに書き直す以外に、速度を上げるにはどうしますか?

42
akdom

「第二に:Pythonでプログラムを最初から作成する場合、パフォーマンスを大幅に向上させるための良い方法は何ですか?」

ジャクソンの最適化のルールを覚えておいてください。

  • ルール1:それをしないでください。
  • ルール2(専門家のみ):まだ実行しないでください。

そしてクヌースのルール:

  • 「時期尚早の最適化はすべての悪の根源です。」

より便利なルールは 最適化の一般ルール にあります。

  1. あなたが行くように最適化しないでください。まず、正しく理解してください。その後、それを速く取得します。間違ったプログラムを最適化することはまだ間違っています。

  2. 80/20の法則を覚えておいてください。

  3. 常に「前」と「後」のベンチマークを実行します。そうしないと、80%を見つけたかどうかわかりません。

  4. 適切なアルゴリズムとデータ構造を使用してください。このルールを最初にする必要があります。アルゴリズムとデータ構造ほど重要なことはありません。

ボトムライン

「このプログラムの最適化」の取り組みを防止または回避することはできません。それは仕事の一部です。設計、コード、およびテストアクティビティと同様に、計画を立てて慎重に行う必要があります。

43
S.Lott

単にCにパントするのではなく、次のことをお勧めします。

コードを重要視してください。行の実行を減らして、より多くのことを実行します。

  • アルゴリズムをより高速なものに変更します。多くの場合、高速にするために派手である必要はありません。
  • たまたまCで書かれたpythonプリミティブ
  • 最初にビッグデータ構造を構築し、次にその消費を行うコードに注意してください。 rangeとxrangeの違いを考えてください。一般に、プログラムのメモリ使用量について考える価値があることがよくあります。ジェネレータを使用すると、O(n)メモリ使用量がO(1)になることがあります。
  • Pythonは一般的に最適化されていません。不変のコードをループから引き上げ、タイトなループで可能な場合は共通部分式を排除します。
  • 何かが高価な場合は、事前に計算するか、メモしてください。たとえば、正規表現をコンパイルできます。
  • 数字をクランチする必要がありますか? numpyをチェックアウトすることをお勧めします。
  • 多くのpythonプログラムは、ディスクI/Oまたはデータベースアクセスに拘束されているため、低速です。データが到着するのを待つ間、ブロックするだけでなく、やりがいのあることを確認してください。武器Twistedフレームワークのようなものである可能性があります。
  • XML、JSONなど、多くの重要なデータ処理ライブラリにはCバージョンがあることに注意してください。多くの場合、Pythonインタープリターよりもかなり高速です。

プロファイルおよび測定されたコードで上記のすべてが失敗した場合は、Cリライトパスについて考え始めてください。

27

通常の容疑者-プロファイルを作成し、最も高価な行を見つけ、それが何をしているのかを理解し、修正します。これまであまりプロファイリングを行ったことがない場合は、大きな太い2次ループや文字列の重複が、他の点では無害に見える式の背後に隠れている可能性があります。

Pythonでは、明らかでない速度低下の最も一般的な原因の2つは、文字列の連結とジェネレーターです。 Pythonの文字列は不変なので、次のようにします。

result = u""
for item in my_list:
    result += unicode (item)

entire文字列を反復ごとに2回コピーします。これは十分にカバーされており、解決策は"".joinを使用することです。

result = "".join (unicode (item) for item in my_list)

ジェネレーターは別の原因です。これらは非常に使いやすく、一部のタスクを大幅に簡素化できますが、適切に適用されていないジェネレーターは、単にアイテムをリストに追加してリストを返すよりもはるかに遅くなります。

最後に、Cでビットを書き換えることを恐れないでください!動的な高級言語としてのPythonは、Cの速度に合わせることができません。 Pythonでこれ以上最適化できない関数が1つある場合は、それを拡張モジュールに抽出することを検討してください。

このための私のお気に入りのテクニックは、モジュールのPythonバージョンとCバージョンの両方を維持することです。Pythonバージョンは、可能な限り明確で明白になるように書かれています-バグは診断と修正が簡単である必要があります。このモジュールに対してテストを記述し、次にCバージョンを記述してテストします。その動作は、すべての場合でPython実装-それらが異なる場合、どちらが間違っているかを見つけて問題を修正するのは非常に簡単です。

24
John Millikin

最初に頭に浮かぶのは: psyco 。とりあえず、x86でのみ動作します。

次に、 定数バインディング 。つまり、すべてのグローバル参照(およびglobal.attrglobal.attr.attr…)を関数内のローカル名にします。とメソッド。これは常に成功するとは限りませんが、一般的には機能します。手作業で行うこともできますが、明らかに面倒です。

コード内の最適化とは別におっしゃっていたので、これについては詳しく説明しませんが、人々が犯す典型的な間違い(for i in range(10000000)が頭に浮かぶ)に心を開いておいてください。

17
tzot

Cythonとpyrexは、Pythonのような構文を使用してcコードを生成するために使用できます。 Psycoは、適切なプロジェクトにも最適です(速度の向上に気付かない場合もあれば、50倍の速度になる場合もあります)。私は今でも、コード(cProfileなど)のプロファイルを作成してから、ボトルネックをpythonのc関数としてコーディングするのが最善の方法だと考えています。

9
hacama

誰もShedSkinについて言及していないことに驚いています: http://code.google.com/p/shedskin/ 、それは自動的にあなたのpythonプログラムをC++に変換します一部のベンチマークでは、速度がpsycoよりも優れています。

さらに、シンプルさに関する逸話: http://pyinsci.blogspot.com/2006/12/trying-out-latest-release-of-shedskin.html

ただし、制限があります。以下を参照してください。 http://tinyurl.com/shedskin-limitations

7
torial

読んでいただければ幸いです: http://wiki.python.org/moin/PythonSpeed/PerformanceTips

すでにあるものを再開すると、通常3つの原則があります。

  • ローカルを使用する、不要なルックアップ/呼び出しを回避する、慣用的な構造を使用するなど、より適切なバイトコードに変換されるコードを記述します(必要なものに自然な構文がある場合は、それを使用します-通常は高速です。例:do n't do: "for key in some_dict.keys() "、" for key in some_dict ")
  • cで書かれたものはすべてかなり高速です。利用可能なC関数/モジュールを悪用してください
  • 疑わしい場合は、timeit、プロファイルをインポートしてください
5
ionelmc

これは必ずしもコードの速度を上げるわけではありませんが、コードの速度を落とさないようにする場合は、Pythonでプログラミングするときに重要な知識です。「グローバルインタープリターロック」(GIL)にはマルチスレッドプログラムの動作が理解されていない場合、その速度が大幅に低下する可能性があります(はい、これは私を苦しめました...一度に1.2プロセッサを超えて使用しないNice 4プロセッサマシンがありました)。 SmoothSpan で始めるためのいくつかのリンクを含む紹介記事。

4
Steve Moyer

Pythonプロファイラーを介してアプリを実行します。深刻なボトルネックを見つけます。そのボトルネックをCで書き直します。繰り返します。

4
Vicent Marti

人々はいくつかの良いアドバイスをしましたが、高性能が必要な場合、pythonモデルは:punt to cです。psycoのような取り組みは将来少し役立つかもしれませんが、 pythonは高速な言語ではなく、そのように設計されていません。動的な処理を非常にうまく実行し、それでも非常に高速なコードを生成できる言語はほとんどありません。少なくとも予見可能な将来(および一部の設計は高速コンパイルに対して機能します)が当てはまります。

したがって、本当にこのバインドに自分自身を見つけた場合、最善の策は、(良い)Pythonで許容できない遅い部分を分離し、Cでそれらのビットを書き換えるという考えに基づいて設計することです。申し訳ありません。優れたデザインは、これをそれほど苦痛にしないのに役立ちます。ただし、最初にpythonでプロトタイプを作成すると、cのサニティチェックも簡単に実行できます。

結局のところ、これはnumpyのようなものには十分に機能します。しかし、どれだけ優れたデザインが役立つかを強調することはできません。 pythonビットを繰り返し突いて、最も遅いビットをCに置き換えると、大きな混乱に終わる可能性があります。Cビットが必要な場所とその方法を正確に考えてください。最小化され、適切にカプセル化されます。

4
simon

Python)に手書きで書かれた明示的なアルゴリズムを置き換えることで、Cに近い速度(最初にPythonを使用するプロジェクトに十分近い!)組み込みのPython呼び出しを使用する暗黙のアルゴリズムを使用します。これは、ほとんどのPython組み込みがCで記述されているため、機能します。もちろん、CPythonでは;-) https://www.python.org/doc/essays/list2str/

3
sep332

これは私が従おうとしている手順です:

  • psycoをインポートします。 psyco.full()
  • 十分な速度がない場合は、プロファイラーを介してコードを実行し、ボトルネックがどこにあるかを確認します。 (このステップではpsycoを無効にします!)
  • 他の人が言及しているようなことをして、それらのボトルネックでコードをできるだけ早く取得するようにしてください。
    • [str(x)for x inl]や[x.strip()for x in l]のようなものは、map(str、x)やmap(str.strip、x)よりもはるかに低速です。
  • この後、さらに速度が必要な場合は、PyRexを起動して実行するのは実際には非常に簡単です。最初にpythonコードのセクションをコピーし、それを直接パイレックスコードに入れて、何が起こるかを確認します。次に、それがどんどん速くなるまでそれをいじります。
3
Claudiu

Psycoの使用に関する注意:場合によっては、実際に実行時間が遅くなる可能性があります。特にCで書かれたコードでpsycoを使おうとすると、これを読んだ記事を思い出せませんが、map()関数とreduce()関数が具体的に言及されました。幸い、指定された関数やモジュールを処理しないようにpsycoに指示できます。

3
Walter

Pythonコードを改善する方法の標準的なリファレンスはここにあります: PerformanceTips 。本当に必要な場合を除いて、Cでの最適化はお勧めしません。ほとんどのアプリケーションでは、そのリンクに掲載されているルールに従うことで、必要なパフォーマンスを得ることができます。

2
Jason Baker

Psycoを使用する場合は、psyco.profile()ではなくpsyco.full()をお勧めします。大規模なプロジェクトの場合、最適化された関数についてより賢くなり、使用するメモリが1トン少なくなります。

イテレーターとジェネレーターも検討することをお勧めします。アプリケーションが大きなデータセットを使用している場合、これによりコンテナのコピーが多数節約されます。

1
Peter Shinners

(素晴らしい) psyco と(素敵な) shedskin の他に、私は cython の素晴らしいフォーク pyrex を試すことをお勧めします。

または、急いでいない場合は、待つことをお勧めします。新しいpython仮想マシンが登場し、 unladen-swallow が主流になります。

1
Davide

確立されたプロジェクトの場合、パフォーマンスの主な向上は、python内部ライブラリを可能な限り利用することによるものだと思います。

いくつかのヒントはここにあります: http://blog.hackerearth.com/faster-python-code

この質問が行われた後、Pythonコードを高速化するいくつかの方法が導入されました:

  • PypyにはJITコンパイラがあり、CPUバウンドコードの処理が大幅に高速化されています。
  • Pypyは Rpython 、ネイティブコードにコンパイルされるPython、 LLVMツールチェーンを活用します。
0
Janus Troelsen