- Mon Shot de Data Science
- Posts
- Qu'est-ce que GIL en Python ?
Qu'est-ce que GIL en Python ?
#102 - Mise à jour de Python 3.13
Python 3.13 est sorti récemment.
Parmi les nombreuses mises à jour intéressantes, celle qui permet de désactiver le GIL retient le plus l'attention. GIL pour Global Intepreter Locker (verrouillage de l'interpréteur global)
Cependant, avant même d'expliquer ce que cette mise à jour signifie, il est essentiel de comprendre ce qu'est le GIL en premier lieu et pourquoi Python l'a utilisé jusqu'à présent.
Plongeons donc dans le vif du sujet !
Sommaire
Quelques principes de base
Un processus est isolé des autres processus et fonctionne dans son propre espace mémoire. Cet isolement signifie que si un processus tombe en panne, cela n'affecte généralement pas les autres processus.
On parle de multi-threading lorsqu'un processus unique comporte plusieurs threads. Ces threads partagent les mêmes ressources, comme la mémoire.
GIL expliqué visuellement
En termes simples, le GIL (Global Interpreter Lock) empêche un processus d'exécuter plus d'UN thread à la fois, comme le montre la figure ci-dessous :
En d'autres termes, bien qu'un processus puisse avoir plusieurs threads, UN SEUL peut être exécuté à un moment donné.
De toute évidence, le processus ne peut pas utiliser plusieurs cœurs de processeur (CPU) pour optimiser les performances, ce qui signifie que le multi-threading conduit à des performances similaires (voire même médiocres) à celles du single-threading.
Laisse-moi te montrer cela rapidement avec une démonstration de code !
Tout d'abord, nous commençons par quelques importations et définissons une longue fonction :
Le code pour le single-threading, dans lequel nous invoquons la même fonction deux fois, est illustré ci-dessous :
Avec le multi-threading, cependant, nous pouvons créer deux threads, un pour chaque fonction. La démonstration en est faite ci-dessous :
Comme nous l'avons vu plus haut, les résultats sont à peine meilleurs que ceux obtenus avec le single-threading.
La raison ?
GIL.
D'ailleurs, comme on pouvait s'y attendre, le multi-processing permet d'améliorer le temps d'exécution :
Les trois scénarios ci-dessus (single-threading, multi-threading et multi-processing) peuvent être expliqués visuellement comme suit :
Single-threading : Un seul thread exécute la même fonction deux fois dans l'ordre.
Multi-threading : Chaque thread est chargé d'exécuter la fonction une fois. Toutefois, en raison de la GIL, un seul thread peut être exécuté à la fois :
Multi-processing : Chaque fonction est exécutée dans le cadre d'un processus différent :
Si cela est clair, il se peut que tu te poses maintenant deux questions :
1) Pourquoi Python utilise-t-il le GIL alors qu'il est clairement sous-optimale ?
Sécurité des threads.
Lorsque plusieurs threads s'exécutent dans un processus et partagent les mêmes ressources (telles que la mémoire), des problèmes peuvent survenir lorsqu'ils tentent d'accéder aux mêmes données et de les modifier.
Par exemple, considérons que nous avons une liste Python et que nous voulons exécuter deux opérations avec deux threads :
Si t1 s'exécute avant t2, nous obtenons le résultat suivant :
Si t2 s'exécute avant t1, nous obtenons le résultat suivant :
Des résultats différents !
Plus formellement, cela peut conduire à des conditions de course, où le résultat dépend de la synchronisation de l'exécution des threads.
Si ces conditions ne sont pas soigneusement contrôlées, elles peuvent conduire à un comportement imprévisible.
Pour cette raison, ainsi que pour d'autres, il est pratique d'imposer qu'un seul thread puisse s'exécuter à un moment donné.
Par ailleurs, le GIL affecte généralement les tâches liées au processeur et non les tâches liées aux I/O, pour lesquelles le multi-threading peut toujours être utile.
2) Si le multi-processing fonctionne, pourquoi ne pas l'utiliser comme solution de contournement ?
C'est plus facile à dire qu'à faire.
Contrairement aux threads, qui partagent le même espace mémoire, les processus sont isolés.
Par conséquent, ils ne peuvent pas partager directement des données comme le font les threads.
Bien qu'il existe des mécanismes de communication interprocessus (IPC pour Inter-Proces Communication) tels que les pipes, les files d'attente (queues) ou la mémoire partagée pour échanger des informations entre les processus, ils ajoutent une tonne de complexité.
Heureusement, Python 3.13 nous permet de désactiver le GIL, ce qui signifie qu'un processus peut utiliser pleinement tous les cœurs du processeur (CPU).
J'ai testé Python 3.13 dernièrement, j'ai donc l'intention de partager ces mises à jour dans un futur Shot de Data Science détaillé.
👉 À toi de jouer : Quelles sont les autres raisons d'appliquer le GIL en Python ?
Ça t'a plu ? 😎 |
Reply