Ovaj vodič će biti fokusiran na jednu od važnih tema Pythona, GIL. Također ćemo obraditi kako GIL utječe na performanse Python programa s implementacijom koda. Prije nego što se bacimo na ovu temu, sjetimo se osnovne ideje GIL-a.
GIL ili Global Interpreter Lock
Python Global Interpreter Lock ili GIL važan je dio višenitnog programiranja. To je vrsta zaključavanja procesa koja se koristi pri radu s više procesa. Daje kontrolu samo jednoj niti. Općenito, Python koristi jednu nit za pokretanje jednog procesa. Dobivamo isti rezultat izvedbe jednonitnih i višenitnih procesa pomoću GIL-a. Ograničava postizanje višenitnosti u Pythonu jer sprječava niti i radi kao jedna nit.
Napomena - Python ne podržava multithreading jer nam paketi threadinga ne mogu dopustiti korištenje višestrukih CPU jezgri.
Zašto Python Developers koristi GIL?
Python pruža jedinstvenu značajku brojača referenci, koja se koristi za upravljanje memorijom. Brojač referenci broji ukupan broj referenci napravljenih interno u Pythonu za dodjelu vrijednosti podatkovnom objektu. Kada broj referenci dosegne nulu, dodijeljena memorija objekta se oslobađa. Pogledajmo donji primjer.
Primjer -
10 posto od 60
import sys a = [] b = a sys.getrefcount(a)
Glavna briga u vezi s varijablom broja referenci je da na nju može utjecati kada dvije ili tri niti pokušavaju povećati ili smanjiti njezinu vrijednost istovremeno. Poznato je kao stanje utrke. Ako se ovo stanje dogodi, to može biti uzrokovano curenjem memorije koja se nikad ne oslobađa. Može se srušiti ili imati pogreške u programu Python.
GIL nam pomaže ukloniti takvu situaciju korištenjem zaključavanja svih zajedničkih struktura podataka u nitima tako da se ne mijenjaju nedosljedno. Python pruža jednostavan način za implementaciju GIL-a budući da se bavi upravljanjem memorijom sigurnim niti. GIL zahtijeva ponudu jednog zaključavanja niti za obradu u Pythonu. Povećava izvedbu jednonitnog programa jer je potrebno samo jedno zaključavanje. Također pomaže u izradi bilo kojeg CPU-vezanog programa i sprječava stanje zastoja.
int u string java
Utjecaj na Python programe s više niti
Postoji razlika između CPU-ograničenja u njihovoj izvedbi i I/O vezanih za tipični Python program ili bilo koji računalni program. CPU vezani programi općenito guraju CPU do njegovih granica. Ovi se programi općenito koriste za matematička izračunavanja kao što su množenje matrice, pečenje, obrada slike itd.
I/O vezani programi su oni programi koji troše vrijeme da dobiju ulaz/izlaz koji može generirati korisnik, datoteka, baza podataka, mreža itd. Takvi programi moraju čekati neko značajno vrijeme dok izvor ne pruži ulaz. S druge strane, izvor također ima svoje vrijeme obrade. Na primjer - korisnik razmišlja o tome što unijeti kao unos.
Razumimo sljedeći primjer.
Primjer -
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)
Izlaz:
Time taken in seconds - 7.422671556472778
Sada modificiramo gornji kod pokretanjem dvije niti.
Primjer - 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)
Izlaz:
Time taken in seconds - 6.90830135345459
Kao što vidimo, oba koda su trebala isto vrijeme da završe. GIL je spriječio paralelno izvođenje niti vezanih za CPU u drugom kodu.
kolika je veličina ekrana mog računala
Zašto GIL još nije uklonjen?
Mnogi programeri imaju pritužbu u vezi s tim, ali Python ne može donijeti promjene tako značajne kao uklanjanje GIL-a. Drugi razlog je taj što GIL još nije poboljšan. Ako se promijeni u Python 3, to će stvoriti ozbiljne probleme. Umjesto uklanjanja GIL-a, GIL koncept se može poboljšati. Prema Guidu van Rossomu -
'Dobrodošao bih skup zakrpa u Py3k samo ako se performanse za jednonitni program (i za višenitni ali I/O-vezan program) ne smanjuju'.
Dostupne su i mnoge metode koje rješavaju isti problem koji rješava GIL, ali ih je teško implementirati.
Kako se nositi s Pythonovim GIL-om
Korištenje višestruke obrade je najprikladniji način za sprječavanje programa od GIL-a. Python nudi različite tumače za svaki proces koji treba pokrenuti, tako da se u tom scenariju jedna nit pruža svakom procesu u višeprocesiranju. Razumimo sljedeći primjer.
Primjer -
povratni tip u Javi
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)
Izlaz:
Time taken in seconds - 3.3707828521728516
Može se činiti da je pristojna izvedba povećana, ali upravljanje procesima ima vlastite troškove i višestruki procesi su teži od više niti.
Zaključak
U ovom vodiču smo razgovarali o GIL-u i kako ga možemo koristiti. Daje kontrolu jednoj niti za izvršavanje u određeno vrijeme. Ovaj vodič je također pokrio zašto je GIL važan za Python programere.