Lab 08: GIL-Free Concurrency

Time: 60 minutes | Level: Architect | Docker: docker run -it --rm python:3.11-slim bash

Overview

The Global Interpreter Lock (GIL) prevents true parallel execution of Python threads for CPU-bound work. This lab benchmarks GIL impact, escapes it with multiprocessing, explores shared memory, and builds efficient parallel pipelines.

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)")

💡 For I/O-bound tasks (network, disk), threads work great — threads release the GIL while waiting for I/O. For CPU-bound tasks, use multiprocessing to bypass the GIL.

Step 2: multiprocessing.Pool — True Parallelism

📸 Verified Output:

Step 3: pool.map vs pool.starmap vs pool.imap

Step 4: ProcessPoolExecutor and as_completed

Step 5: Shared Memory

💡 SharedMemory allows zero-copy data sharing between processes. Wrap with numpy.ndarray for efficient numerical operations across process boundaries.

Step 6: mmap for IPC

Step 7: Chunked Parallel Processing Pattern

Step 8: Capstone — Parallel Data Pipeline

📸 Verified Output:

Summary

Concept
API
Use Case

GIL impact

threading.Thread benchmark

Understand CPU-bound limits

Process pool

multiprocessing.Pool.map

Parallel CPU work

starmap

Multiple args per task

Complex function signatures

ProcessPoolExecutor

concurrent.futures

Modern pool API

as_completed

Futures iteration

Handle results as they arrive

Shared memory

SharedMemory + numpy

Zero-copy inter-process data

mmap IPC

mmap.mmap

File-backed shared memory

Chunked pipeline

Split → parallel → aggregate

Big data processing

Last updated