データのコレクションを取得するpythonアプリケーションがあり、そのコレクション内のデータごとにタスクを実行します。遅延が発生するため、タスクの完了には時間がかかります。この遅延では、各データが後でタスクを実行するのではなく、すべてを並行して実行する必要があります。この操作にマルチプロセスまたはスレッドを使用する必要がありますか?
スレッドを使用しようとしましたが、問題が発生しました。多くの場合、一部のタスクは実際には実行されませんでした。
本当に計算に縛られている場合は、 マルチプロセッシングモジュール を使用するのがおそらく最も軽量なソリューションです(メモリ消費と実装の難しさの両方の観点から)。
I/Oバウンドの場合、 スレッドモジュール を使用すると、通常、良好な結果が得られます。スレッドセーフストレージ(キューなど)を使用してデータをスレッドに渡すようにしてください。または、スポーンされたときに固有の単一のデータを渡します。
PyPy はパフォーマンスに重点を置いています。計算にバインドされた処理に役立つ多くの機能があります。また、ソフトウェアトランザクショナルメモリもサポートしていますが、それはまだ本番品質ではありません。約束は、マルチプロセッシング(いくつかの厄介な要件があります)よりも単純な並列または並行メカニズムを使用できることです。
Stackless Python もいい考えです。 Stacklessには、上記のように移植性の問題があります。 nladen Swallow 有望でしたが、現在は機能していません。 Pyston は別の(未完成の)Python速度に焦点を当てた実装です。PyPyとは異なるアプローチを採用しているため、より良い(または単に異なる)スピードアップが得られる可能性があります。
タスクは順番に実行されますが、並行して実行されるような錯覚があります。タスクは、ファイルまたは接続I/Oに使用する場合、および軽量であるために適しています。
プロセスは並列で実行されるため、プールを使用したマルチプロセスは適切なソリューションである可能性があります。各プロセスは1つのCPU(またはコア)で実行されるため、集中的なコンピューティングに非常に適しています。
マルチプロセスのセットアップは非常に簡単な場合があります。
from multiprocessing import Pool
def worker(input_item):
output = do_some_work()
return output
pool = Pool() # it make one process for each CPU (or core) of your PC. Use "Pool(4)" to force to use 4 processes, for example.
list_of_results = pool.map(worker, input_list) # Launch all automatically
データの小さなコレクションの場合は、 subprocess.Popen でサブプロセスを作成するだけです。
各サブプロセスは、stdinまたはコマンドライン引数からデータを取得し、処理を実行して、結果を出力ファイルに書き込むだけです。
サブプロセスがすべて終了した(またはタイムアウトした)場合は、出力ファイルをマージするだけです。
とてもシンプルです。
Stackless Python を調べることを検討してください。時間がかかる関数を制御できる場合は、そこにstackless.schedule()
をいくつかスローするか(次のコルーチンへのyieldを言う)、または Stacklessをプリエンプティブマルチタスクに設定 。
Stacklessでは、スレッドはありませんが、taskletsまたはgreenletsこれは本質的に非常に軽量なスレッドです。マルチタスクを実行するためのセットアップがほとんどない、非常に優れたフレームワークがあるという意味で、これはうまく機能します。
ただし、Stacklessは、標準のPythonライブラリのいくつかを置き換える必要があるため、移植性を妨げます-StacklessはCスタックへの依存を取り除きます。次のユーザーもStacklessをインストールしている場合、非常に移植性がありますが、めったにありません。
持っているデータを簡単に分割して分離できる場合は、その分割を外部で行って、プログラムのいくつかのプロセスにフィードする必要があるように思われます。 (つまり、スレッドの代わりにいくつかのプロセス)
CPythonのスレッドモデルを使用しても、ガベージコレクションの処理方法が原因でスレッドが実際には並列で実行されないため、パフォーマンスは向上しません。マルチプロセスにより、並列実行が可能になります。明らかに、この場合、並列ジョブをファームアウトするために複数のコアを使用できるようにする必要があります。
この関連する質問 で利用できるより多くの情報があります。
IronPythonには、CPythonやGILとは異なり、実際のマルチスレッドがあります。ですから、あなたがしていることに応じて、それは一見の価値があるかもしれません。しかし、ユースケースはマルチプロセッシングモジュールに適しているようです。
スタックレスPythonを推奨する人には、私はその専門家ではありませんが、実際にはまったく並列ではないソフトウェア「マルチスレッド」について話しているようです(まだ1つの物理スレッドで実行されるため、拡張できません)複数のコア。)これは、非同期(ただし、シングルスレッド、非並列)アプリケーションを構造化するための単なる代替方法です。
Twisted をご覧ください。非同期ネットワークタスク用に設計されています。