Question presented to candidate:
"Now that CPython has a free-threaded build, threads can finally run Python code on several cores. Is there still a reason to reach for multiprocessing? How would you decide between processes and free-threaded threads for a CPU-heavy job?"
What a strong answer should cover:
- Version reality first: there is no free-threaded build in 3.12; it is experimental in 3.13 and supported but optional in 3.14. On the default build, CPU-bound pure-Python work still needs processes.
- What threads win on: no pickling, cheap start-up, shared objects by reference, low memory β best when tasks share large in-memory state or exchange data often.
- What processes still win on: they work on every build and with every C extension (one extension without free-threading support re-enables the GIL), they give memory isolation (no data races by default) and crash isolation (a segfault kills one worker, not the app), and the OS can kill or limit them.
- The costs of processes: pickling every argument and result, start-up time (especially
spawn), duplicated memory; mitigate with chunking,initializer, andshared_memory. - Measure: single-threaded slowdown of the free-threaded build, the size of data crossing the boundary, and real wall-clock time on the target machine.
Clarifying questions expected:
- Which Python version and build will production run, and do all compiled dependencies support free threading?
- How much state do the workers share, and how often do they exchange data?
Code / implementation expected: Optional β the same function run on a ThreadPoolExecutor and a ProcessPoolExecutor, with the trade-offs explained.