Depuis que la plupart d'entre nous écrivons du Python, un fait a façonné notre manière de construire des programmes concurrents : le Global Interpreter Lock. Le GIL explique pourquoi les threads Python pour les tâches CPU-bound n'ont jamais offert de vrai parallélisme, pourquoi « utiliser multiprocessing » est devenu un réflexe, et pourquoi « Python est lent pour le travail parallèle » est devenu une idée reçue. Le Python sans GIL change la donne. Ce guide explique ce qu'est réellement le GIL, ce que sa suppression apporte et n'apporte pas, où elle aide, où elle pénalise, et comment envisager son adoption sans céder au battage médiatique dans un sens ou dans l'autre.
Ce que vous allez vraiment comprendre
- Ce qu'est le GIL et pourquoi il a existé si longtemps
- Ce que le Python « free-threaded » change: et ce qu'il ne change pas
- Les compromis honnêtes : coût en single-thread et compatibilité des extensions C
- Quand le free threading est un vrai gain par rapport à async ou multiprocessing
- Une approche pragmatique pour l'évaluer sur vos propres charges de travail
Info
La réponse courte
Le GIL disparaît: en tant que version optionnelle officiellement supportée, pas comme nouveau défaut silencieux pour tout le monde du jour au lendemain. Le Python free-threaded est réel et pris en charge, mais c'est un choix délibéré avec des compromis, pas une accélération gratuite qu'on active partout sans réflexion.
Ce qu'est réellement le GIL
Le Global Interpreter Lock est un verrou unique à l'intérieur de CPython qui garantit qu'un seul thread exécute du bytecode Python à la fois. Il existe parce qu'il rendait l'interpréteur plus simple et plus rapide pour le code single-thread et qu'il gardait la gestion mémoire (comptage de références) sûre sans parsemer de verrous partout. Le prix à payer : les threads ne peuvent pas exécuter du code Python véritablement en parallèle. Deux threads effectuant un calcul lourd se passent le relais au lieu de tourner côte à côte, donc vous obtenez de la concurrence mais pas de parallélisme avec les threads.
With the GIL (CPU-bound work, 4 threads, 4 cores):
Thread 1 ▓░░░▓░░░▓░░░ ← only one runs Python at a time
Thread 2 ░▓░░░▓░░░▓░░ they take turns; 3 cores sit idle
Thread 3 ░░▓░░░▓░░░▓
Thread 4 ░░░▓░░░▓░░░
Free-threaded (no GIL):
Thread 1 ▓▓▓▓▓▓▓▓▓▓▓▓ ← all four run in parallel
Thread 2 ▓▓▓▓▓▓▓▓▓▓▓▓
Thread 3 ▓▓▓▓▓▓▓▓▓▓▓▓ real use of all cores
Thread 4 ▓▓▓▓▓▓▓▓▓▓▓▓
Ce que le free threading change
Dans une version free-threaded, le GIL est supprimé, donc plusieurs threads peuvent exécuter du bytecode Python simultanément sur plusieurs cœurs. Pour le travail CPU-bound que vous pouvez répartir entre threads, c'est le déblocage tant attendu : un vrai parallélisme à mémoire partagée sans la surcharge et la lourdeur de lancer des processus séparés et de sérialiser les données entre eux. Un seul processus, des objets partagés, tous vos cœurs.
Considérez une tâche CPU embarrassingly parallel. Avec la version standard, la paralléliser avec des threads ne vous apporte presque rien: le GIL sérialise le travail. Le même code sur la version free-threaded passe à l'échelle sur les cœurs :
import sys
from concurrent.futures import ThreadPoolExecutor
def crunch(n: int) -> int: # pure CPU work — no I/O to hide behind
total = 0
for i in range(n):
total += i * i
return total
def run() -> None:
with ThreadPoolExecutor(max_workers=8) as pool:
list(pool.map(crunch, [20_000_000] * 8))
# Tell which world you're in at runtime:
print("GIL enabled:", sys._is_gil_enabled()) # True on standard build, False on 3.14t
run()
# Standard build: threads take turns — wall time ~= running all 8 tasks serially.
python3.14 bench.py # GIL enabled: True
# Free-threaded build: threads run in parallel — wall time ~= one task (on 8 cores).
python3.14t bench.py # GIL enabled: False ← the 't' build is the no-GIL one
PYTHON_GIL=0 python3.14t bench.py # force the GIL off if an extension re-enabled it
Ce que cela NE change PAS
Le free threading n'est pas un bouton magique « rendre Python rapide », et plusieurs espoirs courants sont mal placés.
✓ Avantages
- Vrai parallélisme pour les charges CPU-bound parallélisables par threads
- Mémoire partagée: pas de sérialisation des données entre processus
- Surcharge plus faible que multiprocessing pour le calcul sur nombreux cœurs
✕ Inconvénients
- Le code I/O-bound passait déjà bien à l'échelle avec threads/async: peu de gain ici
- Les programmes single-thread peuvent tourner un peu plus lentement, pas plus vite
- Cela n'accélère pas le code séquentiel ; seul le travail parallélisable en bénéficie
- Cela réintroduit les classiques data races: l'état partagé nécessite désormais une vraie attention
Avertissement
Sans GIL, la sécurité des threads vous incombe à nouveau
Le GIL protégeait accidentellement beaucoup de code bâclé manipulant un état partagé. Sans lui, deux threads qui modifient le même objet s'exécutent vraiment en même temps, donc des conditions de concurrence auparavant masquées peuvent apparaître. Le code free-threaded exige la même discipline de verrouillage que n'importe quel autre langage véritablement parallèle. C'est une fonctionnalité qui vient avec des responsabilités.
Voici le genre de bogue que le GIL cachait. Deux threads qui incrémentent un compteur partagé effectuent une lecture-modification-écriture qui peut s'entrelacer, donc des incréments sont perdus: et la correction est la même que dans tout langage parallèle : protégez l'état mutable partagé avec un verrou.
import threading
# ❌ Racy without the GIL: counter += 1 is read, add, write — and can interleave.
counter = 0
def unsafe():
global counter
for _ in range(1_000_000):
counter += 1 # two threads can both read the same value → lost updates
# ✅ Correct: a lock makes the update atomic.
counter = 0
lock = threading.Lock()
def safe():
global counter
for _ in range(1_000_000):
with lock:
counter += 1 # only one thread mutates at a time
# Better still: avoid shared mutable state. Have each thread return its own
# partial result and combine them at the end — no lock, no contention.
Les deux coûts honnêtes
1. Surcharge en single-thread
Supprimer le GIL nécessite des changements dans la gestion mémoire qui peuvent rendre le code single-thread un peu plus lent qu'avec la version standard. Si votre programme est principalement séquentiel, la version free-threaded risque de vous coûter des performances au lieu de vous en faire gagner. Le pari n'est gagnant que lorsque vous parallélisez véritablement du travail CPU sur plusieurs threads.
2. Compatibilité des extensions C
Une énorme partie de la valeur de Python réside dans les extensions C: la pile scientifique, les pilotes de base de données, les analyseurs syntaxiques. Beaucoup supposent que le GIL existe et ont besoin de mises à jour pour être sûres et correctes sans lui. L'écosystème migre activement, mais vous ne pouvez pas supposer qu'une extension arbitraire est prête pour le free threading. Cette courbe de compatibilité, plus que tout, détermine la vitesse à laquelle le monde sans GIL devient pratique pour les applications courantes.
Choisir le bon outil de concurrence
Le free threading ne remplace pas les autres outils: il comble un manque spécifique. Adaptez l'outil au goulot d'étranglement.
I/O-bound (réseau, disque, appels DB) ?
Utilisez async ou des threads classiques. Le GIL n'a jamais été votre problème ici ; vous attendez, vous ne calculez pas. Le free threading n'apporte pas grand-chose.
CPU-bound et parallélisable ?
C'est le terrain de prédilection du free threading: et auparavant celui de multiprocessing. Le free threading peut le faire avec de la mémoire partagée et moins de surcharge, une fois que vos extensions le supportent.
Code CPU-bound mais extensions pas prêtes ?
Restez pour l’instant sur le multiprocessing. L’isolation par processus contourne le GIL à l’ancienne et reste une solution parfaitement valable.
Application majoritairement monothread ?
Gardez la version standard. La version sans GIL risquerait de dégrader les performances monothread sans apporter de gain parallèle.
tous vos cœurs: la promesse de Python sans GIL pour le calcul CPU parallèle
Comment l’évaluer concrètement
N’adoptez pas le mode sans GIL par principe ou par crainte. Mesurez. Déployez la version sans GIL dans un environnement de test, exécutez votre vraie charge CPU et comparez le temps réel et la justesse des résultats avec la version standard et votre approche multiprocessing actuelle. Surtout, vérifiez que chaque extension C dont vous dépendez est compatible avec le mode sans GIL avant d’envisager la production.
Astuce
Ajoutez l’interpréteur sans GIL comme cible CI parallèle. Exécuter votre suite de tests sur les deux versions fait remonter automatiquement les incompatibilités d’extensions et les nouvelles conditions de concurrence, transformant la question « notre code est-il sûr sans GIL ? » en un simple voyant vert ou rouge.
Alors, le GIL disparaît-il vraiment ?
Oui: mais il faut en comprendre la portée. Le GIL a disparu dans une version officiellement prise en charge, ce qui constitue un véritable tournant historique et le socle du futur parallèle de Python. Dans la version 3.14, ce n’est pas le mode par défaut hérité silencieusement par tout le monde, car le coût en monothread et la migration des extensions C rendent ce changement prématuré. Pour le dire honnêtement : l’époque où « Python ne peut pas faire de vrai parallélisme » touche à sa fin, progressivement, et le rythme dépend plus de l’adaptation de l’écosystème que du langage lui-même.
! Erreurs fréquentes à éviter
-
✕S’attendre à ce que la version sans GIL accélère le code lié aux entrées-sorties.
✓Le GIL n’a jamais été le goulot d’étranglement dans ce cas: utilisez l’asynchrone ou les threads ; le mode sans GIL aide pour le travail CPU.
-
✕Supposer que le code threadé existant est automatiquement sûr sans le GIL.
✓Des conditions de concurrence masquées par le GIL peuvent désormais apparaître: protégez l’état mutable partagé avec des verrous.
-
✕Adopter le mode sans GIL par principe, sans mesurer.
✓Comparez votre charge réelle avec la version standard et le multiprocessing avant de vous engager.
-
✕Ignorer la compatibilité des extensions C.
✓Vérifiez que chaque dépendance native prend en charge le mode sans GIL ; beaucoup supposent encore la présence du GIL.
? Questions fréquentes
Qu’est-ce que le GIL en termes simples ? +
Un verrou unique dans CPython qui ne laisse qu’un seul thread exécuter du bytecode Python à la fois. Il simplifiait l’interpréteur et la gestion mémoire, mais empêchait les threads d’exécuter du code Python véritablement en parallèle.
Supprimer le GIL rend-il Python plus rapide ? +
Uniquement pour le travail CPU que vous pouvez répartir sur plusieurs threads. Le code monothread peut même s’exécuter un peu plus lentement avec la version sans GIL, ce n’est donc pas une accélération universelle.
Dois-je utiliser des threads, de l’asynchrone ou du multiprocessing maintenant ? +
Asynchrone/threads pour les entrées-sorties, mode sans GIL pour le calcul CPU parallèle (une fois les extensions compatibles), multiprocessing si vos extensions ne sont pas encore prêtes, et la version standard pour les applications majoritairement monothread.
Python sans GIL est-il prêt pour la production ? +
Il est officiellement pris en charge, mais l’adoption est conditionnée par la compatibilité des extensions C et le coût en monothread. Évaluez-le délibérément pour les charges parallèles plutôt que de l’activer partout.
Comment savoir quelle version j’exécute ? +
Vérifiez sys._is_gil_enabled() à l’exécution, ou lancez l’interpréteur sans GIL (par exemple python3.14t). La version sans GIL indique que le GIL est désactivé.
Succès
Un fondement, pas une ligne d’arrivée
Python sans GIL ouvre une porte qui était verrouillée depuis trente ans. Franchissez-la avec méthode: mesurez votre charge, vérifiez vos dépendances et respectez la sécurité des threads: et vous obtiendrez un vrai parallélisme multi-cœur en Python pur. Cela mérite d’être bien fait plutôt que précipité.
Entraînez-vous en mobilité
Apprenez Python, l’application Android gratuite
Chaque sujet de cette série est aussi dans l’application : leçons courtes, exemples exécutables, quiz, mini-projets et un environnement Python hors ligne qui fonctionne sur votre téléphone.
Commentaires
0Aucun commentaire pour l’instant. Soyez la première personne à donner votre avis.