Lab 08: GIL-Free Concurrency
Overview
Step 1: Understanding the GIL
import threading
import time
def cpu_bound(n):
"""Pure CPU work — blocked by GIL between threads."""
total = 0
for i in range(n):
total += i * i
return total
N = 2_000_000
# Single thread
start = time.perf_counter()
cpu_bound(N)
cpu_bound(N)
serial_time = time.perf_counter() - start
print(f"Serial (2 calls): {serial_time*1000:.0f}ms")
# Two threads — GIL means they take turns, no speedup
t1 = threading.Thread(target=cpu_bound, args=(N,))
t2 = threading.Thread(target=cpu_bound, args=(N,))
start = time.perf_counter()
t1.start(); t2.start()
t1.join(); t2.join()
thread_time = time.perf_counter() - start
print(f"2 Threads: {thread_time*1000:.0f}ms")
print(f"Thread speedup: {serial_time/thread_time:.2f}x (expected ≈1.0 due to GIL)")Step 2: multiprocessing.Pool — True Parallelism
multiprocessing.Pool — True ParallelismStep 3: pool.map vs pool.starmap vs pool.imap
pool.map vs pool.starmap vs pool.imapStep 4: ProcessPoolExecutor and as_completed
ProcessPoolExecutor and as_completedStep 5: Shared Memory
Step 6: mmap for IPC
mmap for IPCStep 7: Chunked Parallel Processing Pattern
Step 8: Capstone — Parallel Data Pipeline
Summary
Concept
API
Use Case
Last updated
