pythonコードの運行効率を高めるためのいくつかの提案


1.コードとアルゴリズムの最適化
まずコードとアルゴリズムをよく見てください。多くの速度問題はより良いアルゴリズムを実現するかまたはキャッシュを追加することによって解決できる。本論文で述べたのはこのテーマに関するものですが、従うべきいくつかの一般的な指導方針は以下の通りです。
  • 測定して、推測しないでください。コードの中でどれが一番長いですか?まずその部分に重点を置いてください。
  • はキャッシュを実現する。ディスク、ネットワーク、データベースから何度も検索を繰り返すと、大きな最適化の可能性があります。
  • は、新しいオブジェクトを反復ごとに作成するのではなく、オブジェクトを再利用する。Pythonは作成したオブジェクトを整理してこそメモリを解放することができます。これはいわゆる「ゴミ回収」です。未使用のゴミの回収はソフトウェアの速度を大幅に低下させます。
  • は、できるだけコード内の反復回数を減らし、特に反復中の動作回数を減らす。
  • は再帰を避ける。Pythonインタプリタにとっては多くのメモリとメンテナンスが必要です。ジェネレータや反復などのツールに切り替えます。
  • メモリの使用を減らす。一般的には、メモリの使用を最小限にします。例えば、巨大なファイルを先にメモリにロードするのではなく、逐行解析します。
  • そうしないでください。馬鹿に聞こえますよね?しかし、本当にこの操作を行う必要がありますか?後で実行してもいいですか?あるいは一回だけ実行してもいいです。その結果は繰り返し計算するのではなく、記憶してもいいです。
  • 2.PyPyを使う
    Pythonの参考を使ってCPythonを実現しているかもしれません。CPythonというのはC言語で書かれているからです。あなたのコードがCPU密集型(CPU bound)であることを確認したら(この用語を知らないなら、本明細書の「スレッドを使う」セクションを参照してください)、PyPyを検討してください。CPythoonの代替案です。これは、任意の行のコードを変更する必要がない高速解決策かもしれません。
    PyPyによると、その平均速度はCPythonより4.4倍速いという。Just-i-n-time(JIT,インスタントコンパイル)という技術を使って実現しました。Javaと.NETフレームワークはJITコンパイルの他の有名な例です。対照的に、CPythonは説明を用いてコードを実行する。このやり方は大きな柔軟性を提供しますが、速度も遅くなりました。
    JITを使って、あなたのコードはプログラムを実行する時にすぐにコンパイルされます。これはAhead-off-time(AOT,前もってコンパイル)技術の速度優勢(CとC++などの言語で使用される)と解釈の柔軟性を結合しています。もう一つの利点は、JITコンパイラが動作中に常にコードを最適化できることです。コードの実行時間が長いほど、最適化されます。
    PyPyは過去数年間で長足の進歩を遂げ、通常はPython 2とPython 3の簡易代替案として利用できる。Pipenvというツールを使って、完璧に仕事ができるので、試してみてください。
    3.スレッドを使う
    ほとんどのソフトウェアはIO密集型で、CPU密集型ではない。これらの用語がよく分からないなら、以下の説明を見てください。
  • IO密集型(I/O bound):ソフトウェアは主に入出力操作が完了するまで待つ。ネットワークやスローストレージからデータを取得すると、通常このようなことがあります。
  • CPU密集型(CPU bound):ソフトウェアは大量のCPU資源を占有しています。CPUの能力をすべて使って、必要な結果を生成します。
  • ネットワークやディスクからの応答を待っている間、複数のスレッドを使って他の部分を実行状態に維持することができます。
    スレッドは独立した実行シーケンスである。デフォルトでは、Pythonプログラムにメインスレッドがあります。しかし、より多くのメインスレッドを作成し、それらの間でPythonを切り替えることができます。このような切り替えは、同時に並んでいるように見えるほど速く行われています。

    しかし、他のプログラミング言語と違って、Pythonは同時に実行するのではなく、順番に運行します。これはPythonの中にグローバル・インタプリタロック(Global Interpreter Lock,GIL)機構があるからです。この点、およびthreadingライブラリは私が書いたPythonの合併性に関する文章に詳しい説明があります。
    スレッドはIO密集型のソフトウェアに大きな影響を与えると結論したが、CPU密集型のソフトウェアは役に立たない。
    これはなぜですか?簡単です。スレッドがネットワークからの応答を待っている間、他のスレッドが動作し続けることができる。ネットワーク要求を大量に実行すると、スレッドは大きな違いをもたらすことができます。スレッドが重い計算をしている場合、それらはそれらの計算を継続する順番を待つだけで、スレッド化はより多くのオーバーヘッドをもたらすだけです。
    4.アサシンを使う
    AyncicoはPythonの中の比較的新しいコアライブラリです。これはスレッドと同じ問題を解決した:IO密集型ソフトウェアの速度を加速したが、これは異なる方法で実現された。私はすぐにPythonのasyncicoファンではないことを告白します。それはかなり複雑です。特に初心者にとって。私が出会ったもう一つの問題は、asyncicoライブラリが過去数年間に大きな発展を遂げたことです。ネット上の教程と模範コードはよく時代遅れになります。しかし、それは何の役にも立たないという意味ではない。
    5複数のプロセッサを同時に使用する
    あなたのソフトウェアがCPU密集型の場合、通常はより多くのプロセッサを同時に使用してコードを書き換えることができます。このようにして、実行速度を線形に調整することができます。
    これはいわゆる並列性であるが、すべてのアルゴリズムが並列に実行できるわけではない。例えば、再帰的アルゴリズムを単純に並列化することは不可能である。しかし、ほとんどの代替アルゴリズムがよく並行して動作する。
    より多くの処理プロセッサを使用するには、2つの方法があります。
  • は、同じマシン内で複数のプロセッサおよび/またはカーネルを使用する。Pythonでは、これをmultiprocessingライブラリで行うことができます。
  • は、コンピュータネットワークを使用して、複数のプロセッサを使用して、複数のコンピュータに分布している。私たちは分散計算と呼びます。
  • このPythonの合併性に関する記事は、Pythonソフトウェアをどのように拡張するかを紹介することに重点を置いています。また、multiprocessingライブラリを紹介します。これが必要な資料だと思ったら、ぜひ行ってみてください。
    threadingライブラリとは違って、multiprocessingライブラリはPythonのグローバルインタプリタロックをバイパスしました。これは実際には複数のPythonのインスタンスを派生することによって実現される。したがって、複数のPythonプロセスを同時に実行させることができます。単一のPythonプロセスではなく、スレッドを交互に実行します。

    multiprocessingライブラリとthreadingライブラリは非常に似ています。なぜスレッドを考えているのですか?答えは当てられます。スレッドは「軽量化」されています。これは実行中のPythonトランシーバーが必要なため、より少ないメモリが必要です。新たなプロセスを生み出すにはそれなりの出費がある。したがって、あなたのコードがIO密集型であれば、スレッドは十分に良いかもしれません。
    ソフトウェアの並列作業が実現すれば、Hadoopなどの分散計算を使って一歩前進します。クラウドコンピューティングプラットフォームを利用することで、比較的気軽に規模を広げることができます。例えば、クラウドの中で大きなデータセットを処理して、結果をローカルで使うことができます。混合動作を使うと、雲の中の計算力が非常に高いので、お金を節約できます。
    締め括りをつける
    まとめると、
  • は、まずあなたのアルゴリズムとコードの最適化を考えます。
  • 元の速度で問題が解決できるなら、PyPyを使用してください。
  • は、IO密集型ソフトウェアに対して、threadingライブラリとasyncicoを使用する。
  • は、multiprocessingライブラリを使用して、CPUの密集型問題を解決する。
  • これらの措置が足りないなら、Hadoopなどのクラウドコンピューティングプラットフォームを利用して規模を拡大することができます。
  • 以上はpythonコードの運行効率を高めるためのいくつかの提案の詳細です。pythonコードの運行効率を高めるための資料について、他の関連記事に注目してください。