マルチプロセッシングfork()とspawn()
私はPythonドキュメントから2つの説明を読んでいました:
スポーン
親プロセスは、新しいpythonインタープリタープロセスを開始します。子プロセスは、プロセスオブジェクトのrun()メソッドの実行に必要なリソースのみを継承します。特に、親プロセスからの不要なファイル記述子とハンドルは継承されません。この方法を使用してプロセスを開始すると、forkまたはforkserverを使用する場合に比べてかなり遅くなります。[UnixとWindowsで利用できます。WindowsとmacOSのデフォルト。]
フォーク
親プロセスはos.fork()を使用してPythonインタープリターをフォークします。子プロセスは、開始時に、親プロセスと実質的に同じです。親のすべてのリソースは、子プロセスによって継承されます。マルチスレッドプロセスを安全にフォークすることには問題があることに注意してください。[Unixでのみ利用可能です。Unixのデフォルト。]
そして私の質問は:
- フォークがはるかに高速であるということですか?コピーするリソースを識別しようとしないためですか?
- フォークはすべてを複製するので、spawn()と比較してはるかに多くのリソースを「浪費」するということですか?
回答
- フォークがはるかに高速であるということですか?コピーするリソースを識別しようとしないためですか?
はい、はるかに高速です。カーネルはプロセス全体のクローンを作成でき、変更されたメモリページのみを全体としてコピーします。リソースを新しいプロセスにパイプし、インタプリタを最初から起動する必要はありません。
- フォークはすべてを複製するので、spawn()と比較してはるかに多くのリソースを「浪費」するということですか?
最新のカーネルのフォークは「コピーオンライト」のみを実行し、実際に変更されるメモリページにのみ影響します。注意点は、「書き込み」には、CPythonでオブジェクトを反復処理するだけのことも含まれているということです。これは、オブジェクトの参照カウントが増加するためです。
多数の小さなオブジェクトが使用されている長時間実行プロセスがある場合、これは、スポーンよりも多くのメモリを浪費することを意味する可能性があります。ちなみに、FacebookがPythonプロセスの「フォーク」から「スポーン」に切り替えることでメモリ使用量が大幅に削減されたと主張していることを思い出します。