Denna handledning kommer att fokuseras på ett av viktiga Pythons ämnen, GIL. Vi kommer också att täcka hur GIL påverkar Python-programmens prestanda med kodimplementeringen. Innan vi dyker in i detta ämne, låt oss ha en grundläggande idé om GIL.
100 km/h till mph
GIL eller Global Interpreter Lock
Python Global Interpreter Lock eller GIL är en viktig del av flertrådsprogrammering. Det är en typ av processlås som används när man arbetar med flera processer. Det ger kontrollen till endast en tråd. I allmänhet använder Python en enda tråd för att köra en enda process. Vi får samma prestandaresultat av de enkeltrådade och flertrådade processerna med hjälp av GIL. Det begränsar uppnåendet av multithreading i Python eftersom det förhindrar trådarna och fungerar som en enda tråd.
Notera - Python stöder inte multithreading eftersom trådningspaket inte kunde låta oss använda de flera CPU-kärnorna.
Varför Python-utvecklare använder GIL?
Python tillhandahåller den unika referensräknarefunktionen, som används för minneshantering. Referensräknaren räknar det totala antalet referenser som gjorts internt i Python för att tilldela ett värde till ett dataobjekt. När referensräkningarna når noll frigörs det tilldelade minnet för objektet. Låt oss se exemplet nedan.
Exempel -
import sys a = [] b = a sys.getrefcount(a)
Det största problemet med referensräknevariabeln är att den kan påverkas när två eller tre trådar försöker öka eller minska dess värde samtidigt. Det är känt som race condition. Om detta tillstånd inträffar kan det orsakas att minnet läckt ut som aldrig släpps. Det kan krascha eller buggar i Python-programmet.
GIL hjälper oss att ta bort en sådan situation genom att använda låsen till alla delade datastrukturer över trådar så att de inte ändras inkonsekvent. Python ger ett enkelt sätt att implementera GIL eftersom det handlar om trådsäker minneshantering. GIL kräver att man erbjuder ett enda lås till en tråd för bearbetning i Python. Det ökar prestandan hos ett entrådigt program eftersom endast ett lås behöver hanteras. Det hjälper också till att göra alla CPU-bundna program och förhindrar dödläget.
Inverkan på flertrådiga Python-program
Det finns en skillnad mellan CPU-gränser i deras prestanda och I/O-bundna för ett typiskt Python-program eller vilket datorprogram som helst. CPU-bundna program pressas vanligtvis CPU:n till dess gränser. Dessa program används vanligtvis för matematiska beräkningar som matrismultiplikationer, bränning, bildbehandling, etc.
I/O-bundna program är de program som lägger tid på att få indata/utdata som kan genereras av användaren, filen, databasen, nätverket etc. Sådana program måste vänta en betydande tid tills källan tillhandahåller indata. Å andra sidan har källan också en egen handläggningstid. Till exempel - en användare funderar på vad han ska ange som indata.
Låt oss förstå följande exempel.
int till sträng java
Exempel -
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)
Produktion:
Time taken in seconds - 7.422671556472778
Nu modifierar vi ovanstående kod genom att köra de två trådarna.
Exempel - 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)
Produktion:
Time taken in seconds - 6.90830135345459
Som vi kan se att båda koderna tog samma tid att slutföra. GIL förhindrade de CPU-bundna trådarna från att köras parallellt i den andra koden.
Varför har inte GIL tagits bort ännu?
Många programmerare har ett klagomål angående detta, men Python kan inte göra ändringarna lika viktiga som borttagningen av GIL. En annan anledning är att GIL inte är förbättrat nu. Om det ändras i Python 3 kommer det att skapa några allvarliga problem. Istället för att ta bort GIL kan GIL-konceptet förbättras. Enligt Guido van Rossom -
'Jag skulle bara välkomna en uppsättning patchar i Py3k om prestandan för ett entrådigt program (och för ett flertrådigt men I/O-bundet program) inte minskar'.
iPhone emojis på Android-telefon
Det finns också många tillgängliga metoder som löser samma problem som lösts av GIL, men de är svåra att implementera.
Hur man hanterar Pythons GIL
Att använda multiprocessing är det lämpligaste sättet att förhindra programmet från GIL. Python erbjuder olika tolkar för varje process att köra, så i det scenariot tillhandahålls den enda tråden till varje process i multiprocessing. Låt oss förstå följande exempel.
Exempel -
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)
Produktion:
Time taken in seconds - 3.3707828521728516
Det kan tyckas att en anständig prestanda höjs men processhantering har sina egna omkostnader och flera processer är tyngre än flera trådar.
Slutsats
I den här handledningen har vi diskuterat GIL och hur vi kan använda den. Det ger kontrollen till en enda tråd att köra vid tidpunkten. Denna handledning täckte också varför GIL är viktigt för Python-programmerare.