Python GIL, Async vs Threads, and Multiplying Two 2 GB NumPy Matrices in 8 GB RAM
Company: Raiffeisenbank
Role: Machine Learning Engineer
Category: Software Engineering Fundamentals
Difficulty: hard
Interview Round: Technical Screen
Answer three Python questions from the same screen: what the GIL is and whether Python has parallelism, whether multiplying two 2 GB dense NumPy matrices fits in 8 GB of RAM and how the multiplication runs, and how asynchrony differs from multithreading.
### Clarifying Questions
- Is the question about CPython, and which version? Recent releases offer an optional build without the GIL.
- Should NumPy be assumed to be linked against an optimized, multithreaded BLAS library, as standard builds are?
### Part 1 — The GIL and parallelism in Python
What is the GIL, and is there real parallelism in Python?
```hint Who holds the lock
Ask which kinds of work keep the interpreter lock while they run and which kinds release it.
```
#### What This Part Should Cover
- What the GIL protects and why CPython has it
- The difference between CPU-bound and I/O-bound threads
- The ways to get real parallelism, and what each one costs
### Part 2 — Multiplying two 2 GB matrices with 8 GB of RAM
Two dense NumPy matrices of 2 GB each must be multiplied on a machine with 8 GB of RAM. Will the computation fit in memory, and how will it be executed?
```hint Size the output
The inputs are fixed at 2 GB each. Work out what determines the size of the result before deciding whether everything fits.
```
#### Clarifying Questions for this Part
- What are the shapes and the dtype of the two matrices?
- How much of the 8 GB is actually free, and is swap enabled?
#### What This Part Should Cover
- A memory estimate that includes the output and any temporary copies, as a function of the shapes
- What NumPy actually calls to multiply, and how that work is parallelized
- What to do when the product does not fit
### Part 3 — Asynchrony versus multithreading
What is the difference between asynchrony and multithreading, and when is each the better choice?
```hint Who decides when to switch
Compare who decides when one task pauses and another runs in each model.
```
#### What This Part Should Cover
- Cooperative scheduling on an event loop versus preemptive operating-system threads
- The costs of each: memory per task, races, library support
- Which workloads suit each, and how to combine them
### What a Strong Answer Covers
- Accurate mechanics of the GIL, including when it is released
- Correct matching of workload types to threads, processes or async code
- A memory estimate for the matrix product that accounts for the output and any temporary copies
- Knowledge of what NumPy delegates to BLAS and how that runs in parallel
- Concrete fallbacks when the data does not fit in memory
### Follow-up Questions
- Why does a CPU-bound pure-Python function run no faster on four threads, while a NumPy-heavy one can?
- How would you compute the product if the result itself needed 32 GB?
- What happens if a blocking call such as `time.sleep` runs inside an `async` function?
- What changes with the free-threaded CPython builds?
Overview: Three Python fundamentals questions for an AI engineer: what the GIL is and whether Python has real parallelism, whether multiplying two 2 GB dense NumPy matrices fits in 8 GB of RAM and how NumPy executes it, and how asyncio differs from multithreading and when to use each.
Read the full Raiffeisenbank Machine Learning Engineer interview experience this question came from