logo

Hva er GIL i Python? Global tolkelås

Denne opplæringen vil være fokusert på et av viktige Pythons emner, GIL. Vi vil også dekke hvordan GIL påvirker Python-programmenes ytelse med kodeimplementeringen. Før vi dykker inn i dette emnet, la oss ha en grunnleggende idé om GIL.

GIL eller Global Interpreter Lock

Python Global Interpreter Lock eller GIL er en viktig del av multithreading-programmering. Det er en type prosesslås som brukes når du arbeider med flere prosesser. Det gir kontrollen til kun én tråd. Vanligvis bruker Python en enkelt tråd for å kjøre en enkelt prosess. Vi får det samme ytelsesresultatet av de enkelt- og flertrådede prosessene ved å bruke GIL. Det begrenser å oppnå multithreading i Python fordi det forhindrer trådene og fungerer som en enkelt tråd.

Merk - Python støtter ikke multithreading fordi threading-pakker ikke kunne la oss bruke flere CPU-kjerner.

Hvorfor bruker Python-utviklere GIL?

Python gir den unike referansetellerfunksjonen, som brukes til minneadministrasjon. Referansetelleren teller det totale antallet referanser som er gjort internt i Python for å tildele en verdi til et dataobjekt. Når referansetellingene når null, frigjøres det tilordnede minnet til objektet. La oss se eksemplet nedenfor.

Eksempel -

 import sys a = [] b = a sys.getrefcount(a) 

Hovedproblemet med referansetellingsvariabelen er at den kan påvirkes når to eller tre tråder prøver å øke eller redusere verdien samtidig. Det er kjent som rasetilstand. Hvis denne tilstanden oppstår, kan det skyldes lekket minne som aldri frigjøres. Det kan krasje eller feil i Python-programmet.

GIL hjelper oss å fjerne en slik situasjon ved å bruke låsene til alle delte datastrukturer på tvers av tråder slik at de ikke endres inkonsekvent. Python gir en enkel måte å implementere GIL ettersom den omhandler trådsikker minneadministrasjon. GIL krever å tilby en enkelt lås til en tråd for behandling i Python. Det øker ytelsen til et enkelt-trådet program ettersom bare én lås må håndteres. Det hjelper også med å lage et hvilket som helst CPU-bundet program og forhindrer vranglåstilstanden.

avl trerotasjon

Innvirkningen på flertrådede Python-programmer

Det er en forskjell mellom CPU-grenser i ytelsen og I/O-bundet for et typisk Python-program eller et hvilket som helst dataprogram. CPU-bundne programmer presses vanligvis CPU til sine grenser. Disse programmene brukes vanligvis til matematisk beregning som matrisemultiplikasjoner, brenning, bildebehandling, etc.

I/O-bundne programmer er de programmene som bruker tid på å få input/output som kan genereres av brukeren, filen, databasen, nettverket osv. Slike programmer må vente i en betydelig mengde tid før kilden gir input. På den annen side har kilden også sin egen behandlingstid. For eksempel – en bruker tenker på hva han skal legge inn som input.

La oss forstå følgende eksempel.

Eksempel -

 import time from threading import Thread COUNT = 100000000 def countdown(num): while num>0: num -= 1 start_time = time.time() countdown(COUNT) end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Produksjon:

 Time taken in seconds - 7.422671556472778 

Nå endrer vi koden ovenfor ved å kjøre de to trådene.

Eksempel - 2:

 import time from threading import Thread COUNT = 100000000 def countdown(num): while num>0: num -= 1 thread1 = Thread(target=countdown, args=(COUNT//2,)) thread2 = Thread(target=countdown, args=(COUNT//2,)) start_time = time.time() thread1.start() thread2.start() thread1.join() thread2.join() end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Produksjon:

 Time taken in seconds - 6.90830135345459 

Som vi kan se at begge kodene tok samme tid å fullføre. GIL forhindret de CPU-bundne trådene fra å kjøre parallelt i den andre koden.

Hvorfor har ikke GIL blitt fjernet ennå?

Mange programmerere har en klage på dette, men Python kan ikke bringe endringene like viktige som fjerningen av GIL. En annen grunn er at GIL ikke er forbedret per nå. Hvis det endres i Python 3, vil det skape noen alvorlige problemer. I stedet for å fjerne GIL, kan GIL-konseptet forbedres. I følge Guido van Rossom -

'Jeg tar gjerne imot et sett med patcher i Py3k bare hvis ytelsen for et enkelt-tråds program (og for et flertråds, men I/O-bundet program) ikke reduseres'.

Det er også mange metoder tilgjengelig som løser det samme problemet løst av GIL, men det er vanskelig å implementere.

Hvordan håndtere Pythons GIL

Å bruke multiprosessering er den mest egnede måten å forhindre at programmet fra GIL. Python tilbyr forskjellige tolker for hver prosess som skal kjøres, så i det scenariet blir den enkelte tråden gitt til hver prosess i multiprosessering. La oss forstå følgende eksempel.

Eksempel -

 from multiprocessing import Pool import time COUNT = 50000000 def countdown(num): while num>0: num -= 1 if __name__ == '__main__': pool = Pool(processes=2) start_time = time.time() r1 = pool.apply_async(countdown, [COUNT//2]) r2 = pool.apply_async(countdown, [COUNT//2]) pool.close() pool.join() end_time = time.time() print('Time taken in seconds -', end_time - start_time) 

Produksjon:

 Time taken in seconds - 3.3707828521728516 

Det kan virke som en anstendig ytelse økes, men prosessledelse har sine egne kostnader og flere prosesser er tyngre enn flere tråder.

Konklusjon

I denne opplæringen har vi diskutert GIL og hvordan vi kan bruke den. Det gir kontrollen til en enkelt tråd som skal utføres til tider. Denne opplæringen dekket også hvorfor GIL er viktig for Python-programmerere.