2017-05-19 1 views
0

Ich habe einen Produzenten und Verbraucher-Prozess und eine gemeinsame Speicherbereich zwischen ihnen. Ich verwende das Condition-Objekt, um den Konsumentenprozess aus dem Produzentenprozess zu signalisieren, wenn neue Daten verfügbar sind.Python-Multiprozessor-Deadlock beim Aufruf von Condition.notify(), bevor der andere Prozess bereit ist

Aktuelles Problem ist die ArrayConsumer Deadlocks auf cond.wait() mit der folgenden Spur:

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

Was aus meinem Verständnis geschieht, ist, dass der Hersteller die Verbraucher informiert, bevor die Verbraucher bereit ist, die Benachrichtigung zu erhalten, und wartet daher auf die Benachrichtigung des Herstellers. Was ist der beste Weg, um sicherzustellen, dass der Verbraucher nur dann signalisiert wird, wenn er bereit ist?

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

Persönlich denke ich, dass der "beste" Weg ist, sich nicht mit 'Condition' zu beschäftigen: Verwenden Sie eine' Queue', um produzierte Daten an die Konsumenten zu senden. – torek

+0

Ich habe mehrere GB Daten. Eine Warteschlange könnte es nicht halten oder zu lange dauern, um sie zu serialisieren und zu serialisieren. –

+0

Wenn Sie große Daten haben, dann ja, ein 'Queue'-Objekt * kann * zu teuer sein (aber Sie sollten dies messen, um zu sehen). Wie [noxdafox sagte] (http://stackoverflow.com/a/44084827/1256452) können Sie ein 'Event'-Objekt verwenden, bei dem es sich im Wesentlichen um ein mit einer Sperre umschlossenes Flag handelt. – torek

Antwort

1

Die Condition.notify Methode ist ein noop wenn niemand wartet. Sie müssen Ihre Logik in einer while-Schleife kapseln und regelmäßig prüfen, ob die Daten bereit sind. Die Python-Dokumentation hat eine P&C example. Sie müssten eine Zeitüberschreitung für die Methode wait festlegen und die Daten in Ihrem Array bei jeder Iteration überprüfen.

Es ist viel einfacher, eine Lock und eine Event zu verwenden, die einen Long-Polling-Mechanismus vermeiden würde.

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')` 

Trotzdem Ich würde empfehlen, ein Pipe oder zu verwenden Queue das Erzeuger- und Verbrauchermuster zu implementieren. Es ist ein viel robuster Mechanismus.

+0

Warum sollte ein Ereignis angemessener sein? Ich brauche ein Schloss, um die Rennen zu verhindern. Ich glaube nicht, dass ich mehrere GB-Datenstrukturen durch eine Pipe passieren kann. –

+0

Ja können Sie. Es ist immer noch der einfachste Weg, um das zu erreichen, was Sie tun möchten. Ich werde die Antwort ändern, um zu zeigen, wie P & C mit einer Bedingung implementiert wird. – noxdafox

Verwandte Themen