Perché Python è stato scritto con GIL?

104

Il global interpreter lock (GIL) sembra essere spesso citato come una delle principali ragioni per cui il threading e simili è un po 'complicato in Python - il che solleva la domanda "Perché è stato fatto in primo luogo?"

Non essere un programmatore, non ho idea di cosa possa essere - qual è stata la logica alla base della messa in GIL?

    
posta Fomite 13.02.2013 - 02:14
fonte

3 risposte

100

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

  • Dal link

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.

    
risposta data 13.02.2013 - 04:57
fonte
39

Primo: Python non ha un GIL. Python è un linguaggio di programmazione. Un linguaggio di programmazione è un insieme di regole matematiche astratte e restrizioni. Non c'è nulla nella specifica del linguaggio Python che dice che deve esserci un GIL.

Ci sono molte diverse implementazioni di Python. Alcuni hanno un GIL, altri no.

Una semplice spiegazione per avere un GIL è che scrivere codice concorrente è difficile. Inserendo un blocco gigante attorno al codice, lo costringi a eseguire sempre in serie. Problema risolto!

In CPython, in particolare, un obiettivo importante è quello di facilitare l'estensione dell'interprete con i plugin scritti in C. Ancora, scrivere codice concorrente è difficile, quindi garantendo che non ci sarà concorrenza, è più facile scrivere estensioni per l'interprete. Inoltre, molte di queste estensioni sono solo involucri sottili attorno alle librerie esistenti che potrebbero non essere state scritte con concomitanza in mente.

    
risposta data 13.02.2013 - 04:22
fonte
15

Qual è lo scopo di un GIL?

La documentazione CAPI ha questo da dire sull'argomento:

The Python interpreter is not fully thread-safe. In order to support multi-threaded Python programs, there’s a global lock, called the global interpreter lock or GIL, that must be held by the current thread before it can safely access Python objects. Without the lock, even the simplest operations could cause problems in a multi-threaded program: for example, when two threads simultaneously increment the reference count of the same object, the reference count could end up being incremented only once instead of twice.

In altre parole, il GIL impedisce la corruzione di stato. I programmi Python non dovrebbero mai produrre un errore di segmentazione, perché sono consentite solo le operazioni di sicurezza della memoria. Il GIL estende questa garanzia ai programmi multi-thread.

Quali sono le alternative?

Se lo scopo del GIL è quello di proteggere lo stato dalla corruzione, allora un'ovvia alternativa è il blocco di una grana molto più fine; forse a livello di oggetto. Il problema è che, sebbene sia stato dimostrato che aumenta le prestazioni dei programmi multi-thread, ha come conseguenza un maggior numero di overhead e di problemi con i programmi single-thread.

    
risposta data 13.02.2013 - 07:37
fonte

Leggi altre domande sui tag