CodeGym /Cours Java /Python SELF FR /Contourner le GIL

Contourner le GIL

Python SELF FR
Niveau 26 , Leçon 4
Disponible

11.1 Global Interpreter Lock

Global Interpreter Lock (GIL) est un mécanisme dans l'interpréteur CPython qui garantit qu'un seul thread exécute le bytecode Python à la fois. Le GIL empêche l'exécution parallèle des threads, ce qui peut avoir un impact négatif sur les performances des programmes multi-threads, surtout sur les processeurs multi-cœurs.

Raisons de l'existence du GIL

Simplification de la gestion de la mémoire : le GIL simplifie la gestion de la mémoire et le garbage collection, rendant Python plus facile à implémenter.

Sécurité des threads : le GIL prévient les conditions de compétition, rendant l'exécution du code sécurisée pour les threads sans avoir besoin d'utiliser des verrous.

Problèmes causés par le GIL

Performances limitées : les programmes multi-threads effectuant des tâches intensives en calcul ne peuvent pas tirer pleinement parti des processeurs multi-cœurs à cause des limitations du GIL.

Détérioration des performances : les programmes qui utilisent intensivement les threads pour effectuer des tâches peuvent rencontrer une dégradation des performances à cause des basculements de contexte entre threads.

Actuellement, il y a 4 principales façons de « contourner le GIL » :

11.2 Utilisation du multiprocessus (multiprocessing)

Le module multiprocessing permet de créer des processus qui s'exécutent en parallèle et ne sont pas limités par le GIL, car chaque processus a son propre interpréteur Python et sa mémoire.

Exemple :


import multiprocessing

def worker(num):
    print(f'Worker: {num}')
            
def main():
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        processes.append(p)
        p.start()
            
    for p in processes:
        p.join()
            
main()

11.3 Programmation Asynchrone

La programmation asynchrone utilisant asyncio permet d'exécuter des tâches en parallèle sans bloquer le thread principal. Même si cela ne contourne pas le GIL au sens propre, cela permet d'utiliser efficacement le temps d'attente pour effectuer d'autres tâches.

Exemple :


import asyncio

async def main():
    await asyncio.sleep(1)
    print('Hello')
            
asyncio.run(main())

11.4 Utilisation de bibliothèques avec gestion des threads propre

Certaines bibliothèques, comme NumPy et SciPy, sont écrites en C et utilisent leurs propres mécanismes de gestion des threads, ce qui leur permet de contourner le GIL et d'utiliser efficacement les processeurs multi-cœurs pour les calculs.

En fait, c'est l'une des principales raisons du succès de Python, aussi lent soit-il. Tous les calculs complexes sont réécrits en C/C++ et exécutés sur tous les cœurs du processeur ou même directement sur les cœurs du GPU. Et sur les GPU modernes, il y a des milliers de cœurs.

Ainsi, il n'est plus important de savoir si le langage est rapide ou lent, tant que tous les calculs gourmands en ressources sont effectués par des bibliothèques externes ou complètement délocalisés dans des centres de données à distance.

11.5 Exécution de calculs hors de l'interpréteur Python

L'utilisation d'extensions en C/C++ ou d'autres langages qui peuvent effectuer des calculs hors de l'interpréteur Python puis retourner le résultat. Cela permet d'éviter le blocage du GIL pendant l'exécution de calculs intensifs.

Exemple d'utilisation de Cython :


# example.pyx

def compute(int n):
    cdef int i, result = 0
    for i in range(n):
        result += i
    return result

Compilation et utilisation :


cythonize -i example.pyx

import example
print(example.compute(1000000))
1
Опрос
Asynchronie,  26 уровень,  4 лекция
недоступен
Asynchronie
Asynchronie
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION