Python 3의 Concurrent.futures vs 멀티 프로세싱


답변:


145

concurrent.futures더 "고급" 이라고 부르지는 않겠 습니다. 기본 병렬 처리 기믹으로 여러 스레드를 사용하는지 아니면 여러 프로세스를 사용하는지에 관계없이 매우 간단한 인터페이스입니다.

따라서 거의 모든 "단순한 인터페이스"인스턴스와 마찬가지로 거의 동일한 트레이드 오프가 수반됩니다. 학습 수있는 것이 훨씬 적기 때문에 학습 곡선이 더 얕 습니다. 그러나 더 적은 옵션을 제공하기 때문에 더 풍부한 인터페이스가 제공하지 않는 방식으로 결국 실망 할 수 있습니다.

CPU 바운드 작업이 진행되는 한, 너무 의미가 없어서 의미가 없습니다. CPython의 CPU 바운드 작업의 경우 속도를 높일 수있는 여러 스레드가 아닌 여러 프로세스가 필요합니다. 그러나 얼마나 많은 속도를 얻는지는 하드웨어, OS의 세부 사항, 특히 특정 작업에 필요한 프로세스 간 통신량에 따라 다릅니다. 엄밀히 말하면 모든 프로세스 간 병렬 특수 효과는 동일한 OS 프리미티브에 의존합니다.이를 달성하기 위해 사용하는 고급 API는 최종 속도의 주요 요소가 아닙니다.

편집 : 예

참조한 기사에 표시된 최종 코드는 다음과 같지만 작동시키는 데 필요한 import 문을 추가하고 있습니다.

from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
    # Let the executor divide the work among processes by using 'map'.
    with ProcessPoolExecutor(max_workers=nprocs) as executor:
        return {num:factors for num, factors in
                                zip(nums,
                                    executor.map(factorize_naive, nums))}

multiprocessing대신에 똑같은 것을 사용하십시오 :

import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
    with mp.Pool(nprocs) as pool:
        return {num:factors for num, factors in
                                zip(nums,
                                    pool.map(factorize_naive, nums))}

multiprocessing.Pool컨텍스트 관리자로 객체 를 사용하는 기능이 Python 3.3에서 추가되었습니다.

어느 것이 더 쉬운가요? LOL ;-) 그것들은 본질적으로 동일합니다.

한 가지 차이점은 즉 Pool지원 당신이 얼마나 쉽게 실현되지 않을 수도 있다는 것을 일을 여러 가지 방법으로 그렇게 할 수 는 꽤 방법 학습 곡선까지 상승 할 때까지 일을.

다시 말하지만, 그 모든 다른 방법은 강점과 약점입니다. 일부 상황에서는 유연성이 필요할 수 있으므로 장점입니다. "바람직한 방법은 하나뿐"이기 때문에 약점입니다. concurrent.futures최소한의 API를 사용하는 방법에 대한 참신한 부족으로 인해 독점적으로 (가능한 경우) 고집하는 프로젝트 는 아마도 장기적으로 유지 관리가 더 쉬울 것입니다.


20
"스피드 업할 가능성을 가지려면 여러 스레드가 아닌 여러 프로세스가 필요합니다 . " 속도가 중요하다면; 코드는 이미 C 라이브러리를 사용하고 있으므로 regex, lxml, numpy와 같은 GIL을 릴리스 할 수 있습니다.
jfs

4
@JFSebastian은 다음과 같이 덧붙여 주셔서 감사합니다. 아마도 " 순수한 CPython에서" 라고 말했을 것입니다 . 그러나 GIL을 논의하지 않고 진실을 설명 할 수있는 짧은 방법이 없습니다.
Tim Peters

2
그리고 긴 IO로 작업 할 때 스레드가 특히 유용하고 충분할 수 있습니다.
코트라

9
어떤면에서 @TimPeters가 ProcessPoolExecutor실제로 이상의 옵션이 Pool있기 때문에 ProcessPoolExecutor.submit반환 Future을 취소 할 수 있도록 인스턴스 ( cancel), 확인 (제기 된 예외 exception가 완료되면 호출되는), 동적 콜백을 추가하는 ( add_done_callback). 이 기능은에서 AsyncResult반환 한 인스턴스에서 사용할 수 없습니다 Pool.apply_async. 다른 방법 Pool으로 인해 더 많은 옵션이있다 initializer/ initargs, maxtasksperchildcontext에서 Pool.__init__, 그리고에 의해 노출 이상의 메소드 Pool인스턴스를.
최대

2
@ max, 물론, 질문은 Pool모듈에 관한 것이 아니라는 점에 유의하십시오 . 에 포함 된 문서 Pool의 일부이며 multiprocessing, 문서에 너무 많이 포함되어있어 사람들이 문서에 존재한다는 것을 깨닫는 데 시간이 걸립니다 multiprocessing. 이 특정 답변 Pool은 OP가 링크 한 모든 기사이기 때문에 cf"작업하기가 훨씬 쉽다"는 기사에서 논의한 내용에 대해서는 사실이 아니기 때문입니다. 그건 그렇고, cf'들 as_completed()도 매우 편리 할 수 있습니다.
Tim Peters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.