2017-05-19 6 views
0

저는 프로듀서와 소비자 프로세스 및 이들 사이에 공유 메모리 영역을 가지고 있습니다. Condition 객체를 사용하여 새 데이터를 사용할 수있을 때 생성자 프로세스에서 소비자 프로세스에 신호를 보냅니다.다른 프로세스가 준비되기 전에 Condition.notify()를 호출 할 때 파이썬 다중 처리 교착 상태가 발생했습니다.

현재 문제는 다음과 같은 추적과 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 메서드는 아무도 대기 중이 아니면 아무런 반응이 없습니다. while 루프에서 논리를 캡슐화하고 데이터가 준비되었는지 정기적으로 확인해야합니다. 파이썬 문서는 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