2012-02-09 6 views
6

concurrent.futures.ProcessPoolExecutor을 사용하여 일부 코드를 병렬 처리하려고 시도했지만 ThreadPoolExecutor에서 발생하지 않는 이상한 교착 상태가 계속 발생했습니다. 최소한의 예 :concurrent.futures 코드의 교착 상태

파이썬 3.2.2에서
from concurrent import futures 

def test(): 
    pass 

with futures.ProcessPoolExecutor(4) as executor: 
    for i in range(100): 
     print('submitting {}'.format(i)) 
     executor.submit(test) 

은 (64 비트 Ubuntu에서),이 모든 작업을 제출 한 후 지속적으로 걸 것 - 이것이 제출 된 작업의 수가보다 클 때마다 일어날 것 같다 근로자 수. ProcessPoolExecutorThreadPoolExecutor으로 바꾸면 완벽하게 작동합니다. callback에 의해 인쇄 i의 값이의 값입니다 -

from concurrent import futures 

def test(): 
    pass 

with futures.ProcessPoolExecutor(4) as executor: 
    for i in range(100): 
     print('submitting {}'.format(i)) 
     future = executor.submit(test) 

     def callback(f): 
      print('callback {}'.format(i)) 
     future.add_done_callback(callback) 

단지 더 나를 혼동 :

조사하기 위해, 나는 i의 값을 출력하는 콜백을 각각 미래를 준 그것이 그것이 정의 된 시간보다는 오히려 호출되는 시간 (그래서 나는 결코 callback 0을 볼 수 없다. 그러나 나는 callback 99을 많이 얻는다). 다시 ThreadPoolExecutor은 예상 값을 인쇄합니다.

궁금한 점이 있으시면 궁금한 점이 있으시면 최근 개발 된 Python 개발 버전을 사용해 보시기 바랍니다. 자, 적어도 코드는 종료 된 것처럼 보이지만 여전히 잘못된 값인 i이 출력됩니다. 그래서

누구든지 설명 할 수 : 파이썬 3.2 i의 '잘못된'값이 인쇄되는 이유를 분명히이 교착 상태

  • 를 고정 현재 dev에 버전 사이에 ProcessPoolExecutor에 무슨 일이 있었는지

    편집 : jukiewicz가 아래에 지적한대로 물론 인쇄하십시오. i 콜백이 호출 될 때의 값으로, 내가 생각한 것이 무엇인지 모르겠다 ... i의 값을 가진 호출 가능 객체를 속성으로 전달하면 예상대로 작동한다.

    EDIT : 조금 더 자세한 정보 : 모든 콜백이 실행되므로 프로세스가 완료되었음을 알 수없는 executor.shutdown (executor.__exit__이 호출 됨) 인 것처럼 보입니다. 이것은 현재 파이썬 3.3에서 완전히 수정 된 것으로 보이지만, multiprocessingconcurrent.futures에 많은 변화가 있었던 것 같아요. 그래서이 문제를 고쳤습니다. 3.3 버전을 사용할 수 없기 때문에 다중 처리 및 동시 패키지를 3.2 설치로 복사하는 것이 좋았습니다. 그래도 내가 알 수있는 한 이상한 이상한 것 같습니다 - ProcessPoolExecutor은 최신 버전에서 완전히 깨졌지만 아무도 영향을받지 않습니다.

  • +1

    두 번째 문제는 프로세스가 99를 인쇄하는 것이 당연합니다. 심볼'i'는 글로벌 컨텍스트에 묶여 있고, 새로운 프로세스를 만드는 것은 비용이 많이 들기 때문에, 무엇이든 실행할 때까지는'i == 99'가됩니다. – julkiewicz

    +1

    또한 우분투 64 비트, 파이썬 3.2.2를 가지고 있으며 첫 번째 코드 스 니펫은 걸리지 않습니다 ... – julkiewicz

    +0

    @julkiewicz : 그건 아주 이상합니다. 필자는 64 비트 Scientific Linux와 Python 3.2.2를 실행하는 다른 컴퓨터에서이 도구를 시험해 보았습니다. 10 번에서 10 번 시도시 '99를 제출하는 중'인쇄가 지연되었습니다. 'if __name__ =='에 코드를 래핑하려고했습니다. __main __ ''Windows에서 다중 처리에 필요한 것으로 들었습니다. – James

    답변

    2

    코드를 다음과 같이 수정하여 두 가지 문제를 모두 해결했습니다. callback 함수는 클로저로 정의되었으므로 매번 i의 업데이트 된 값을 사용합니다. 교착 상태는 모든 작업이 완료되기 전에 실행 프로그램을 종료하는 원인이 될 수 있습니다. 미래가 끝나기를 기다리면서도 그걸 해결합니다.

    from concurrent import futures 
    
    def test(i): 
        return i 
    
    def callback(f): 
        print('callback {}'.format(f.result())) 
    
    
    with futures.ProcessPoolExecutor(4) as executor: 
        fs = [] 
        for i in range(100): 
         print('submitting {}'.format(i)) 
         future = executor.submit(test, i) 
         future.add_done_callback(callback) 
         fs.append(future) 
    
        for _ in futures.as_completed(fs): pass 
    

    업데이트 : 오, 죄송합니다. 업데이트를 읽지 않았습니다. 이미 해결 된 것으로 보입니다.