Nota: ovunque io menzioni thread
intendo specificamente i thread in Python fino a quando non viene dichiarato esplicitamente.
I thread funzionano in modo leggermente diverso in Python se provieni dallo C/C++
sfondo. In python, solo un thread può essere in esecuzione in un dato momento. Ciò significa che i thread in python non possono davvero sfruttare la potenza di più core di elaborazione poiché per progettazione non è possibile che i thread vengano eseguiti parallelamente su più core.
Poiché la gestione della memoria in python non è thread-safe, ogni thread richiede un accesso esclusivo alle strutture dati nell'interprete python.Questo accesso esclusivo viene acquisito da un meccanismo chiamato (global interpretr lock) .GIL
Why does python use GIL?
Per evitare che più thread accedano allo stato dell'interprete contemporaneamente e danneggino lo stato dell'interprete.
L'idea è che ogni volta che un thread viene eseguito (anche se è il thread principale) , viene acquisito un GIL e dopo un intervallo di tempo predefinito il GIL viene rilasciato dal thread corrente e riacquistato da qualche altro thread (se presente).
Why not simply remove GIL?
Non è che sia impossibile rimuovere GIL, è solo che nel processo di farlo finiamo per mettere più blocchi all'interno dell'interprete per serializzare l'accesso, il che rende meno performante anche una singola applicazione con thread.
quindi il costo della rimozione di GIL viene ripagato dalla riduzione delle prestazioni di una singola applicazione thread, che non è mai desiderata.
So when does thread switching occurs in python?
Il cambio di thread si verifica quando viene rilasciato GIL. Quindi, quando viene rilasciato GIL? Ci sono due scenari da prendere in considerazione.
Se un thread sta eseguendo operazioni di CPU Bound (elaborazione immagine Ex).
Nelle versioni precedenti di python, il cambio di thread si verificava dopo un numero fisso di istruzioni python ed era impostato di default su 100
. Si è scoperto che non è una buona politica per decidere quando il passaggio dovrebbe avvenire dato il tempo impiegato per eseguire una singola istruzione può molto selvaggiamente da millisecondi a anche un secondo. Pertanto, il rilascio di GIL dopo ogni 100
istruzione indipendentemente dal tempo necessario per l'esecuzione è una cattiva politica.
Nelle nuove versioni invece di utilizzare il conteggio delle istruzioni come metrica per cambiare thread, viene utilizzato un intervallo di tempo configurabile. L'intervallo di commutazione predefinito è 5 millisecondi. È possibile ottenere l'intervallo di commutazione corrente utilizzando sys.getswitchinterval()
. Questo può essere modificato usandosys.setswitchinterval()
Se un thread sta eseguendo alcune operazioni di I / O (accesso al file system Ex o I /
O di rete)
GIL viene rilasciato ogni volta che il thread attende il completamento di un'operazione di I / O.
Which thread to switch to next?
L'interprete non ha un proprio scheduler. Il thread che viene pianificato alla fine dell'intervallo è una decisione del sistema operativo. .