A newsletter covering three separate topics: a visual explainer of combining RAG with Cache-Augmented Generation (CAG) using KV-memory caching and the CacheBlend technique from the open-source LMCache project; a deep dive into Python's Global Interpreter Lock (GIL), explaining why it exists, how it affects multi-threading versus multi-processing, and noting that Python 3.14 allows disabling the GIL for the first time; and an explainer of contrastive learning using Siamese networks illustrated through a face-unlock system example.

10m read timeFrom blog.dailydoseofds.com
Post cover image
Table of contents
​ RAG vs. CAG, explained visually! ​What is (was?) GIL in Python?​ What is Contrastive Learning? ​

Questions this post answers

What is the Global Interpreter Lock (GIL) in Python and why does it exist?

The GIL is a mechanism in Python that restricts a process to running only one thread at a time, preventing multiple CPU cores from being used simultaneously by threads in the same process. It exists mainly for thread safety, since threads share memory and running them concurrently without a lock can cause race conditions when multiple threads modify the same data, producing different results depending on execution order. Developers optimizing concurrent Python code can follow GIL-related changes and workarounds on daily.dev.

Can Python run without the GIL, and starting with which version?

Yes, Python 3.14 allows disabling the GIL for the first time, letting a process fully utilize all CPU cores for multi-threaded workloads. Before this, multi-threaded CPU-bound Python code performed similarly to single-threaded code because only one thread could execute at a time, and multi-processing was the common workaround despite the added complexity of inter-process communication. Teams planning to adopt free-threaded Python track version-specific changes like this via daily.dev.

Why doesn't multi-threading speed up CPU-bound Python code even with multiple threads?

Multi-threading does not speed up CPU-bound Python code because the GIL only lets one thread run at a time within a process, so multiple threads executing a CPU-bound function take roughly the same time as running them sequentially, for example 0.432 seconds single-threaded versus 0.428 seconds multi-threaded. Multi-processing avoids this since each process gets its own interpreter and GIL, allowing true parallel execution across CPU cores. Developers debugging slow multi-threaded Python performance can dig into concurrency explainers on daily.dev.

260 Impressions