2017-05-19 3 views
0

私はプロデューサとコンシューマプロセスとそれらの間に共有メモリ領域を持っています。 Conditionオブジェクトを使用して、新しいデータが利用可能なときにプロデューサプロセスからコンシューマプロセスを通知します。他のプロセスが準備される前にCondition.notify()を呼び出すときのPythonマルチプロセッシングのデッドロック

現在の問題は、以下のトレースとcond.wait上ArrayConsumerデッドロック()である:私の理解から、何が起こっている

Producer: (3, 3, 30, 100) 
Producer Done 
Consumer: (3, 3, 30, 100) 
Consumer Waiting... 

消費者が通知を受信する準備ができている前に、プロデューサーが消費者に通知していることですプロデューサーの通知を待っています。準備が整うと消費者に通知されるようにする最良の方法は何ですか?

def ArrayConsumer(aArray, cond): 
    print('Consumer:', aArray.shape) 

    with cond: 
     print('Consumer Waiting...') 
     cond.wait() 
     print('Waiting finished..') 
     print('Consumer:', aArray[1, 1, 1, 1]) 

def ArrayProducer(aArray, cond): 
    print('Producer:', aArray.shape) 
    with cond: 
     aArray.fill(1) 
     cond.notify() 
    print('Producer Done') 

if __name__ == '__main__': 

    # sharing numpy arrays 
    csi = csiMatrix(3, 3, 30, 100) 
    shared = sm.sharedmem.empty(csi.shape, dtype=complex) 
    shared[:] = csi 

    cond = Condition() 

    p = Process(target=ArrayProducer, args=(shared, cond,)) 
    c = Process(target=ArrayConsumer, args=(shared, cond,)) 
    p.start() 
    c.start() 

    p.join() 
    c.join() 
+1

個人的には、「最良の」方法は「条件」を気にしないことです。生成されたデータをコンシューマに送信するために「キュー」を使用します。 – torek

+0

私は複数のGBのデータを持っています。キューは、それを保持することができないか、直列化および直列化解除に時間がかかりすぎる可能性があります。 –

+0

大きなデータがある場合は、 'Queue'オブジェクト*が高価すぎるかもしれません(しかし、これを見て測定する必要があります)。 [noxdafox said](http://stackoverflow.com/a/44084827/1256452)、本質的にロックでラップされたフラグである 'Event'オブジェクトを使用することができます。 – torek

答えて

1

Condition.notifyの方法は誰も待機していない場合はnoopです。あなたのロジックをwhileループにカプセル化し、データが準備ができているかどうか定期的に確認する必要があります。 PythonのドキュメントにはP&C exampleがあります。 waitメソッドにタイムアウトを設定し、すべての反復で配列内のデータをチェックする必要があります。

長いポーリングの仕組みを避けるためにLockEventを使用する方がはるかに簡単です。

def ArrayConsumer(aArray, lock, event): 
    print('Consumer:', aArray.shape) 
    print('Consumer Waiting...') 
    event.wait() 
    print('Waiting finished..') 
    with lock: 
     print('Consumer:', aArray[1, 1, 1, 1]) 
     event.clear() 

def ArrayProducer(aArray, lock, event): 
    print('Producer:', aArray.shape) 
    with lock: 
     aArray.fill(1) 
     event.set() 
    print('Producer Done')` 

それにもかかわらず、私は非常に生産者と消費者のパターンを実装するためにPipeまたはQueueを使用することをお勧めします。それははるかに堅牢なメカニズムです。

+0

イベントはなぜより適切でしょうか?競争状態を防ぐためにロックが必要です。私はパイプを通して複数のGBデータ構造を渡すことはできないと思います。 –

+0

はいできます。それはあなたがしたいことを達成する最も簡単な方法です。条件を使ってP&Cを実装する方法を示す答えを修正します。 – noxdafox

関連する問題