병렬분산
from concurrent.futures import ThreadPoolExecutor
ThreadPoolExecutor
- 스레드 시작 작업에 계산이 많이 필요
- 스레드들의 풀을 생성해 해결
- 스레드 한번 생성한 후 그 스레드에게 계속 작업 주어 실행
concurrent.futures 모듈 - Executor 클래스
- 다양한 호출들을 병행적으로 동시에(concurrent) 실행
- Executor 객체 자체
executor = ThreadPoolExecutor(max_workers=3)
ThreadPoolExecutor 객체에 스레드 전달: submit() 함수
executor.submit(task) 작업 전달
- 컨텍스트 관리자와 함께 사용
- 자동으로 ThreadPoolExecutor를 인스턴스화하여 사용
with ThreadPoolExecutor(max_workers=3) as executor: # 컨텍스트 관리자
future1 = executor.submit(task, (2))
future2 = executor.submit(task, (3))
future3 = executor.submit(task, (4))
map() 함수
- 파이썬 내장 함수, Executor 함수 = iterables의 모든 요소들을 함수에 매핑하여
ThreadPoolExecutor 객체에 독립적인 작업으로 submit()
map(function, iterables, timeout=None, chunksize=1)
results = executor.map(multiplyByTwo, values)
==
for value in values:
executor.submit(multiplyByTwo, (value))
객체 shutdown() 함수
- 이미 진행 중인 작업들이 모두 종료 -> executor 객체가 할당받은 자원 반납
- shutdown 이후 submit() or map() 시 RuntimeError
- wait=True/False with 컨텍스트 관리자는 executor.shutdown(wait=True) 함수 자동 호출
퓨처 객체(Future Object)
- executor 객체에게 작업을 submit 할 때마다 퓨처 객체가 인스턴스화됨
- 호출가능한 작업의 비동기적 실행을 캡슐화한 객체로 미래의 언젠가 연산이 실행되어 결과값을 가짐
- result(timeout=None)/add_done_callback(func)/running()/cancel()/exception(timeout=None)/done()/cancelled()
- 콜백 함수 여러 개 등록해도 됨
퓨처 객체의 단위 테스트
- set_running_or_notify_cancel()
- set_result(result)
- set_exception(exception)
결과 얻어내기
results = executor.map( … )
for result in results:
print(result)
concurrent.futures.as_completed() 메서드
- 배열에 저장된 submit된 퓨처 객체들 중 완료된 퓨처 객체의 실행 결과를 전달받아 쉽게 처리 가능
- 실행을 종료 or 취소된 퓨처 객체들의 iterator 반환
- 중복된 건 한번만 실행
- 호출되기 전에 종료된 건 가장 먼저 iterator 반환
자식스레드에서 발생한 예외를 다른 부모 스레드에 자동으로 전달하여 처리 지원
ProcessPoolExecutor
executor = ProcessPoolExecutor(max_workers=3)
max_workers의 기본값 None = 기계의 프로세서 개수로 설정됨
with ProcessPoolExecutor(max_workers=3) as executor: #컨텍스트 관리자 - 가독성 향상
계산량이 많은 문제의 속도 높이기
- 멀티 프로세스가 멀티스레드 방식의 2배 이상 속도 fast
- 단일 스레드가 멀티스레드 방식보다 약간 fast