Yeda AI Tips · #124

Español

Threads Won't Fix CPU-Bound Python

Threads will not make your CPU-bound Python faster. Ever. On CPython, the global interpreter lock (GIL) lets only one thread execute Python bytecode at a time — so ten threads crunching numbers take turns on one core while the other cores idle. Yet ask an AI assistant to "parallelize this" and it reaches for ThreadPoolExecutor by default, whatever the workload. The fix is one decision: name the bound, then pick the model.

The one table that settles it

Your work is…ExamplesUseWhy it works
I/O-bound, a handful of callsa few HTTP requests, file readsThreadPoolExecutorThe GIL is always released during I/O, so threads genuinely overlap waits
I/O-bound, thousands of connectionsscrapers, websockets, API fan-outasyncioOne thread, an event loop; the docs call it "a perfect fit for IO-bound and high-level structured network code"
CPU-boundimage processing, hashing loops, heavy math in pure PythonProcessPoolExecutorSeparate processes each have their own interpreter — it "side-steps the Global Interpreter Lock"

The stdlib itself encodes this split in the default worker counts: ThreadPoolExecutor defaults to min(32, os.process_cpu_count() + 4) — more workers than cores, because they're expected to be waiting — while ProcessPoolExecutor defaults to exactly os.process_cpu_count(), one busy process per core.

The two-line swap

Both executors share the concurrent.futures interface, so fixing a wrong choice is often a one-word edit:

from concurrent.futures import ProcessPoolExecutor  # was ThreadPoolExecutor

with ProcessPoolExecutor() as pool:          # one process per core
    results = list(pool.map(hash_block, blocks))

Same submit(), same map(), same futures. The caveat: process pools pickle arguments and return values across process boundaries, so pass plain data (bytes, dicts, dataclasses), not open sockets or lambdas.

How to know which bound you're fighting

Don't guess — measure. Run the serial version once:

time.process_time() vs time.perf_counter() around the hot loop answers this in four lines. This is also the review question to ask when an assistant hands you threaded code: "what did the profiler say the bound was?"

Power-user notes

Resources

Building an AI feature? Yeda AI designs, audits, and ships production LLM systems.

Talk to us · Read the blog