Python 3.2는 Concurrent Futures를 도입 했으며, 이는 이전 스레딩 및 멀티 프로세싱 모듈 의 고급 조합으로 보입니다 .
구형 멀티 프로세싱 모듈에 비해 CPU 바운드 작업에이 기능을 사용할 경우의 장단점은 무엇입니까?
이 기사 는 작업하기가 훨씬 쉽다는 것을 제안합니다.
Python 3.2는 Concurrent Futures를 도입 했으며, 이는 이전 스레딩 및 멀티 프로세싱 모듈 의 고급 조합으로 보입니다 .
구형 멀티 프로세싱 모듈에 비해 CPU 바운드 작업에이 기능을 사용할 경우의 장단점은 무엇입니까?
이 기사 는 작업하기가 훨씬 쉽다는 것을 제안합니다.
답변:
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를 사용하는 방법에 대한 참신한 부족으로 인해 독점적으로 (가능한 경우) 고집하는 프로젝트 는 아마도 장기적으로 유지 관리가 더 쉬울 것입니다.
ProcessPoolExecutor
실제로 이상의 옵션이 Pool
있기 때문에 ProcessPoolExecutor.submit
반환 Future
을 취소 할 수 있도록 인스턴스 ( cancel
), 확인 된 (제기 된 예외 exception
가 완료되면 호출되는), 동적 콜백을 추가하는 ( add_done_callback
). 이 기능은에서 AsyncResult
반환 한 인스턴스에서 사용할 수 없습니다 Pool.apply_async
. 다른 방법 Pool
으로 인해 더 많은 옵션이있다 initializer
/ initargs
, maxtasksperchild
과 context
에서 Pool.__init__
, 그리고에 의해 노출 이상의 메소드 Pool
인스턴스를.
Pool
모듈에 관한 것이 아니라는 점에 유의하십시오 . 에 포함 된 문서 Pool
의 일부이며 multiprocessing
, 문서에 너무 많이 포함되어있어 사람들이 문서에 존재한다는 것을 깨닫는 데 시간이 걸립니다 multiprocessing
. 이 특정 답변 Pool
은 OP가 링크 한 모든 기사이기 때문에 cf
"작업하기가 훨씬 쉽다"는 기사에서 논의한 내용에 대해서는 사실이 아니기 때문입니다. 그건 그렇고, cf
'들 as_completed()
도 매우 편리 할 수 있습니다.