파이썬에서 여러 작업을 동시에 실행하고 싶을 때 유용한 모듈이 **concurrent.futures**입니다. 이번 예제는 ThreadPoolExecutor를 사용해 여러 개의 합계를 동시에 계산하는 코드입니다.
1. 코드 구조
import time
from concurrent import futures
WORK_LIST = [10000, 100000, 1000000, 10000000]
def sum_generator(n):
return sum(range(1, n+1))
def main():
start_tm = time.time()
# CPU-bound 작업 → ProcessPoolExecutor 사용
with futures.ProcessPoolExecutor() as executor:
result = executor.map(sum_generator, WORK_LIST)
end_tm = time.time() - start_tm
print("Result -> {} Time : {:.2f}s".format(list(result), end_tm))
if __name__ == '__main__':
main()
- ThreadPoolExecutor: 여러 개의 스레드를 풀(pool)로 만들어 작업을 분산 실행.
- executor.map(func, iterable): map처럼 동작하지만, 여러 스레드에서 동시에 실행.
- 결과 반환: list(result)를 호출하면 모든 작업의 결과가 순서대로 모임.
1️⃣ 실행 흐름
- WORK_LIST의 각 숫자에 대해 sum_generator 실행.
- ThreadPoolExecutor가 작업을 나눠 스레드에서 동시에 처리.
- 모든 결과를 모아 최종 합계와 걸린 시간 출력.
간단한 실행 예시
Result -> [50005000, 5000000050000, 500000000500000, 50000000005000000] Time : 0.12s
큰 입력값(예: 천만)도 동시에 처리하기 때문에 순차 실행보다 훨씬 빠르게 끝납니다.
2️⃣ ThreadPoolExecutor vs ProcessPoolExecutor
ThreadPoolExecutor
- 스레드 기반 동시성.
- 동일한 프로세스 내에서 스레드를 여러 개 만들어 실행.
- GIL(Global Interpreter Lock) 때문에 I/O 중심 작업에 유리.
ProcessPoolExecutor
- 프로세스 기반 병렬성.
- 여러 개의 파이썬 프로세스를 띄워서 CPU 코어를 활용.
- 각 프로세스는 독립적인 메모리 공간을 가져서 GIL의 영향을 받지 않음.
- 따라서 CPU 집약적 작업에 유리.
2. ASCII 다이어그램으로 보는 실행 흐름
1️⃣ ThreadPoolExecutor (스레드 기반)
[Main Process]
|
+--[Thread-1] sum_generator(10000)
+--[Thread-2] sum_generator(100000)
+--[Thread-3] sum_generator(1000000)
+--[Thread-4] sum_generator(10000000)
하나의 프로세스 안에서 여러 스레드가 작업을 동시에 처리합니다.
2️⃣ ProcessPoolExecutor (프로세스 기반)
[Main Process]
|
+--[Process-1] sum_generator(10000)
+--[Process-2] sum_generator(100000)
+--[Process-3] sum_generator(1000000)
+--[Process-4] sum_generator(10000000)
작업마다 별도의 프로세스가 실행되어, 여러 CPU 코어를 활용해 병렬 계산이 가능합니다.
3️⃣ 실행 흐름 요약
- ThreadPoolExecutor: 같은 프로세스 안에서 여러 스레드가 일을 나눠 처리 → I/O에 적합.
- ProcessPoolExecutor: 여러 프로세스를 띄워 병렬 실행 → CPU 연산에 적합.
정리하면
- concurrent.futures는 파이썬에서 병행성을 쉽게 구현할 수 있는 고수준 API.
- ThreadPoolExecutor는 I/O 중심 작업에, ProcessPoolExecutor는 CPU 중심 작업에 적합.
- .map()을 활용하면 리스트나 반복 가능한 객체를 병렬로 처리할 수 있어 코드가 간결해짐.
이 예제는 동시에 여러 합계 계산을 수행해 시간을 단축하는 기본 패턴을 보여줍니다.
'파이썬 > 기초 프로그래밍' 카테고리의 다른 글
| Python 동시성 프로그래밍: concurrent.futures 실습 (0) | 2025.09.09 |
|---|---|
| 파이썬 concurrent.futures에서 Future 객체의 Wait 다루기 (0) | 2025.09.09 |
| 파이썬 코루틴과 제너레이터 상태 & yield from 이해하기 (1) | 2025.09.09 |
| 파이썬 코루틴(제너레이터)로 메인↔서브 루틴 데이터 교환 이해하기 (0) | 2025.09.09 |
| 파이썬 이터레이터 vs 제너레이터 (0) | 2025.09.08 |