logo

Kas ir GIL Python? Globālā tulka bloķēšana

Šī apmācība būs vērsta uz vienu no svarīgām Python tēmām GIL. Mēs arī apskatīsim, kā GIL ietekmē Python programmu veiktspēju, ieviešot kodu. Pirms iedziļināties šajā tēmā, iegūsim pamatideju par GIL.

GIL vai Global Interpreter Lock

Python Global Interpreter Lock jeb GIL ir svarīga daudzpavedienu programmēšanas sastāvdaļa. Tas ir procesa bloķēšanas veids, ko izmanto, strādājot ar vairākiem procesiem. Tas nodrošina kontroli tikai vienam pavedienam. Parasti Python izmanto vienu pavedienu, lai palaistu vienu procesu. Izmantojot GIL, mēs iegūstam vienādu viena un vairāku vītņu procesu veiktspējas rezultātu. Tas ierobežo vairākpavedienu sasniegšanu programmā Python, jo tas novērš pavedienus un darbojas kā viens pavediens.

Piezīme. Python neatbalsta vairākpavedienu izveidi, jo pavedienu pakotnes nevarēja ļaut mums izmantot vairākus CPU kodolus.

Kāpēc Python izstrādātāji izmanto GIL?

Python nodrošina unikālu atsauces skaitītāja funkciju, kas tiek izmantota atmiņas pārvaldībai. Atsauces skaitītājs uzskaita kopējo atsauču skaitu, kas iekšēji veiktas programmā Python, lai datu objektam piešķirtu vērtību. Kad atsauces skaits sasniedz nulli, objektam piešķirtā atmiņa tiek atbrīvota. Apskatīsim zemāk redzamo piemēru.

Piemērs -

saglabātās programmas vadība
 import sys a = [] b = a sys.getrefcount(a) 

Galvenās bažas par atsauces skaita mainīgo ir tas, ka to var ietekmēt, ja divi vai trīs pavedieni mēģina vienlaikus palielināt vai samazināt tā vērtību. Tas ir pazīstams kā sacensību stāvoklis. Ja rodas šāds stāvoklis, var rasties atmiņas noplūde, kas nekad netiek atbrīvota. Tas var avarēt vai kļūdas programmā Python.

GIL palīdz mums novērst šādu situāciju, izmantojot visu pavedienu koplietoto datu struktūru bloķēšanu, lai tās netiktu mainītas nekonsekventi. Python nodrošina vienkāršu veidu, kā ieviest GIL, jo tas nodarbojas ar pavedienu drošu atmiņas pārvaldību. GIL prasa piedāvāt vienu pavediena bloķēšanu, lai to apstrādātu programmā Python. Tas palielina viena vītnes programmas veiktspēju, jo ir jāapstrādā tikai viena bloķēšana. Tas arī palīdz izveidot jebkuru ar CPU saistītu programmu un novērš strupceļu stāvokli.

int uz virkni java

Ietekme uz daudzpavedienu Python programmām

Pastāv atšķirība starp CPU veiktspējas ierobežojumiem un I/O saitēm parastai Python programmai vai jebkurai datorprogrammai. Ar CPU saistītās programmas parasti tiek nospiestas CPU līdz tā robežām. Šīs programmas parasti izmanto matemātiskiem aprēķiniem, piemēram, matricas reizināšanai, apdedzināšanai, attēlu apstrādei utt.

I/O saistītās programmas ir tās programmas, kuras pavada laiku, lai iegūtu ievadi/izeju, ko var ģenerēt lietotājs, fails, datubāze, tīkls utt. Šādām programmām ir jāgaida ievērojams laiks, līdz avots nodrošina ievadi. No otras puses, avotam ir arī savs apstrādes laiks. Piemēram – lietotājs domā, ko ievadīt kā ievadi.

Sapratīsim šādu piemēru.

Piemērs -

 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) 

Izvade:

 Time taken in seconds - 7.422671556472778 

Tagad mēs modificējam iepriekš minēto kodu, palaižot divus pavedienus.

Piemērs — 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) 

Izvade:

 Time taken in seconds - 6.90830135345459 

Kā redzam, abiem kodiem bija vajadzīgs vienāds laiks, lai pabeigtu. GIL neļāva CPU piesaistītajiem pavedieniem paralēli izpildīt otrajā kodā.

objekts Java

Kāpēc GIL vēl nav noņemts?

Daudziem programmētājiem ir sūdzības par to, taču Python nevar ieviest tik nozīmīgas izmaiņas kā GIL noņemšana. Vēl viens iemesls ir tas, ka GIL pašlaik nav uzlabots. Ja tas mainīsies Python 3, tas radīs nopietnas problēmas. Tā vietā, lai noņemtu GIL, GIL koncepcija var uzlaboties. Pēc Gvido van Rosoma teiktā -

'Es atzinīgi vērtēju Py3k ielāpu komplektu tikai tad, ja viena pavediena programmas (un vairāku pavedienu, bet ar I/O saistītai programmai) veiktspēja nemazinās.'

Ir pieejamas arī daudzas metodes, kas atrisina to pašu problēmu, ko atrisināja GIL, taču tās ir grūti ieviest.

Kā rīkoties ar Python GIL

Daudzapstrādes izmantošana ir vispiemērotākais veids, kā novērst programmu no GIL. Python piedāvā dažādus tulkus katram procesam, tāpēc šajā scenārijā katram procesam tiek nodrošināts viens pavediens vairāku apstrādi. Sapratīsim šādu piemēru.

Piemērs -

vlc multivides atskaņotāja lejupielāde youtube
 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) 

Izvade:

 Time taken in seconds - 3.3707828521728516 

Var šķist, ka ir palielināta pienācīga veiktspēja, taču procesu pārvaldībai ir savas pieskaitāmās izmaksas, un vairāki procesi ir smagāki par vairākiem pavedieniem.

Secinājums

Šajā apmācībā mēs esam apsprieduši GIL un to, kā mēs varam to izmantot. Tas ļauj kontrolēt vienu pavedienu, kas jāizpilda laikā. Šajā apmācībā tika apskatīts arī tas, kāpēc GIL ir svarīga Python programmētājiem.