PYTHON · 비동기
동시성 — multiprocessing & concurrent.futures
GIL 때문에 CPU 바운드 작업은 threading으로 병렬화되지 않습니다. multiprocessing이나 concurrent.futures.ProcessPoolExecutor를 사용하면 멀티코어를 활용한 진정한 병렬 처리가 가능합니다.
핵심 설명
GIL 때문에 CPU 바운드 작업은 threading으로 병렬화되지 않습니다. multiprocessing이나 concurrent.futures.ProcessPoolExecutor를 사용하면 멀티코어를 활용한 진정한 병렬 처리가 가능합니다.
Python code
import time
import math
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed
def is_prime(n):
"""CPU 바운드 작업: 소수 판별"""
if n < 2:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def count_primes(start, end):
"""범위 내 소수 개수 계산"""
return sum(1 for n in range(start, end) if is_prime(n))
def benchmark(executor_class, name, ranges):
start = time.perf_counter()
results = []
with executor_class(max_workers=4) as executor:
futures = {
executor.submit(count_primes, s, e): (s, e)
for s, e in ranges
}
for future in as_completed(futures):
s, e = futures[future]
count = future.result()
results.append(count)
elapsed = time.perf_counter() - start
total = sum(results)
print(f" {name}: {total}개 소수, {elapsed:.3f}초")
return elapsed
if __name__ == '__main__':
RANGE = 500_000
CHUNKS = 4
chunk_size = RANGE // CHUNKS
ranges = [(i * chunk_size, (i+1) * chunk_size) for i in range(CHUNKS)]
print(f"0~{RANGE:,} 범위 소수 계산 (4 workers):")
# 순차 실행
start = time.perf_counter()
total = count_primes(0, RANGE)
seq_time = time.perf_counter() - start
print(f" 순차 실행: {total}개 소수, {seq_time:.3f}초")
# 멀티프로세스 (CPU 바운드에 효과적)
proc_time = benchmark(ProcessPoolExecutor, "프로세스풀", ranges)
# 멀티스레드 (GIL로 인해 CPU 바운드에 비효율)
thread_time = benchmark(ThreadPoolExecutor, "스레드풀 ", ranges)
print(f"\n속도 향상: 프로세스풀 {seq_time/proc_time:.1f}x")학습 팁
ProcessPoolExecutor는 프로세스 간 데이터를 pickle로 직렬화합니다. 큰 데이터는 공유 메모리(multiprocessing.shared_memory)를 사용하세요.
주의할 점
Windows에서 multiprocessing 사용 시 if __name__ == "__main__": 가드가 없으면 무한 재귀로 프로세스가 폭발합니다.
자주 묻는 질문
동시성 — multiprocessing & concurrent.futures란 무엇인가요?
GIL 때문에 CPU 바운드 작업은 threading 으로 병렬화되지 않습니다. multiprocessing 이나 concurrent.futures.ProcessPoolExecutor 를 사용하면 멀티코어를 활용한 진정한 병렬 처리가 가능합니다.
동시성 — multiprocessing & concurrent.futures 학습 시 주의할 점은 무엇인가요?
Windows에서 multiprocessing 사용 시 if __name__ == "__main__": 가드가 없으면 무한 재귀로 프로세스가 폭발합니다.
Continue Learning
Python 학습을 이어가세요
총 200개의 독립 HTML 학습 문서 중 하나입니다. 각 문서는 고유 URL과 canonical 메타데이터를 가집니다.