Ez az oktatóanyag a Python egyik fontos témájára, a GIL-re összpontosít. Kitérünk arra is, hogy a GIL hogyan befolyásolja a Python programok teljesítményét a kód implementációjával. Mielőtt belemerülnénk ebbe a témába, legyen egy alapötlet a GIL-ről.
GIL vagy Global Interpreter Lock
A Python Global Interpreter Lock vagy GIL a többszálú programozás fontos része. Ez egyfajta folyamatzár, amelyet több folyamattal végzett munka során használnak. Csak egy szálhoz adja a vezérlést. A Python általában egyetlen szálat használ egyetlen folyamat futtatásához. Ugyanazt a teljesítményt kapjuk az egyszálú és a többszálú folyamatok GIL használatával. Korlátozza a többszálú feldolgozást Pythonban, mert megakadályozza a szálakat, és egyetlen szálként működik.
Megjegyzés – A Python nem támogatja a többszálú feldolgozást, mert a szálfűző csomagok nem tudták több CPU mag használatát engedélyezni.
Miért használ a Python Developers GIL-t?
A Python egyedülálló referenciaszámláló funkciót biztosít, amelyet a memóriakezelésre használnak. A referenciaszámláló megszámolja a Pythonban belsőleg készített hivatkozások teljes számát, hogy értéket rendeljen egy adatobjektumhoz. Amikor a referenciaszám eléri a nullát, az objektumhoz rendelt memória felszabadul. Lássuk az alábbi példát.
Példa -
import sys a = [] b = a sys.getrefcount(a)
A referenciaszám változóval kapcsolatos fő probléma az, hogy hatással lehet rá, ha két vagy három szál egyszerre próbálja növelni vagy csökkenteni az értékét. Versenyfeltételként ismert. Ha ez az állapot bekövetkezik, akkor kiszivároghat a memória, amely soha nem szabadul fel. Összeomolhat vagy hibás lehet a Python programban.
A GIL segít eltávolítani az ilyen helyzeteket azáltal, hogy a szálak közötti összes megosztott adatszerkezet zárolását használja, hogy azok ne változzanak következetlenül. A Python egyszerű módot kínál a GIL megvalósítására, mivel a szálbiztos memóriakezeléssel foglalkozik. A GIL megköveteli, hogy egy szál egyetlen zárolását kínálja fel a Pythonban való feldolgozáshoz. Növeli az egyszálú programok teljesítményét, mivel csak egy zárolást kell kezelni. Ezenkívül segít bármilyen CPU-hoz kötött program elkészítésében, és megakadályozza a patthelyzetet.
A többszálú Python programok hatása
Különbség van a teljesítményükben a CPU-korlátok és a tipikus Python-programok vagy bármely számítógépes program I/O-korlátai között. A CPU-hoz kötött programok általában a CPU-t a korlátai közé szorítják. Ezeket a programokat általában matematikai számításokra használják, például mátrixszorzásra, égetésre, képfeldolgozásra stb.
Az I/O kötött programok azok a programok, amelyek időt töltenek a felhasználó, fájl, adatbázis, hálózat stb. által generálható bemenet/kimenet megszerzésével. Az ilyen programoknak jelentős ideig kell várniuk, amíg a forrás biztosítja a bemenetet. Másrészt a forrásnak is megvan a maga feldolgozási ideje. Például - a felhasználó azon gondolkodik, mit írjon be bevitelként.
szögletes anyag
Értsük meg a következő példát.
Példa -
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)
Kimenet:
Time taken in seconds - 7.422671556472778
Most módosítjuk a fenti kódot a két szál futtatásával.
Példa - 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)
Kimenet:
Time taken in seconds - 6.90830135345459
Amint látjuk, mindkét kód befejezése ugyanannyi időt vett igénybe. A GIL megakadályozta, hogy a CPU-hoz kötött szálak párhuzamosan fussanak a második kódban.
Miért nem távolították el még a GIL-t?
Sok programozónak van panasza ezzel kapcsolatban, de a Python nem tudja olyan jelentős változásokat hozni, mint a GIL eltávolítása. Egy másik ok, hogy a GIL jelenleg nincs továbbfejlesztve. Ha megváltozik a Python 3-ban, az komoly problémákat okoz. A GIL eltávolítása helyett a GIL koncepciója javulhat. Guido van Rossom szerint -
int string java
'Csak akkor szívesen fogadok javításokat a Py3k-ba, ha egy egyszálú program (és egy többszálú, de I/O-hoz kötött program) teljesítménye nem csökken.'
Számos módszer is rendelkezésre áll, amelyek megoldják ugyanazt a problémát, amelyet a GIL megoldott, de ezeket nehéz megvalósítani.
Hogyan kell kezelni a Python GIL-jét
A többfeldolgozás használata a legalkalmasabb módja annak, hogy megakadályozzuk a programot a GIL-től. A Python különféle értelmezőket kínál minden egyes folyamathoz, így ebben a forgatókönyvben az egyetlen szálat biztosítják minden folyamatnak a többfeldolgozás során. Értsük meg a következő példát.
Példa -
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)
Kimenet:
Time taken in seconds - 3.3707828521728516
Úgy tűnhet, hogy a tisztességes teljesítmény megnő, de a folyamatkezelésnek megvannak a maga általános költségei, és több folyamat nehezebb, mint több szál.
Következtetés
Ebben az oktatóanyagban a GIL-ről és annak használatáról beszéltünk. Egyetlen szál vezérlését adja, hogy azok időben végrehajthatók legyenek. Ez az oktatóanyag arra is kitért, hogy miért fontos a GIL a Python programozók számára.