2010-06-25 3 views
6

나는이 코드 조각으로 교착 상태에 문제가 발생 얻을 : 내 프로그램을 실행할 때, _entropy_split_parallel를 통해 여러 실행을 위해 잘 작동파이썬 multiprocessing.Queue 넣어에서 교착 상태와


def _entropy_split_parallel(data_train, answers_train, weights): 
    CPUS = 1 #multiprocessing.cpu_count() 
    NUMBER_TASKS = len(data_train[0]) 
    processes = [] 

    multi_list = zip(data_train, answers_train, weights) 

    task_queue = multiprocessing.Queue() 
    done_queue = multiprocessing.Queue() 

    for feature_index in xrange(NUMBER_TASKS): 
     task_queue.put(feature_index) 

    for i in xrange(CPUS): 
     process = multiprocessing.Process(target=_worker, 
       args=(multi_list, task_queue, done_queue)) 
     processes.append(process) 
     process.start() 

    min_entropy = None 
    best_feature = None 
    best_split = None 
    for i in xrange(NUMBER_TASKS): 
     entropy, feature, split = done_queue.get() 
     if (entropy < min_entropy or min_entropy == None) and entropy != None: 
      best_feature = feature 
      best_split = split 

    for i in xrange(CPUS): 
     task_queue.put('STOP') 

    for process in processes: 
     process.join() 

    return best_feature, best_split 


def _worker(multi_list, task_queue, done_queue): 
    feature_index = task_queue.get() 
    while feature_index != 'STOP': 
     result = _entropy_split3(multi_list, feature_index) 
     done_queue.put(result) 
     feature_index = task_queue.get() 

, 결국 교착 상태. 부모 프로세스는 done_queue.get()에서 차단되고 작업자 프로세스는 done_queue.put()에서 차단됩니다. 이 경우 대기열이 항상 비어 있으므로 get에 대한 차단이 예상됩니다. 내가 이해하지 못하는 이유는 대기열이 분명히 가득 차 있지 않기 때문에 (왜냐하면 그것은 비어있다!) 노동자가 put에서 막고있는 이유 다. blocktimeout 키워드 인수를 시도했지만 동일한 결과가 나타납니다.

파이썬 2.5가 붙어있어 멀티 프로세싱 백 포트를 사용하고 있습니다.


EDIT : 멀티 프로세싱 모듈과 함께 제공되는 예제 중 하나에서 교착 상태 문제가 발생하는 것 같습니다. 아래쪽에서 세번째 예제입니다. here. 테스트 메소드를 여러 번 호출하면 교착 상태가 발생하는 것 같습니다. 나는이 오래된 질문이다 알지만, 시험이 파이썬 2.7과 창에 더 이상 문제가 있음을 보여줍니다 :


if __name__ == '__main__': 
    freeze_support() 
    for x in xrange(1000): 
     test() 

편집을 예를 들어, 다음에 스크립트의 바닥을 변경. 나는 리눅스를 시도하고 다시보고 할 것이다.

답변

0

이 문제는 최신 버전의 Python에서 사라 졌으므로 백 포트 문제라고 생각합니다. 어쨌든 더 이상 문제가 아닙니다.

4

문제는 부모 스레드가 큐를 통과 한 자식 스레드에 참가한다고 생각합니다. 이것은 다중 처리 모듈의 programming guidelines section에 대해 설명합니다.

어쨌든, 나는 당신이 묘사 한 증상과 똑같은 증상을 겪었고, 마스터 스레드가 자식 스레드에 참여하지 못하도록 논리를 리팩토링했을 때 교착 상태가 발생하지 않았습니다. 내 리팩터링 로직은 결과 또는 "완료"대기열 (하위 스레드 수나 작업 대기열의 항목 수 등을 기준으로 예측할 수 있음)에서 가져와야하는 항목의 수를 파악하고 루핑 이 모든 것이 수집 될 때까지 무한히 논리의

"장난감"그림 :

num_items_expected = figure_it_out(work_queue, num_threads) 
items_received = [] 
while len(items_received) < num_items_expected: 
    items_received.append(done_queue.get()) 
    time.sleep(5) 

위의 논리는 자식 스레드에 가입하는 부모 스레드에 대한 필요성을 피할 수는 아직 모든 아이들이 완료 될 때까지 부모 스레드를 차단할 수 있습니다. 이 접근법은 교착 상태 문제를 피했습니다.

+0

프로세스가 결합 될 때 모든 대기열이 비어 있어야한다고 생각하기 때문에 문제가되지 않습니다. 게다가, 마스터 프로세스는 참여하기보다는 풋에서 교착 상태에 빠져 있습니다. 방금 Python을 업그레이드 했으므로 (이전 버전이 붙어 있었음) 다시 테스트 해 보겠습니다. – ajduff574

+0

@ajduff 내 경우에는, 데드락은 조인에 발생하지 않았지만 put은 자식 스레드에 있었다는 것을 제외하고는 put에도 발생했습니다. 또한 필자의 경우 대기열은 비어있었습니다. 따라서 귀하의 경우에는 합당한 가치가 있다고 생각합니다 (즉, 마스터 스레드가 하위 스레드에 참여하는 것을 피하는 것). – Jeet