10

Pipes複数の送信者と受信者がいるのに、なぜ安全でないと言われるのかわかりません。

Queuesこの場合、次のコードを使用してコードに変換するにはどうすればよいですか?閉じたときにQueuesスローしないでください。プロセスを停止できません。EOFError停止するように指示するために「毒」メッセージを際限なく送信する必要がありますか(このようにして、すべてのプロセスが少なくとも1つの毒を受け取ると確信しています)?

別の方法で決定するまでパイプをp1開いたままにしておきます(ここでは、10個のメッセージを送信したときです)。


from multiprocessing import Pipe, Process
from random import randint, random
from time import sleep

def job(name, p_in, p_out):
    print(name + ' starting')
    nb_msg = 0
    try:
        while True:
            x = p_in.recv()
            print(name + ' receives ' + x)
            nb_msg = nb_msg + 1
            p_out.send(x)
            sleep(random())
    except EOFError:
        pass
    print(name + ' ending ... ' + str(nb_msg) + ' message(s)')

if __name__ == '__main__':
    p1_in, p1_out = Pipe()
    p2_in, p2_out = Pipe()

    proc = []

    for i in range(3):
        p = Process(target=job, args=(str(i), p1_out, p2_in))
        p.start()
        proc.append(p)

    for x in range(10):
        p1_in.send(chr(97+x))
    p1_in.close()
    for p in proc:
        p.join()
    p1_out.close()
    p2_in.close()

    try:
        while True:
            print(p2_out.recv())
    except EOFError:
        pass

    p2_out.close()
4

2 に答える 2

17

基本的に、問題はPipe、プラットフォームで定義されたパイプオブジェクトの薄いラッパーであるということです。recv完全なPythonオブジェクトが取得されるまで、バイトのバッファを繰り返し受信するだけです。2つのスレッドまたはプロセスrecvが同じパイプで使用する場合、読み取りがインターリーブし、各プロセスにピクルス化されたオブジェクトの半分が残り、データが破損する可能性があります。Queue■複雑さを犠牲にして、プロセス間で適切な同期を行います。

multiprocessingドキュメントに記載されているように:

2つのプロセス(またはスレッド)がパイプの同じ端から同時に読み取りまたは書き込みを行おうとすると、パイプ内のデータが破損する可能性があることに注意してください。もちろん、パイプの異なる端を同時に使用するプロセスによる破損のリスクはありません。

毒薬を際限なく送る必要はありません。必要なのは、ワーカーごとに1つだけです。各労働者は退出する前にちょうど1つの毒薬を拾うので、労働者がどういうわけかメッセージを見逃す危険はありません。

multiprocessing.Poolまた、「ワーカープロセス」モデルを再実装する代わりに、を使用することを検討する必要がPoolあります。これには、複数のスレッドに作業を非常に簡単に分散できる多くのメソッドがあります。

于 2012-09-18T20:37:37.297 に答える
8

複数の送信者と受信者がいるときにパイプが安全ではないと言われる理由がわかりません。

水源 A と B から同時にパイプに水を入れたとします。パイプの反対側では、水が A から来たのか B から来たのかを知ることはできませんよね? :)

パイプは、バイト レベルでデータ ストリームを転送します。その上に通信プロトコルがないと、メッセージが何であるかがわからないため、メッセージの完全性を保証できません。したがって、複数の送信者でパイプを使用することは「安全でない」だけではありません。これは主要な設計上の欠陥であり、通信の問題につながる可能性が最も高いです。

ただし、キューはより高いレベルで実装されます。これらは、メッセージ(または抽象的なオブジェクト) を伝達するために設計されています。キューは、メッセージ/オブジェクトを自己完結型に保つために作成されます。複数のソースがオブジェクトをキューに入れることができ、複数のコンシューマーがこれらのオブジェクトをプルできますが、ユニットとしてキューに入ったものは何でもユニットとしてキューから出てくることを 100% 確信しています。

しばらくしてから編集します。

バイトストリームでは、すべてのバイトが送信されたのと同じ順序で取得されることを追加する必要があります (保証されます)。複数の送信者の問題は、送信順序 (入力の順序) が既に不明またはランダムである可能性があることです。つまり、複数のストリームが予測できない方法で混在する可能性があります。

共通キューの実装により、複数の送信者がいる場合でも、単一のメッセージがそのまま保持されることが保証されます。メッセージも送信順に取得されます。ただし、複数の競合する送信者があり、さらに同期メカニズムがない場合、入力メッセージの順序については保証されません。

于 2012-09-18T22:13:31.273 に答える