Python-stöd för fri trådning¶
Från och med version 3.13 har CPython stöd för en version av Python som kallas free threading där global interpreter lock (GIL) är inaktiverat. Fri trådning gör att den tillgängliga processorkraften kan utnyttjas fullt ut genom att trådar körs parallellt på tillgängliga processorkärnor. Även om inte all programvara kan dra nytta av detta automatiskt, kommer program som utformats med trådning i åtanke att köras snabbare på flerkärnig maskinvara.
Det fritt trådade läget fungerar och fortsätter att förbättras, men det finns en del ytterligare overhead i enkeltrådade arbetsbelastningar jämfört med den vanliga byggningen. Dessutom kan tredjepartspaket, i synnerhet sådana med en extension module, kanske inte vara klara för användning i en fritt trådad byggnation, och kommer att återaktivera GIL.
Detta dokument beskriver konsekvenserna av fri trådning för Python-kod. Se Stöd för fri trådning i C API-tillägg för information om hur man skriver C-tillägg som stöder den frittrådade byggnaden.
Se även
PEP 703 - Making the Global Interpreter Lock Optional in CPython för en övergripande beskrivning av Python med fri trådning.
Installation¶
Från och med Python 3.13 stöder de officiella installationsprogrammen för macOS och Windows valfritt installation av Python-binärfiler med fri tråd. Installatörerna finns tillgängliga på https://www.python.org/downloads/.
För information om andra plattformar, se Installing a Free-Threaded Python, en gemenskapsunderhållen installationsguide för installation av Free-Threaded Python.
När CPython byggs från källkod bör konfigurationsalternativet --disable-gil
användas för att bygga en Python-tolk med fri tråd.
Identifiera fritt trådade Python¶
För att kontrollera om den aktuella tolken stöder free-threading, innehåller python -VV
och sys.version
”free-threading build”. Den nya funktionen sys._is_gil_enabled()
kan användas för att kontrollera om GIL faktiskt är inaktiverad i den process som körs.
Konfigurationsvariabeln sysconfig.get_config_var("Py_GIL_DISABLED")
kan användas för att avgöra om build har stöd för fri trådning. Om variabeln är inställd på 1
har byggnaden stöd för fri trådning. Detta är den rekommenderade mekanismen för beslut relaterade till build-konfigurationen.
Det globala tolklåset i Python med fri trådning¶
Free-threaded-versioner av CPython stöder valfri körning med GIL aktiverad vid körning med hjälp av miljövariabeln PYTHON_GIL
eller kommandoradsalternativet -X gil
.
GIL kan också aktiveras automatiskt vid import av en C-API-tilläggsmodul som inte uttryckligen är markerad som stödjande fri trådning. En varning kommer att skrivas ut i detta fall.
Förutom dokumentationen för de enskilda paketen finns följande webbplatser där man kan följa statusen för populära paket som stöder fri trådning:
Tråd säkerhet¶
Den fritt trådade versionen av CPython syftar till att ge liknande trådsäkerhetsbeteende på Python-nivå som den standardiserade GIL-aktiverade versionen. Inbyggda typer som dict
, list
och set
använder interna lås för att skydda mot samtidiga ändringar på sätt som beter sig på liknande sätt som GIL. Python har dock inte historiskt garanterat ett specifikt beteende för samtidiga modifieringar av dessa inbyggda typer, så detta bör behandlas som en beskrivning av den nuvarande implementationen, inte en garanti för nuvarande eller framtida beteende.
Anteckning
Det rekommenderas att använda threading.Lock
eller andra synkroniseringsprimitiver istället för att förlita sig på de inbyggda typernas interna lås, när det är möjligt.
Kända begränsningar¶
I det här avsnittet beskrivs kända begränsningar för den fritt trådade CPython-versionen.
Odödliggörande¶
Den fritt trådade versionen av 3.13-versionen gör vissa objekt immortal. Odödliga objekt avallokeras inte och har referensvärden som aldrig ändras. Detta görs för att undvika konflikter om referensantal som skulle förhindra effektiv skalning med flera trådar.
Ett objekt blir odödligt när en ny tråd startas för första gången efter att huvudtråden är igång. Följande objekt är odödliga:
funktion objekt som deklareras på modulnivå
metod deskriptorer
code-objekt
module-objekt och deras ordlistor
classes (typobjekt)
Eftersom odödliga objekt aldrig avallokeras kan applikationer som skapar många objekt av dessa typer få ökad minnesanvändning. Detta förväntas vara åtgärdat i version 3.14.
Dessutom blir numeriska och stränglitteraler i koden samt strängar som returneras av sys.intern()
också odödliga. Detta beteende förväntas finnas kvar i den frittrådade versionen av 3.14.
Ramobjekt¶
Det är inte säkert att komma åt frame-objekt från andra trådar och det kan leda till att ditt program kraschar . Detta innebär att sys._current_frames()
i allmänhet inte är säker att använda i en fri-trådad konstruktion. Funktioner som inspect.currentframe()
och sys._getframe()
är i allmänhet säkra så länge som det resulterande ramobjektet inte skickas till en annan tråd.
Iteratorer¶
Att dela samma iteratorobjekt mellan flera trådar är i allmänhet inte säkert och trådarna kan se duplicerade eller saknade element när de itererar eller krascha tolken.
Prestanda med en tråd¶
Den fritt trådade versionen har ytterligare overhead när Python-kod exekveras jämfört med den standardiserade GIL-aktiverade versionen. I 3.13 är denna overhead cirka 40% on i pyperformance-sviten. Program som tillbringar den mesta av sin tid i C-tillägg eller I/O kommer att se mindre av en inverkan. Den största påverkan beror på att den specialiserade adaptiva tolken (PEP 659) är inaktiverad i den frittrådade versionen. Vi räknar med att återaktivera den på ett trådsäkert sätt i 3.14-utgåvan. Denna overhead förväntas minska i kommande Python-versioner. Vi siktar på en overhead på 10% or mindre på pyperformance-sviten jämfört med standard GIL-aktiverad byggnad.
Förändringar i beteendet¶
I det här avsnittet beskrivs CPythons beteendeförändringar med den fritt trådade versionen.
Variabler i sammanhanget¶
I den fritt trådade byggnaden är flaggan thread_inherit_context
som standard satt till true vilket gör att trådar som skapas med threading.Thread
startar med en kopia av Context()
för anroparen av start()
. I standardversionen med GIL-aktivering är flaggan som standard false så att trådar startar med en tom Context()
.
Varningsfilter¶
I den fritt trådade versionen är flaggan context_aware_warnings
satt till true som standard. I standardversionen med GIL-aktivering är flaggan som standard false. Om flaggan är true använder kontexthanteraren warnings.catch_warnings
en kontextvariabel för varningsfilter. Om flaggan är false modifierar catch_warnings
den globala filterlistan, vilket inte är trådsäkert. Se modulen warnings
för mer information.