miniatura|250x250px|Representació esquemàtica de com funcionen els fils sota GIL. Verd: fil que conté GIL, vermell: fils bloquejats Un bloqueig d'intèrpret global (GIL) és un mecanisme utilitzat en els intèrprets de llenguatges informàtics per sincronitzar l'execució de fils de treball de manera que només un fil natiu (per procés) pugui executar operacions bàsiques (com ara l'assignació de memòria i el recompte de referències) alhora. Com a regla general, un intèrpret que utilitza GIL només veurà un fil per executar alhora, fins i tot si s'executa en un processador multinucli, tot i que algunes implementacions permeten que el codi que utilitza molta CPU alliberi el GIL, permetent que diversos fils utilitzin diversos nuclis. Alguns intèrprets populars que tenen un GIL són CPython i Ruby MRI.
Conceptes tècnics de base Un bloqueig d'intèrpret global (GIL) és un bloqueig d'exclusió mútua que manté un fil d'intèrpret de llenguatge de programació per evitar compartir codi que no és segur per a fils amb altres fils. En implementacions amb un GIL, sempre hi ha un GIL per a cada procés d'intèrpret.
Les aplicacions que s'executen en implementacions amb una GIL es poden dissenyar per utilitzar processos separats per aconseguir un paral·lelisme complet, ja que cada procés té el seu propi intèrpret i, al seu torn, el seu propi GIL. En cas contrari, la GIL pot ser una barrera important per al paral·lelisme.
Història i evolució El bloqueig d'intèrpret global forma part de la implementació de CPython des de les primeres versions del llenguatge Python. La seva incorporació responia a la necessitat de simplificar la gestió de memòria mitjançant el sistema de recompte de referències utilitzat per l'intèrpret.
Durant les dècades de 1990 i 2000, quan la majoria d'ordinadors personals disposaven d'un únic nucli de processament, les limitacions del GIL tenien un impacte relativament reduït. Amb la popularització dels processadors multinúcli, però, la comunitat de desenvolupadors va començar a qüestionar la seva conveniència, ja que impedia aprofitar plenament el paral·lelisme mitjançant fils dins d'un mateix procés.
Diverses propostes per eliminar o substituir el GIL han estat presentades al llarg dels anys. Alguns intents experimentals van aconseguir eliminar-lo, però sovint provocaven una disminució significativa del rendiment dels programes monofil o dificultaven la compatibilitat amb extensions escrites en llenguatge C.
Com a conseqüència, la majoria de versions de CPython han mantingut aquest mecanisme, mentre que altres implementacions de Python, com Jython o IronPython, han optat per estratègies diferents de gestió de concurrència.
Avantatges Els motius per utilitzar un bloqueig d'intèrpret global inclouen:
augment de la velocitat dels programes d'un sol fil (no cal adquirir o alliberar bloquejos en totes les estructures de dades per separat), integració fàcil de biblioteques C que normalment no són segures per a fils, facilitat d'implementació (tenir un únic GIL és molt més senzill d'implementar que un intèrpret sense bloqueig o un que utilitza bloqueigs precisos).
Una manera d'evitar una GIL és crear un intèrpret separat per fil, cosa que és massa cara amb la majoria d'idiomes.
Inconvenients L'ús d'un bloqueig d'intèrpret global en un llenguatge limita eficaçment la quantitat de paral·lelisme assolible mitjançant la concurrència d'un únic procés d'intèrpret amb diversos fils. Si el procés està format gairebé completament per codi interpretat i no fa crides fora de l'intèrpret que es bloquegin durant llargs períodes (permetent que aquest fil alliberi la GIL mentre processa), és probable que hi hagi molt poc augment de velocitat quan s'executa el procés en una màquina multiprocessador. A causa de la senyalització amb un fil vinculat a la CPU, pot causar una desacceleració significativa, fins i tot en processadors individuals. Més greu encara, quan el fil natiu únic crida un procés del sistema operatiu que bloqueja (com ara l'accés al disc), tot el procés es bloqueja, fins i tot si altres fils d'aplicació poden estar esperant.
Comparació amb altres implementacions de Phyton La presència del bloqueig d'intèrpret global no és una característica inherent al llenguatge Python, sinó una decisió d'implementació adoptada principalment per CPython. Altres implementacions del llenguatge han desenvolupat estratègies diferents per gestionar la concurrència i l'execució paral·lela. Jython, una implementació de Python basada en la Java Virtual Machine (JVM), no incorpora un bloqueig d'intèrpret global. Com que aprofita el model de fils de Java, permet l'execució simultània de diversos fils sobre diferents nuclis del processador.
De manera similar, IronPython, desenvolupat sobre la plataforma .NET, utilitza els mecanismes de concurrència proporcionats pel Common Language Runtime (CLR) i tampoc depèn d'un GIL per protegir les estructures internes de l'intèrpret.
PyPy, una altra implementació popular de Python, ha mantingut tradicionalment un mecanisme equivalent al GIL per motius de compatibilitat i rendiment. No obstant això, al llarg dels anys s'han desenvolupat diverses línies de recerca orientades a reduir-ne les limitacions o a facilitar models alternatius d'execució concurrent
Aquestes diferències han convertit el bloqueig d'intèrpret global en un dels principals elements distintius entre les diverses implementacions de Python, especialment en entorns que requereixen elevats nivells de paral·lelisme.
Desenvolupaments recents Durant la dècada de 2020 s'han impulsat diverses iniciatives destinades a millorar les capacitats de concurrència de CPython. Entre aquestes destaca la proposta PEP 684, aprovada l'any 2022, que introdueix un bloqueig d'intèrpret independent per a cada subintèrpret. Aquesta aproximació permet reduir algunes de les limitacions tradicionals associades al GIL sense modificar completament el model de gestió de memòria existent.
Posteriorment, l'any 2023, el Consell Directiu de Python va acceptar la proposta PEP 703, titulada ''Making the Global Interpreter Lock Optional in CPython''. Aquesta proposta estableix un pla progressiu per permetre compilacions opcionals de CPython sense bloqueig d'intèrpret global.
L'objectiu principal del PEP 703 és facilitar l'execució paral·lela de fils en processadors multinúcli mantenint, al mateix temps, un alt grau de compatibilitat amb l'ecosistema existent de biblioteques i extensions desenvolupades per a CPython.
Les primeres implementacions experimentals d'aquest model es van incorporar a Python 3.13. Aquestes versions permeten compilar l'intèrpret en un mode conegut com a ''free-threaded'', en què els fils poden executar codi Python simultàniament sense dependre d'un bloqueig global compartit.
La documentació oficial de Python indica que aquesta funcionalitat continua en fase d'evolució i que la seva adopció generalitzada dependrà de l'adaptació progressiva de nombroses biblioteques externes. Per aquest motiu, les versions estàndard de CPython continuen utilitzant el bloqueig d'intèrpret global com a mecanisme predeterminat.
Debat sobre la seva eliminació El GIL (sigles de Bloqueig d'interprèt global en anglès) ha estat objecte de debat recurrent dins de la comunitat Python. Els seus defensors argumenten que contribueix a la simplicitat de l'intèrpret, redueix la complexitat del desenvolupament i permet mantenir un elevat rendiment en aplicacions monofil.
Els seus detractors, en canvi, consideren que representa una limitació important per a determinades aplicacions científiques, d'anàlisi de dades i d'intel·ligència artificial, especialment en entorns amb múltiples nuclis de processament.
L'any 2023 el Consell Directiu de Python va acceptar la proposta PEP 703 (Making the Global Interpreter Lock Optional in CPython), presentada per Sam Gross. Aquesta proposta estableix les bases perquè futures versions de CPython puguin funcionar opcionalment sense GIL.
Les primeres implementacions experimentals van arribar amb Python 3.13, on es permet compilar l'intèrpret sense aquest mecanisme. Tot i això, la versió estàndard continua utilitzant el GIL mentre es completa l'adaptació de nombroses biblioteques i extensions de tercers.
L'acceptació del PEP 703 és considerada per diversos analistes com una de les modificacions més importants en l'arquitectura interna de Python des de la introducció de Python 3.
Exemples Algunes implementacions de llenguatges que implementen un bloqueig d'intèrpret global són CPython, la implementació més utilitzada de Python, i Ruby MRI, la implementació de referència de Ruby (on s'anomena Global VM Lock).
Els equivalents basats en JVM d'aquests llenguatges (Jython i JRuby) no utilitzen bloquejos d'intèrpret globals. IronPython i IronRuby s'implementen sobre el Dynamic Language Runtime de Microsoft i també eviten l'ús d'una GIL.
Un exemple d'un llenguatge interpretat sense GIL és Tcl, que s'utilitza a l'eina de benchmarking HammerDB.
Codi d'exemple Exemple de codi en Python. Observeu com s'adquireix i s'allibera un bloqueig entre cada crida d'instrucció. Utilitza el l'objecte des del mòdul.from threading import Lock
INSTRUCTION_TABLE = { ... }
def execute(bytecode: list) -> None: """Execute bytecode.""" lock = Lock() for (opcode, args) in bytecode: lock.acquire() INSTRUCTION_TABLE[opcode](args) lock.release()
Funcionament i gestió de memòria L'existència del bloqueig d'intèrpret global a la implementació de CPython respon a la necessitat de garantir la integritat del mecanisme de comptatge de referències. Atès que Python gestiona la memòria incrementant o disminuint un comptador per a cada objecte, l'accés simultani de diversos fils a aquests comptadors podria derivar en condicions de cursa, provocant corrupció de dades o fuites de memòria (memory leaks). El GIL simplifica la implementació de l'intèrpret i facilita la coexistència amb extensions escrites en C que no són segures per a fils (thread-safe).
Impacte en el rendiment concurrent L'efecte del GIL sobre el rendiment depèn directament de la naturalesa de la càrrega de treball: Tasques limitades per la CPU (CPU-bound): En operacions que requereixen un ús intensiu del processador, com ara càlculs matemàtics o processament de dades, el GIL impedeix que el multithreading ofereixi millores de velocitat. En aquests casos, la competició dels fils per adquirir el bloqueig genera una sobrecàrrega (overhead) que pot fer l'execució més lenta que en un sistema d'un sol fil. Per a aquests escenaris, la solució òptima és el multiprocessament (multiprocessing), on cada procés té el seu propi intèrpret i GIL independent.
Tasques limitades per l'entrada/sortida (I/O-bound): En operacions de xarxa o lectura de disc, el GIL s'allibera automàticament mentre s'espera la resposta del sistema operatiu. Això permet que altres corrutines o fils s'executin simultàniament, optimitzant l'ús dels recursos mitjançant biblioteques com asyncio.
Vegeu també CPython
Referències
Categoria:Python Categoria:Programació