web-dev-qa-db-ja.com

Pythonマルチプロセッシングモジュールの.join()メソッドの実行内容

Pythonについて学習します MultiprocessingPMOTWの記事 から)join()メソッドが正確に何をしているのかを明確にしたいと思います。

2008年の古いチュートリアル では、以下のコードでp.join()呼び出しがなければ、「子プロセスはアイドル状態になり、終了せず、手動で殺す必要があるゾンビになります」と述べています。

from multiprocessing import Process

def say_hello(name='world'):
    print "Hello, %s" % name

p = Process(target=say_hello)
p.start()
p.join()

テストするためにPIDtime.sleepのプリントアウトを追加しましたが、わかる限り、プロセスは自動的に終了します。

from multiprocessing import Process
import sys
import time

def say_hello(name='world'):
    print "Hello, %s" % name
    print 'Starting:', p.name, p.pid
    sys.stdout.flush()
    print 'Exiting :', p.name, p.pid
    sys.stdout.flush()
    time.sleep(20)

p = Process(target=say_hello)
p.start()
# no p.join()

20秒以内:

936 ttys000    0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000    0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001    0:00.13 -bash

20秒後:

947 ttys001    0:00.13 -bash

動作は、p.join()がファイルの最後に追加された場合と同じです。 Python今週のモジュールでは、 モジュールの非常に読みやすい説明 ;を提供しています。 「プロセスが処理を完了して終了するまで待つには、join()メソッドを使用します。」とはいえ、少なくともOS Xはそれを行っていたようです。

メソッドの名前についても疑問に思っています。 .join()メソッドはここで何かを連結していますか?プロセスを終了と連結していますか?または、Pythonのネイティブ.join()メソッドと名前を共有するだけですか?

86
MikeiLL

join()メソッドは、threadingまたはmultiprocessingとともに使用される場合、str.join()とは関係ありません。実際には、何かを連結することはありません。むしろ、「この[スレッド/プロセス]が完了するのを待つ」という意味です。 joinモジュールのAPIはmultiprocessingモジュールのAPIに似ているため、threadingモジュールはthreadingオブジェクトにjoinを使用するため、Threadという名前が使用されます。 「スレッドが完了するのを待つ」という意味のjoinという用語の使用は、多くのプログラミング言語で一般的であるため、Pythonも同様に採用しました。

ここで、join()の呼び出しの有無にかかわらず20秒の遅延が発生する理由は、デフォルトでは、メインプロセスが終了する準備ができたときに、実行中のすべてのmultiprocessing.Processインスタンスで暗黙的にjoin()を呼び出すためです。これは、multiprocessing docsに明確に記載されているはずではありませんが、 プログラミングガイドライン セクションで言及されています。

また、非デーモンプロセスは自動的に結合されることに注意してください。

プロセスを開始する前に、daemonProcessフラグをTrueに設定することにより、この動作をオーバーライドできます。

p = Process(target=say_hello)
p.daemon = True
p.start()
# Both parent and child will exit here, since the main process has completed.

その場合、子プロセス メインプロセスが完了するとすぐに終了します

デーモン

プロセスのデーモンフラグ、ブール値。これは、start()を呼び出す前に設定する必要があります。

初期値は作成プロセスから継承されます。

プロセスが終了すると、すべてのデーモンの子プロセスを終了しようとします。

95
dano

join()がない場合、メインプロセスは子プロセスが完了する前に完了できます。どのような状況でそれがゾンビにつながるかはわかりません。

join()の主な目的は、メインプロセスが子プロセスの作業に依存する処理を行う前に、子プロセスが完了していることを確認することです。

join()の語源は、forkの反対です。これは、子プロセスを作成するためのUnixファミリオペレーティングシステムで一般的な用語です。単一のプロセスが複数に「分岐」し、「結合」して1つに戻ります。

29

joinが何をするのかを詳しく説明するつもりはありませんが、その背後にある語源と直観があります。

アイデアは、「 forks 」を実行して、そのうちの1つをマスター、残りのワーカー(または「スレーブ」)にするプロセスです。ワーカーが完了すると、マスターが「結合」され、シリアル実行が再開されます。

joinメソッドにより、マスタープロセスはワーカーが参加するのを待ちます。このメソッドは、それがマスターで発生する実際の動作であるため、「待機」と呼ばれる可能性があります(POSIXスレッドでは「結合」とも呼ばれますが、それはPOSIXで呼び出されます)。結合は、スレッドが適切に連携する結果としてのみ発生します。これは、マスターが行うものではありませんdoes

「fork」および「join」という名前は、マルチプロセッシングでこの意味で使用されています 1963年以降

11
Fred Foo

join()は、ワーカープロセスが終了するのを待つために使用されます。 close()を使用する前に、terminate()またはjoin()を呼び出す必要があります。

@Russellが言及したようにjoinfork(Spawnsサブプロセス)の反対のようなものです。

結合を実行するには、close()を実行する必要があります。これにより、それ以上のタスクがプールに送信されなくなり、すべてのタスクが完了すると終了します。または、terminate()を実行すると、すべてのワーカープロセスがすぐに停止して終了します。

"the child process will sit idle and not terminate, becoming a zombie you must manually kill"これは、メイン(親)プロセスは終了しますが、子プロセスはまだ実行中であり、完了したら、終了ステータスを返す親プロセスがありません。

1
Ani Menon