これは実際には2つの質問ですが、それらは非常に似ているので、簡単にするために、それらをまとめるだけだと思いました。
最初に:確立されたpythonプロジェクトを考えると、単なるコード内最適化を超えてそれをスピードアップするためのいくつかの適切な方法は何ですか?
Secondly:Pythonでプログラムを最初から作成する場合、パフォーマンスを大幅に向上させるための良い方法は何ですか?
最初の質問では、きちんと書かれたプロジェクトが渡され、パフォーマンスを改善する必要があると想像してください。しかし、リファクタリング/最適化によって多くの利益を得ることができないようです。この場合、Cのようなものに書き直す以外に、速度を上げるにはどうしますか?
「第二に:Pythonでプログラムを最初から作成する場合、パフォーマンスを大幅に向上させるための良い方法は何ですか?」
ジャクソンの最適化のルールを覚えておいてください。
そしてクヌースのルール:
より便利なルールは 最適化の一般ルール にあります。
あなたが行くように最適化しないでください。まず、正しく理解してください。その後、それを速く取得します。間違ったプログラムを最適化することはまだ間違っています。
80/20の法則を覚えておいてください。
常に「前」と「後」のベンチマークを実行します。そうしないと、80%を見つけたかどうかわかりません。
適切なアルゴリズムとデータ構造を使用してください。このルールを最初にする必要があります。アルゴリズムとデータ構造ほど重要なことはありません。
ボトムライン
「このプログラムの最適化」の取り組みを防止または回避することはできません。それは仕事の一部です。設計、コード、およびテストアクティビティと同様に、計画を立てて慎重に行う必要があります。
単にCにパントするのではなく、次のことをお勧めします。
コードを重要視してください。行の実行を減らして、より多くのことを実行します。
numpy
をチェックアウトすることをお勧めします。Twisted
フレームワークのようなものである可能性があります。プロファイルおよび測定されたコードで上記のすべてが失敗した場合は、Cリライトパスについて考え始めてください。
通常の容疑者-プロファイルを作成し、最も高価な行を見つけ、それが何をしているのかを理解し、修正します。これまであまりプロファイリングを行ったことがない場合は、大きな太い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実装-それらが異なる場合、どちらが間違っているかを見つけて問題を修正するのは非常に簡単です。
Cythonとpyrexは、Pythonのような構文を使用してcコードを生成するために使用できます。 Psycoは、適切なプロジェクトにも最適です(速度の向上に気付かない場合もあれば、50倍の速度になる場合もあります)。私は今でも、コード(cProfileなど)のプロファイルを作成してから、ボトルネックをpythonのc関数としてコーディングするのが最善の方法だと考えています。
誰も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
読んでいただければ幸いです: http://wiki.python.org/moin/PythonSpeed/PerformanceTips
すでにあるものを再開すると、通常3つの原則があります。
これは必ずしもコードの速度を上げるわけではありませんが、コードの速度を落とさないようにする場合は、Pythonでプログラミングするときに重要な知識です。「グローバルインタープリターロック」(GIL)にはマルチスレッドプログラムの動作が理解されていない場合、その速度が大幅に低下する可能性があります(はい、これは私を苦しめました...一度に1.2プロセッサを超えて使用しないNice 4プロセッサマシンがありました)。 SmoothSpan で始めるためのいくつかのリンクを含む紹介記事。
Pythonプロファイラーを介してアプリを実行します。深刻なボトルネックを見つけます。そのボトルネックをCで書き直します。繰り返します。
人々はいくつかの良いアドバイスをしましたが、高性能が必要な場合、pythonモデルは:punt to cです。psycoのような取り組みは将来少し役立つかもしれませんが、 pythonは高速な言語ではなく、そのように設計されていません。動的な処理を非常にうまく実行し、それでも非常に高速なコードを生成できる言語はほとんどありません。少なくとも予見可能な将来(および一部の設計は高速コンパイルに対して機能します)が当てはまります。
したがって、本当にこのバインドに自分自身を見つけた場合、最善の策は、(良い)Pythonで許容できない遅い部分を分離し、Cでそれらのビットを書き換えるという考えに基づいて設計することです。申し訳ありません。優れたデザインは、これをそれほど苦痛にしないのに役立ちます。ただし、最初にpythonでプロトタイプを作成すると、cのサニティチェックも簡単に実行できます。
結局のところ、これはnumpyのようなものには十分に機能します。しかし、どれだけ優れたデザインが役立つかを強調することはできません。 pythonビットを繰り返し突いて、最も遅いビットをCに置き換えると、大きな混乱に終わる可能性があります。Cビットが必要な場所とその方法を正確に考えてください。最小化され、適切にカプセル化されます。
Python)に手書きで書かれた明示的なアルゴリズムを置き換えることで、Cに近い速度(最初にPythonを使用するプロジェクトに十分近い!)組み込みのPython呼び出しを使用する暗黙のアルゴリズムを使用します。これは、ほとんどのPython組み込みがCで記述されているため、機能します。もちろん、CPythonでは;-) https://www.python.org/doc/essays/list2str/
これは私が従おうとしている手順です:
Psycoの使用に関する注意:場合によっては、実際に実行時間が遅くなる可能性があります。特にCで書かれたコードでpsycoを使おうとすると、これを読んだ記事を思い出せませんが、map()
関数とreduce()
関数が具体的に言及されました。幸い、指定された関数やモジュールを処理しないようにpsycoに指示できます。
Pythonコードを改善する方法の標準的なリファレンスはここにあります: PerformanceTips 。本当に必要な場合を除いて、Cでの最適化はお勧めしません。ほとんどのアプリケーションでは、そのリンクに掲載されているルールに従うことで、必要なパフォーマンスを得ることができます。
Psycoを使用する場合は、psyco.profile()
ではなくpsyco.full()
をお勧めします。大規模なプロジェクトの場合、最適化された関数についてより賢くなり、使用するメモリが1トン少なくなります。
イテレーターとジェネレーターも検討することをお勧めします。アプリケーションが大きなデータセットを使用している場合、これによりコンテナのコピーが多数節約されます。
(素晴らしい) psyco と(素敵な) shedskin の他に、私は cython の素晴らしいフォーク pyrex を試すことをお勧めします。
または、急いでいない場合は、待つことをお勧めします。新しいpython仮想マシンが登場し、 unladen-swallow が主流になります。
確立されたプロジェクトの場合、パフォーマンスの主な向上は、python内部ライブラリを可能な限り利用することによるものだと思います。
いくつかのヒントはここにあります: http://blog.hackerearth.com/faster-python-code
この質問が行われた後、Pythonコードを高速化するいくつかの方法が導入されました: