Det globala tolklåset (GIL) tycks ofta citeras som en viktig anledning till att trådning och liknande är en knepig känsla i Python – vilket väcker frågan ”Varför gjordes det i första hand?”
Eftersom jag inte är programmerare har jag ingen aning om varför det kan vara – vad var logiken bakom att sätta in GIL?
Kommentarer
- Wikipedia-artikeln anger att ” GIL kan vara ett betydande hinder för parallellism – ett pris som betalas för att ha dynamiken i språket ” , och fortsätter med att säga att ” Anledningarna till att använda ett sådant lås inkluderar: ökad hastighet för enkeltrådade program (ingen nödvändighet att skaffa eller släppa lås på alla datastrukturer separat) och enkel integration av C-bibliotek som vanligtvis är inte trådsäker. ”
- @RobertHarvey, Dynamism har inget att göra med det. Problemet är mutation.
- stackoverflow.com/questions/265687/…
- Kan ’ inte hjälpa till att känna att som Java ’ saknar osignerade siffror, var det avsett att förhindra människor som inte ’ vet inte vad de ’ gör för att skjuta sig i foten. Tyvärr, alla som vet vet vad de ’ gör får ett bristfälligt språk, vilket är verkligen synd eftersom Python vaggar på så många andra sätt
- @ Basic måste det finnas något vanligt sätt att hantera byte-arrays i Java (jag har inte ’ använde det inte länge) för att göra kryptomatning. Python (till exempel) har inte ’ t undertecknade nummer, men jag skulle inte ’ t ens försöka göra bitvis ops med det eftersom det finns bättre sätt.
Svar
Det finns flera implementeringar av Python, till exempel CPython, IronPython, RPython, etc.
Några av dem har en GIL, vissa har inte. Till exempel har CPython GIL:
Från http://en.wikipedia.org/wiki/Global_Interpreter_Lock
Applikationer skrivna på programmeringsspråk med en GIL kan utformas för att använda separata processer för att uppnå full parallellitet, eftersom varje process har sin egen tolk och i sin tur har sin egen GIL.
Fördelarna med GIL
- Ökad hastighet för enkeltrådade program.
- Enkel integration av C-bibliotek som vanligtvis inte är trådsäkra.
Varför Python (CPython och andra) använder GIL
I CPython är det globala tolklåset, eller GIL, en mutex som förhindrar att flera inbyggda trådar kör Python-bytkoder på en gång. Detta lås är nödvändigt främst för att CPythons minneshantering inte är trådsäker.
GIL är kontroversiell eftersom det förhindrar flertrådade CPython-program att dra full nytta av multiprocessorsystem i vissa situationer. Observera att potentiellt blockering eller långvariga operationer, som I / O, bildbehandling och NumPy-nummerkramning, händer utanför GIL. Därför är det bara i flertrådade program som spenderar mycket tid inuti GIL, vilket tolkar CPython-bytkod, som GIL blir en flaskhals.
Python har en GIL i motsats till finkornig låsning av flera anledningar:
-
Det är snabbare i fallet med en tråd.
-
Det är snabbare i fallet med flera trådar för i / o-bundna program.
-
Det är snabbare i fallet med flera trådar för CPU-bundna program som gör deras datorintensiva arbete i C-bibliotek.
-
Det gör C-förlängningar lättare att skriva: det går inte att byta Python-trådar förutom där du låter det hända (dvs. mellan Py_BEGIN_ALLOW_THREADS och Py_END_ALLOW_THREADS-makron).
-
Det gör det lättare att radera C-bibliotek. Du behöver inte oroa dig för trådsäkerhet. Om biblioteket inte är trådsäkert håller du helt enkelt GIL låst medan du kallar det.
GIL kan släpps av C-tillägg. Pythons standardbibliotek släpper GIL runt varje blockerande i / o-samtal. Således har GIL ingen konsekvens för prestanda för i / o-bundna servrar. Du kan alltså skapa nätverksservrar i Python med hjälp av processer (gaffel), trådar eller asynkron i / o, och GIL kommer inte i vägen för dig.
Numeriska bibliotek i C eller Fortran kan på samma sätt kallas med GIL släppt. Medan ditt C-tillägg väntar på att en FFT ska slutföras kommer tolk att köra andra Python-trådar.En GIL är alltså lättare och snabbare än finkornig låsning också i detta fall. Detta utgör huvuddelen av det numeriska arbetet. NumPy-tillägget släpper ut GIL när det är möjligt.
Trådar är vanligtvis ett dåligt sätt att skriva de flesta serverprogram. Om lasten är låg är det lättare att gaffla. Om belastningen är hög är asynkron i / o och händelsestyrd programmering (t.ex. med Pythons Twisted framework) bättre. Den enda ursäkten för att använda trådar är bristen på os.fork i Windows.
GIL är ett problem om, och bara om du gör CPU-intensivt arbete i ren Python. Här kan du få renare design med processer och meddelandeöverföring (t.ex. mpi4py). Det finns också en ”bearbetnings” -modul i Python-ost shop, som ger processer samma gränssnitt som trådar (dvs. byt ut trådning.Tråd med bearbetning.Process).
Trådar kan användas för att upprätthålla ett GUI: s respons, oavsett GIL. (jfr diskussionen ovan), du kan låta din tråd skapa en process och vänta tills den är klar.
Kommentarer
- Låter som sura druvor för mig. Python kan ’ inte göra trådar ordentligt, så du gör upp skäl till varför trådar är onödiga eller till och med dåliga. ” Om belastningen är låg, fo rking är lättare ”, allvarligt? Och GIL är ” snabbare ” bara för alla dessa fall om du insisterar på att använda referensräkning-GC.
-
s/RPython/PyPy/g
. @MichaelBorgwardt Ange skäl för GIL är typ av frågan, är det inte ’? Även om jag håller med om att något av innehållet i det här svaret (nämligen diskussion om alternativ) är utanför saken. Och på gott och ont, är omräkning nu nästan omöjligt att bli av med – den är djupt inbäddad i hela API och kodbas; det ’ är nästan omöjligt att bli av med det utan att skriva om halva koden och bryta alla externa koder. - Don ’ glöm inte
multiprocessing
biblioteket – standard sedan 2.6. Den ’ s arbetarkompanjer är en superglatt abstraktion för vissa enkla typer av parallellism. - @alcalde Endast om du inte ’ vet inte vad du ’ gör och / eller du inte ’ t vill att dina trådar ska kunna arbeta tillsammans / kommunicera. Annars är det ’ en kunglig smärta i baksidan, speciellt med tanke på överhead för att starta en ny process på vissa operativsystem. Vi har servrar med 32 kärnor, så för att kunna använda dem fullt ut i CPython I ’ d behöver 32 processer. Att ’ inte är en ” bra lösning ” det ’ ett hack för att kringgå CPython ’ otillräcklighet.
- Det faktum att trådar finns på andra plattformar än Windows borde vara tillräckligt bevis för att gaffel inte är ’ är inte tillräcklig i alla situationer.
Svar
Först av: Python har inte en GIL. Python är ett programmeringsspråk. Ett programmeringsspråk är en uppsättning abstrakta matematiska regler och begränsningar. Det finns inget i Python Language Specification som säger att det måste finnas en GIL.
Det finns många olika implementeringar av Python. Vissa har en GIL, andra inte.
En enkel förklaring för att ha en GIL är att det är svårt att skriva samtidig kod. Genom att placera ett jätte lås runt din kod tvingar du den att alltid köra seriellt. Problem löst!
I synnerhet i CPython är ett viktigt mål att göra det enkelt att förlänga tolk med plugins skrivna i C. Återigen är det svårt att skriva samtidig kod, så genom att garantera att det inte finns samtidigt gör det lättare att skriva tillägg för tolk. Dessutom är många av dessa tillägg bara tunna omslag runt befintliga bibliotek som kanske inte har skrivits med samtidighet i åtanke.
Kommentarer
- Att ’ är samma argument som Java ’ saknar osignerade numeriska typer – utvecklarna tycker att alla andra är dummare än de är …
- @Basic – tro det eller inte, även när du ’ inte är riktigt, riktigt dum, visar det sig att ha ett språk som gör förenklade antaganden som betyder att du inte ’ Tänk inte på vissa saker för att få dem att fungera är fortfarande en användbar sak.CPython är utmärkt för vissa saker, inklusive enkla flertrådade applikationer (där programmet är IO-bundet, vilket många är, och därför spelar GIL ingen roll ’), eftersom designbesluten som gjorde GIL den bästa lösningen gör det också enklare att programmera dessa applikationer, särskilt det faktum att det stöder atomoperationer på samlingar .
- @Jules Ja, det ’ är mycket praktiskt ända tills du behöver dessa funktioner. cpython ’ s ” föredragen ” lösning av ” skriv bara på ett annat språk som c ++ ” betyder att du förlorar varje enskild pythonfördel. Om du ’ skriver halva koden i c ++, varför börja då från Python? Visst, för små API / limprojekt är det ’ snabbt och enkelt, och för ETL är det ’ oöverträffat, men det ’ är inte lämpligt för något som kräver tunga lyft. Samma som att använda Java för att prata med hårdvara … Det ’ är nästan komiska de banden du måste hoppa igenom.
- @Basic One of Python ’ s och därmed CPython ’ s kärnfilosofier är att göra tekniken ” vänlig och lätt att använda ”. Parallell programmering utan globalt lås är inte det. Med tanke på att det finns många implementeringar utan GIL är det vettigt att åtminstone tillhandahålla en implementering som har det.
- Du säger ” det är vettigt att åtminstone tillhandahålla en implementering som har det. ” gillar det ’ är den självklara slutsatsen, men inget annat språk jag ’ är medveten om att hobba utvecklarna på detta sätt så att den kan ’ t vara det uppenbart.
Svar
Vad är syftet med en GIL?
CAPI-dokumentationen har detta att säga om ämnet:
Python-tolk är inte helt trådsäker . För att stödja Python-program med flera trådar finns det ett globalt lås, kallat det globala tolklåset eller GIL, som måste hållas av den aktuella tråden innan det säkert kan komma åt Python-objekt. Utan låset kan även de enklaste operationerna orsaka problem i ett program med flera trådar: till exempel när två trådar samtidigt ökar referensantalet för samma objekt, kan referensantalet ökas bara en gång istället för två gånger.
Med andra ord förhindrar GIL korruption av staten. Python-program bör aldrig producera ett segmenteringsfel, eftersom endast minnessäkra funktioner är tillåtna. GIL utökar denna försäkran till fler trådade program.
Vilka är alternativen?
Om syftet med GIL är att skydda staten mot korruption, är ett självklart alternativ att låsa en mycket finare säd. kanske på en nivå per objekt. Problemet med detta är att även om det har visat sig öka prestandan hos flertrådade program, har det mer overhead och enkeltrådade program lider som ett resultat.
Kommentarer
- Det skulle vara jättebra att låta en användare köra ett program med ett tolkalternativ som ersätter gil för finkornigt lås, och på något sätt vet – på ett enkelt sätt – om den nuvarande processen höjdes med eller utan gil.
- Trots GIL lyckades jag producera ett segmenteringsfel i ett multitrådat program på grund av slarvig användning av modulen pyodbc. Således ska ” aldrig producera ett segmenteringsfel ” är ett fel.