4

Python で並行処理を行うにはさまざまな方法があります。以下に簡単なリストを示します。

  • プロセスベース: process.Popen, multiprocessing.Process, 昔ながらos.systemの , os.popen,os.exe*
  • スレッドベース:threading.Thread
  • マイクロスレッドベース:greenlet

私は、スレッドベースの同時実行とプロセスベースの同時実行の違いを知っています。また、のスレッド サポートGILにおける の影響についてもある程度 (あまり多くはありません) 知っています。CPython

ある程度の同時実行性を実装したい初心者の場合、どのように選択すればよいでしょうか? または、それらの一般的な違いは何ですか? Pythonで並行処理を行う方法は他にありますか?

正しい質問をしているかどうかわかりません。お気軽にこの質問を改善してください。

4

1 に答える 1

6

これらの3つのメカニズムすべてが存在する理由は、それらが異なる長所と短所を持っているためです。

まず、多数の小さな独立したタスクがあり、それらをバッチ処理する賢明な方法がない場合(通常、これはC10kサーバーを作成していることを意味しますが、それが唯一の可能なケースではありません)、マイクロスレッドが勝ちます。すべてが停止するか、単に失敗する前に、数百のOSスレッドまたはプロセスしか実行できません。したがって、マイクロスレッドを使用するか、自動同時実行をあきらめて、明示的なコールバックまたはコルーチンの作成を開始します。これは、マイクロスレッドが勝つ唯一の時間です。それ以外の点では、いくつかの点が正しく機能しないことを除けば、OSスレッドと同じです。

次に、コードがCPUにバインドされている場合は、プロセスが必要です。マイクロスレッドは本質的にシングルコアソリューションです。Pythonのスレッドは、GILが原因で、通常、うまく並列化できません。プロセスは、OSが処理できる限り多くの並列処理を取得します。したがって、プロセスにより、4コアシステムでコードを4倍の速度で実行できます。他には何もしません。(実際、さらに進んで別々のコンピューターに分散したい場合もありますが、それについては尋ねませんでした。)ただし、コードがI / Oバウンドの場合、コア並列処理は役に立たないため、スレッドは同じです。プロセスとして良い。

共有された可変データがたくさんある場合、事態は困難になります。multiprocessing.Arrayプロセスでは、の代わりに使用するなど、すべてを共有可能な構造に明示的に配置する必要がありますがlist、これは悪夢のように複雑になります。スレッドはすべてを自動的に共有します。つまり、どこにでも競合状態があります。つまり、フローを慎重に検討し、ロックを効果的に使用する必要があります。プロセスを使用すると、経験豊富な開発者は、すべてのテストデータで機能するシステムを構築できますが、新しい入力セットを提供するたびに再編成する必要があります。スレッドを使用すると、経験豊富な開発者は、数週間実行されるコードを記述してから、誤ってサイレントに全員のクレジットカード番号をスクランブリングすることができます。

問題をよりよく理解しているので、これら2つのどちらがあなたをもっと怖がらせますか。どちらかを実行してください。または、可能であれば、一歩下がってコードを再設計し、共有データのほとんどを独立または不変にするようにしてください。これは(物事を遅すぎたり、理解しづらくしたりせずに)不可能かもしれませんが、それを決定する前にそれについてよく考えてください。

独立したデータや共有された不変のデータがたくさんある場合は、スレッドが明らかに勝ちます。プロセスには、明示的な共有(multiprocessing.Array再度のように)またはマーシャリングのいずれかが必要です。multiprocessingまた、サードパーティの代替手段により、すべてが選択可能であるという単純なケースではマーシャリングが非常に簡単になりますが、値を直接渡すほど単純ではなく、速度も大幅に低下します。

残念ながら、渡す必要のある不変のデータがたくさんあるほとんどの場合は、CPUの並列処理が必要な場合とまったく同じです。つまり、トレードオフがあります。そして、このトレードオフに対する最善の答えは、現在の4コアシステムのOSスレッドかもしれませんが、2年以内に使用している16コアシステムのプロセスです。(たとえば、multiprocessing.ThreadPoolまたはなどを整理し、後で、またはランタイム構成スイッチを使用しconcurrent.futures.ThreadPoolExecutorて簡単に切り替えると、問題はほぼ解決します。ただし、これが常に可能であるとは限りません。)PoolProcessPoolExecutor

最後に、アプリケーションが本質的にイベントループを必要とする場合(GUIアプリやネットワークサーバーなど)、最初に好きなフレームワークを選択します。たとえば、PySidevs wx。、またはtwistedvs.geventを使用したコーディングは、マイクロスレッドとOSスレッドを使用したコーディングよりも大きな違いがあります。そして、フレームワークを選択したら、実際の同時実行性が必要だと思ったイベントループをどれだけ活用できるかを確認してください。たとえば、30秒ごとに実行するコードが必要な場合は、そのためのスレッド(microまたはOS)を開始せず、フレームワークに必要に応じてスケジュールするように依頼します。

于 2013-01-15T21:36:45.563 に答える