Den globale tolkelåsen (GIL) ser ofte ut til å bli sitert som en hovedårsak til at threading og lignende er en touch vanskelig i Python – noe som reiser spørsmålet «Hvorfor ble det gjort i utgangspunktet?»
Jeg er ikke programmerer, men jeg har ingen anelse om hvorfor det kan være – hva var logikken bak å legge inn GIL?
Kommentarer
- Wikipedia-artikkelen sier at » GIL kan være en betydelig barriere mot parallellitet – en pris som betales for å ha dynamikken i språket » , og fortsetter med å si at » Årsaker til å bruke en slik lås inkluderer: økt hastighet på enkeltrådede programmer (ingen nødvendighet å skaffe eller frigjøre låser på alle datastrukturer separat), og enkel integrering av C-biblioteker som vanligvis er ikke trådsikker. »
- @RobertHarvey, Dynamisme har ingenting å gjøre med det. Problemet er mutasjon.
- stackoverflow.com/questions/265687/…
- Kan ‘ ikke føle at Java (div id = «765eabeb7e»>
mangler usignerte tall, var det ment å forhindre folk som ikke ‘ vet ikke hva de ‘ gjør og skyter seg selv i foten. Dessverre, alle som vet vet hva de ‘ gjør, får et mangelfullt språk, noe som er veldig synd fordi Python klipper på så mange andre måter
Svar
Det er flere implementeringer av Python, for eksempel CPython, IronPython, RPython, osv.
Noen av dem har en GIL, noen har ikke. For eksempel har CPython GIL:
Fra http://en.wikipedia.org/wiki/Global_Interpreter_Lock
Programmer skrevet på programmeringsspråk med en GIL kan utformes for å bruke separate prosesser for å oppnå full parallellitet, ettersom hver prosess har sin egen tolk og har igjen sin egen GIL.
Fordelene med GIL
- Økt hastighet på enkeltrådede programmer.
- Enkel integrering av C-biblioteker som vanligvis ikke er trådsikre.
Hvorfor bruker Python (CPython og andre) GIL
I CPython er den globale tolkelåsen, eller GIL, en mutex som forhindrer flere innfødte tråder i å utføre Python-bytekoder samtidig. Denne låsen er nødvendig hovedsakelig fordi CPythons minneadministrasjon ikke er trådsikker.
GIL er kontroversiell fordi den forhindrer flertrådede CPython-programmer i å utnytte multiprosessorsystemer i visse situasjoner. Merk at potensielt blokkering eller langvarige operasjoner, som I / O, bildebehandling og NumPy-nummerknusing, skjer utenfor GIL. Derfor er det bare i flertrådede programmer som bruker mye tid inne i GIL, og tolker CPython bytecode, at GIL blir en flaskehals.
Python har en GIL i motsetning til finkornet låsing av flere grunner:
-
Det er raskere i tilfellet med en tråd.
-
Det er raskere i flertrådet tilfelle for i / o-bundne programmer.
-
Det er raskere i flertrådede tilfeller for CPU-bundne programmer som gjør deres beregningskrevende arbeid i C-biblioteker.
-
Det gjør C-utvidelser lettere å skrive: det vil ikke være noen bytte av Python-tråder bortsett fra der du lar det skje (dvs. mellom Py_BEGIN_ALLOW_THREADS og Py_END_ALLOW_THREADS makroer).
-
Det gjør innpakning av C-biblioteker enklere. Du trenger ikke å bekymre deg for trådsikkerhet. Hvis biblioteket ikke er trådsikkert, holder du ganske enkelt GIL låst mens du kaller det.
GIL kan frigjøres av C.-utvidelser. Pythons standardbibliotek frigjør GIL rundt hver blokkerende i / o-samtale. Dermed har GIL ingen konsekvens for ytelsen til i / o-bundne servere. Du kan dermed opprette nettverksservere i Python ved hjelp av prosesser (fork), tråder eller asynkron i / o, og GIL vil ikke komme i veien for deg.
Tallrike biblioteker i C eller Fortran kan på samme måte kalles med GIL løslatt. Mens C-utvidelsen din venter på at en FFT skal fullføres, vil tolken utføre andre Python-tråder.En GIL er dermed lettere og raskere enn finkornet låsing også i dette tilfellet. Dette utgjør mesteparten av det numeriske arbeidet. NumPy-utvidelsen frigjør GIL når det er mulig.
Tråder er vanligvis en dårlig måte å skrive de fleste serverprogrammer på. Hvis lasten er lav, er gaffel lettere. Hvis belastningen er høy, er asynkron i / o og hendelsesdrevet programmering (f.eks. Ved bruk av Pythons Twisted framework) bedre. Den eneste unnskyldningen for å bruke tråder er mangelen på os.fork på Windows.
GIL er et problem hvis, og bare hvis du gjør CPU-intensivt arbeid i ren Python. Her kan du få renere design ved hjelp av prosesser og overføring av meldinger (f.eks. Mpi4py). Det er også en «prosesseringsmodul» i Python-ost butikk, som gir prosesser det samme grensesnittet som tråder (dvs. bytt ut tråder.Tråd med prosessering.Prosess).
Tråder kan brukes til å opprettholde responsen til en GUI uavhengig av GIL. Hvis GIL svekker ytelsen din (jf. diskusjonen ovenfor), kan du la tråden gyte en prosess og vente på at den er ferdig.
Kommentarer
- Høres ut som sure druer for meg. Python kan ‘ ikke gjøre tråder ordentlig, så du finner opp grunner til at tråder er unødvendige eller til og med dårlige. » Hvis belastningen er lav, fo rking er lettere «, seriøst? Og GIL er » raskere » bare for alle disse tilfellene hvis du insisterer på å bruke referansetelling GC.
-
s/RPython/PyPy/g
. @MichaelBorgwardt Å gi grunner til at GIL er slags poenget med spørsmålet, er det ikke ‘? Selv om jeg er enig i at noe av innholdet i dette svaret (nemlig diskusjon om alternativer) er utenfor poenget. Og på godt og vondt er det nå nesten umulig å kvitte seg med gjentelling – det er dypt inngrodd i hele API og kodebase; det ‘ er nesten umulig å kvitte seg med det uten å skrive om halvparten av koden og bryte all ekstern kode. - Don ‘ t glem
multiprocessing
biblioteket – standard siden 2.6. Det ‘ arbeiderbassenger er en superglatt abstraksjon for noen enkle typer parallellisme. - @alcalde Bare hvis du ikke ‘ vet ikke hva du ‘ gjør og / eller du ikke ‘ t vil at trådene dine skal kunne samarbeide / kommunisere. Ellers er det ‘ en kongelig smerte på baksiden, spesielt med tanke på overhead for å starte en ny prosess på noen operativsystemer. Vi har servere med 32 kjerner, så for å kunne bruke dem fullt ut i CPython I ‘ d trenger 32 prosesser. At ‘ ikke er en » god løsning » det ‘ sa hack for å omgå CPython ‘ mangler.
- Det faktum at tråder eksisterer på andre plattformer enn Windows, bør være et bevis nok på at gaffel ikke er ‘ t tilstrekkelig i alle situasjoner.
Svar
Først av: Python har ikke en GIL. Python er et programmeringsspråk. Et programmeringsspråk er et sett med abstrakte matematiske regler og begrensninger. Det er ingenting i Python Language Specification som sier at det må være en GIL.
Det er mange forskjellige implementeringer av Python. Noen har en GIL, noen ikke.
En enkel forklaring på å ha en GIL er at det å skrive samtidig kode er vanskelig. Ved å plassere en gigantisk lås rundt koden din, tvinger du den til å alltid kjøre seriell. Problem løst!
Spesielt i CPython er et viktig mål å gjøre det enkelt å utvide tolken med plugins skrevet i C. Igjen er det vanskelig å skrive samtidig kode, så ved å garantere at det ikke blir noe samtidig gjør det det lettere å skrive utvidelser for tolk. I tillegg er mange av disse utvidelsene bare tynne omslag rundt eksisterende biblioteker som kanskje ikke er skrevet med tanke på samtid.
Kommentarer
- At ‘ er det samme argumentet som Java ‘ mangler usignerte numeriske typer – utviklerne tror at alle andre er dummere enn de er …
- @Basic – tro det eller ei, selv når du ‘ ikke er veldig, dum, viser det seg at det å ha et språk som gjør forenklende antagelser som betyr at du ikke ‘ Ikke tenk på bestemte ting for å få dem til å fungere er fortsatt en nyttig ting.CPython er flott for visse ting, inkludert enkle flertrådede applikasjoner (der programmet er IO-bundet, som mange er, og derfor betyr ikke GIL ‘ t), fordi designbeslutningene som tok GIL den beste løsningen gjør det også enklere å programmere disse applikasjonene, spesielt det faktum at den støtter atomoperasjoner på samlinger .
- @Jules Ja, den ‘ er veldig nyttig helt til du trenger disse mulighetene. cpython ‘ s » foretrukket » løsning av » bare skriv det på et annet språk som c ++ » betyr at du mister hver eneste pythonfordel. Hvis du ‘ skriver halvparten av koden din i c ++, hvorfor starte fra Python? Visst, for små API / lim projiserer det ‘ raskt og enkelt, og for ETL er det ‘ uten sidestykke, men det ‘ er ikke egnet for noe som krever tunge løft. Samme som å bruke Java til å snakke med maskinvare … Det ‘ er nesten komiske ringene du må hoppe gjennom.
- @Basic One of Python ‘ s og dermed i utstrakt grad CPython ‘ s kjernefilosofier er å gjøre teknologien » vennlig og enkel å bruke «. Parallell programmering uten global lås er ikke det. Tatt i betraktning at det er mange implementeringer uten GIL, er det fornuftig å i det minste gi en implementering som har det.
- Du sier » det er fornuftig å i det minste gi en implementering som har det. » liker det ‘ er den åpenbare konklusjonen, men ingen andre språk jeg ‘ er klar over å hakke utviklerne på denne måten, slik at den kan ‘ t være det åpenbart.
Svar
Hva er formålet med en GIL?
CAPI-dokumentasjonen har dette å si om emnet:
Python-tolken er ikke helt trådsikker . For å støtte Python-programmer med flere tråder, er det en global lås, kalt global tolkelås eller GIL, som må holdes av den gjeldende tråden før den trygt kan få tilgang til Python-objekter. Uten låsen kan til og med de enkleste operasjonene forårsake problemer i et program med flere tråder: For eksempel, når to tråder samtidig øker referansetellingen til det samme objektet, kan referansen teller til slutt kun å økes en gang i stedet for to ganger.
Med andre ord forhindrer GIL korrupsjon av staten. Python-programmer skal aldri produsere en segmenteringsfeil, fordi bare minnesikker drift er tillatt. GIL utvider denne forsikringen til programmer med flere tråder.
Hva er alternativene?
Hvis formålet med GIL er å beskytte staten mot korrupsjon, er et åpenbart alternativ å låse på et mye finere korn; kanskje på nivå per objekt. Problemet med dette er at selv om det er demonstrert å øke ytelsen til flertrådede programmer, har det flere overheadprogrammer og enkelttrådede programmer lider som et resultat.
Kommentarer
- Det ville være flott å la en bruker kjøre et program med et tolkalternativ som erstatter gil for finkornet lås, og på en eller annen måte vet – på en readonly måte – om den nåværende prosessen ble hevet med eller uten gil.
- Til tross for GIL klarte jeg å produsere en segmenteringsfeil i et flertrådet program på grunn av uforsiktig bruk av modul pyodbc. Dermed skal » aldri produsere en segmenteringsfeil » er en feil.