logo

Què és GIL a Python? Bloqueig global d'intèrpret

Aquest tutorial se centrarà en un dels temes importants de Python, GIL. També tractarem com el GIL afecta el rendiment dels programes Python amb la implementació del codi. Abans d'endinsar-nos en aquest tema, tinguem una idea bàsica del GIL.

GIL o bloqueig global d'intèrpret

Python Global Interpreter Lock o GIL és una part important de la programació multithreading. És un tipus de bloqueig de procés que s'utilitza quan es treballa amb diversos processos. Dóna el control a un sol fil. En general, Python utilitza un sol fil per executar un sol procés. Obtenim el mateix resultat de rendiment dels processos d'un sol fil i de diversos fils mitjançant el GIL. Restringeix l'assoliment de fils múltiples a Python perquè impedeix els fils i funciona com un sol fil.

Nota: Python no admet multithreading perquè els paquets de threading no ens poden permetre utilitzar els múltiples nuclis de la CPU.

Per què els desenvolupadors de Python fan servir GIL?

Python proporciona la funció de comptador de referència única, que s'utilitza per a la gestió de la memòria. El comptador de referències compta el nombre total de referències fetes internament a Python per assignar un valor a un objecte de dades. Quan els recomptes de referència arriben a zero, s'allibera la memòria assignada de l'objecte. Vegem l'exemple següent.

Exemple -

reemplaça la cadena javascript
 import sys a = [] b = a sys.getrefcount(a) 

La principal preocupació de la variable de recompte de referència és que es pot veure afectada quan dos o tres fils intenten augmentar o disminuir el seu valor simultàniament. Es coneix com a condició de carrera. Si es produeix aquesta condició, es pot provocar una fuga de memòria que mai s'allibera. Pot fallar o fallar al programa Python.

GIL ens ajuda a eliminar aquesta situació utilitzant els bloquejos a totes les estructures de dades compartides a través dels fils perquè no es modifiquin de manera inconsistent. Python proporciona una manera senzilla d'implementar el GIL, ja que s'ocupa de la gestió de memòria segura per a fils. GIL requereix oferir un únic bloqueig a un fil per processar-lo a Python. Augmenta el rendiment d'un programa d'un sol fil, ja que només cal manejar un bloqueig. També ajuda a crear qualsevol programa vinculat a la CPU i evita la condició de bloqueig.

int a cadena java

L'impacte en els programes de Python multifils

Hi ha una diferència entre els límits de la CPU pel que fa al seu rendiment i l'enllaç d'E/S per a un programa típic de Python o qualsevol programa informàtic. Els programes vinculats a la CPU generalment empènyer la CPU als seus límits. Aquests programes s'utilitzen generalment per a càlculs matemàtics, com ara multiplicacions de matrius, searing, processament d'imatges, etc.

Els programes vinculats a E/S són aquells programes que dediquen temps a obtenir entrada/sortida que pot ser generada per l'usuari, fitxer, base de dades, xarxa, etc. Aquests programes han d'esperar una quantitat significativa de temps fins que la font proporcioni l'entrada. D'altra banda, la font també té el seu propi temps de processament. Per exemple, un usuari està pensant què introduir com a entrada.

Entenem l'exemple següent.

Exemple -

 import time from threading import Thread COUNT = 100000000 def countdown(num): while num>0: num -= 1 start_time = time.time() countdown(COUNT) end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Sortida:

 Time taken in seconds - 7.422671556472778 

Ara modifiquem el codi anterior executant els dos fils.

Exemple - 2:

 import time from threading import Thread COUNT = 100000000 def countdown(num): while num>0: num -= 1 thread1 = Thread(target=countdown, args=(COUNT//2,)) thread2 = Thread(target=countdown, args=(COUNT//2,)) start_time = time.time() thread1.start() thread2.start() thread1.join() thread2.join() end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Sortida:

 Time taken in seconds - 6.90830135345459 

Com podem veure, ambdós codis van trigar el mateix temps a acabar. GIL va impedir que els fils vinculats a la CPU s'executin en paral·lel al segon codi.

cadena per xerrar

Per què encara no s'ha eliminat el GIL?

Molts programadors tenen una queixa sobre això, però Python no pot aportar els canvis tan significatius com l'eliminació de GIL. Un altre motiu és que el GIL no s'ha millorat fins ara. Si canvia a Python 3, crearà alguns problemes greus. En lloc d'eliminar GIL, el concepte GIL pot millorar. Segons Guido van Rossom -

'Doncs la benvinguda a un conjunt de pedaços a Py3k només si el rendiment d'un programa d'un sol fil (i d'un programa multifil però vinculat a E/S) no disminueix'.

També hi ha molts mètodes disponibles que resolen el mateix problema resolt pel GIL, però són difícils d'implementar.

Com tractar amb el GIL de Python

L'ús del multiprocessament és la forma més adequada d'evitar que el programa des de GIL. Python ofereix diversos intèrprets per a cada procés que s'executa, de manera que en aquest escenari, el fil únic es proporciona a cada procés en multiprocessament. Entenem l'exemple següent.

Exemple -

obtenir la longitud de la matriu en c
 from multiprocessing import Pool import time COUNT = 50000000 def countdown(num): while num>0: num -= 1 if __name__ == '__main__': pool = Pool(processes=2) start_time = time.time() r1 = pool.apply_async(countdown, [COUNT//2]) r2 = pool.apply_async(countdown, [COUNT//2]) pool.close() pool.join() end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Sortida:

 Time taken in seconds - 3.3707828521728516 

Pot semblar que augmenta un rendiment decent, però la gestió de processos té les seves pròpies despeses generals i diversos processos són més pesats que diversos fils.

Conclusió

En aquest tutorial, hem parlat del GIL i com podem utilitzar-lo. Dóna el control a un sol fil per executar-se en el moment. Aquest tutorial també va explicar per què GIL és important per als programadors de Python.