Esistono diverse implementazioni di Python, ad esempio, CPython, IronPython, RPython, ecc.
Alcuni di loro hanno un GIL, altri no. Ad esempio, CPython ha GIL:
Da link
Le applicazioni scritte in linguaggi di programmazione con un GIL possono essere progettate per utilizzare processi separati per raggiungere il pieno parallelismo, poiché ogni processo ha il proprio interprete e, a sua volta, ha il proprio GIL.
Vantaggi del GIL
- Maggiore velocità dei programmi a thread singolo.
- Facile integrazione delle librerie C che solitamente non sono thread-safe.
Perché Python (CPython e altri) usa GIL
In CPython, il blocco dell'interprete globale, o GIL, è un mutex che impedisce a più thread nativi di eseguire contemporaneamente bytecode Python. Questo blocco è necessario principalmente perché la gestione della memoria di CPython non è thread-safe.
Il GIL è controverso perché impedisce a programmi CPython multithread di sfruttare appieno i sistemi multiprocessore in determinate situazioni. Si noti che le operazioni potenzialmente bloccanti o di lunga durata, come I / O, elaborazione delle immagini e numerazione dei numeri di NumPy, si verificano all'esterno di GIL. Quindi è solo nei programmi multithread che passano molto tempo all'interno di GIL, interpretando il bytecode CPython, che il GIL diventa un collo di bottiglia.
Python ha un GIL anziché un blocco a grana fine per diversi motivi:
-
È più veloce nel caso a thread singolo.
-
È più veloce nel caso a più thread per i programmi di i / o associati.
-
È più veloce nel caso multithreading per i programmi legati alla cpu che eseguono il loro lavoro di elaborazione intensiva nelle librerie C.
-
Rende le estensioni C più facili da scrivere: non ci sarà alcun cambio di thread Python eccetto dove permetti che accada (cioè tra le macro Py_BEGIN_ALLOW_THREADS e Py_END_ALLOW_THREADS).
-
Rende più facili le wrapping delle librerie C. Non devi preoccuparti della sicurezza del thread. Se la libreria non è thread-safe, tieni semplicemente bloccato GIL mentre lo chiami.
Il GIL può essere rilasciato da estensioni C. La libreria standard di Python rilascia GIL attorno ad ogni chiamata i / o di blocco. Pertanto il GIL non ha alcuna conseguenza per le prestazioni dei server associati i / o. È quindi possibile creare server di rete in Python utilizzando processi (fork), thread o i / o asincroni e GIL non si intrometterà.
Anche le librerie numeriche in C o Fortran possono essere chiamate con il rilascio di GIL. Mentre l'estensione C è in attesa di completamento di un FFT, l'interprete eseguirà altri thread Python. In questo caso, un GIL è quindi più facile e veloce del blocco a grana fine. Questo costituisce la maggior parte del lavoro numerico. L'estensione NumPy rilascia il GIL quando possibile.
I thread di solito sono un brutto modo di scrivere la maggior parte dei programmi server. Se il carico è basso, la biforcazione è più facile. Se il carico è elevato, l'I / O asincrono e la programmazione basata su eventi (ad esempio usando il framework Twisted di Python) sono migliori. L'unica scusa per usare i thread è la mancanza di os.fork su Windows.
Il GIL è un problema se, e solo se, stai facendo un lavoro intensivo della CPU in puro Python. Qui puoi ottenere un design più pulito utilizzando i processi e il passaggio dei messaggi (ad es. Mpi4py). Esiste anche un modulo di 'elaborazione' nel negozio di formaggi Python, che fornisce ai processi la stessa interfaccia dei thread (cioè sostituisci il threading.Thread con processing.Process).
I thread possono essere utilizzati per mantenere la reattività di una GUI indipendentemente dal GIL. Se il GIL altera le tue prestazioni (vedi la discussione sopra), puoi lasciare che il tuo thread spawn un processo e aspettare che finisca.