Programiranje

Večjedrni Python: Težek, vreden in dosegljiv cilj

Za vse odlične in priročne funkcije Pythona en cilj ostaja nedosegljiv: aplikacije Python, ki se izvajajo na referenčnem tolmaču CPython in vzporedno uporabljajo več jeder CPU.

To je že dolgo največji kamen spotike Pythona, še posebej, ker so vse rešitve okorne. Nujnost iskanja dolgoročne rešitve vprašanja narašča, zlasti ker se število procesorjev še naprej povečuje (glej Intelov 24-jedrni behemoth).

Ena ključavnica za vse

V resnici je v aplikacijah Python mogoče uporabljati niti - veliko jih že. Kajne je mogoče, da CPython zažene večnitne aplikacije z vsako izvedbo niti vzporedno na drugem jedru. CPythonovo upravljanje notranjega pomnilnika ni varno z nitmi, zato tolmač hkrati izvaja samo eno nit, po potrebi preklaplja med njimi in nadzoruje dostop do globalnega stanja.

Ta mehanizem za zaklepanje, Global Interpreter Lock (GIL), je največji razlog, zakaj CPython ne more vzporedno izvajati niti. Obstaja nekaj olajševalnih dejavnikov; na primer V / I operacije, kot so branje diskov ali omrežja, niso vezane na GIL, zato lahko te prosto tečejo v svojih nitih. Toda karkoli večnitnega in vezanega na CPU je težava.

Za programerje Pythona to pomeni, da težke računske naloge, ki jim koristi razporeditev po več jedrih, ne delujejo dobro, kar prepoveduje uporabo zunanje knjižnice. Priročnost dela v Pythonu povzroča velike stroške zmogljivosti, ki jih je vse težje pogoltniti, saj v ospredje stopijo hitrejši, enako priročni jeziki, kot je Googlov Go.

Izberi ključavnico

Sčasoma se je pojavilo ogromno možnosti, ki izboljšajo - vendar ne odpravijo - meje GIL. Ena standardna taktika je zagon več primerkov CPython in izmenjava konteksta in stanja med njimi; vsak primerek teče neodvisno od drugega v ločenem procesu. A kot pojasnjuje Jeff Knupp, lahko dobiček, ki ga zagotavlja vzporedno izvajanje, izgubi prizadevanje, potrebno za skupno rabo stanja, zato je ta tehnika najbolj primerna za dolgotrajne operacije, ki sčasoma združujejo svoje rezultate.

Razširitve C niso vezane na GIL, zato lahko številne knjižnice za Python, ki potrebujejo hitrost (na primer knjižnica matematike in statistike Numpy), delujejo na več jedrih. Toda omejitve samega CPythona ostajajo. Če se GIL-u najboljše izognemo, če uporabimo C, bo to odgnalo več programerjev stran od Pythona in proti C.

PyPy, različica Pythona, ki prevaja kodo prek JIT, se GIL-a ne znebi, ampak ga nadoknadi s preprostim hitrejšim izvajanjem kode. Na nek način to ni slab nadomestek: če je hitrost glavni razlog, da ste opazovali večnitnost, bo PyPy morda lahko zagotovil hitrost brez zapletov večnitnosti.

Končno je bil sam GIL nekoliko predelan v Pythonu 3, z boljšim upravljalnikom za preklapljanje niti. Toda vse temeljne predpostavke - in omejitve - ostajajo. Še vedno obstaja GIL in še vedno vodi postopke.

Brez GIL-a? Ni problema

Kljub vsemu se prizadevanje za Python brez GIL, združljiv z obstoječimi aplikacijami, nadaljuje. Druge izvedbe Pythona so GIL v celoti odpravile, vendar s svojo ceno. Jython, na primer, deluje na vrhu JVM in namesto GIL uporablja sistem za sledenje predmetom JVM. IronPython ima enak pristop prek Microsoftovega CLR. Toda oba trpijo zaradi nedosledne zmogljivosti in včasih tečejo veliko počasneje kot CPython. Prav tako se ne morejo zlahka povezati z zunanjo kodo C, zato številne obstoječe aplikacije Python ne bodo delovale.

PyParallel, projekt, ki ga je ustvaril Trent Nelson iz podjetja Continuum Analytics, je "eksperimentalna preizkusna vilica Pythona 3, zasnovana za optimalno izkoriščanje več procesorskih jeder." GIL-a ne odstrani, izboljša pa njegov učinek z zamenjavo asinh modul, torej aplikacije, ki uporabljajoasinh za paralelnost (na primer večnitni V / I kot spletni strežnik) ima največ koristi. Projekt že nekaj mesecev miruje, vendar njegova dokumentacija navaja, da si njegovi razvijalci lahko vzamejo čas, da ga popravijo, tako da ga je sčasoma mogoče vključiti v CPython: "Nič ni narobe s počasnim in stabilnim, dokler greš v pravo smer. "

Eden od dolgoletnih projektov ustvarjalcev PyPy je bila različica Pythona, ki uporablja tehniko, imenovano "programski transakcijski pomnilnik" (PyPy-STM). Po besedah ​​ustvarjalcev PyPy je prednost v tem, da "lahko obstoječe programe, ki niso večnitni, naredijo manjše spremembe in jih prisilijo, da uporabljajo več jeder."

PyPy-STM zveni čarobno, ima pa dve pomanjkljivosti. Prvič, to je delo v teku, ki trenutno podpira samo Python 2.x, in drugič, še vedno zahteva uspešnost za aplikacije, ki se izvajajo v enem jedru. Ker je ena izmed določb, ki jih je ustvarjalec Pythona Guido van Rossum navedel za kakršne koli poskuse odstranitve GIL-a iz CPythona, ta, da njegova nadomestitev ne bi smela poslabšati zmogljivosti enojedrnih, enonitnih aplikacij, takšen popravek v CPythonu ne bo prispel v sedanjem stanju.

Pohiti in počakaj

Larry Hastings, osrednji razvijalec Pythona, je na PyCon 2016 delil nekaj svojih stališč o tem, kako je mogoče odstraniti GIL. Hastings je dokumentiral svoje poskuse odstranitve GIL-a in pri tem končal z različico Pythona, ki ni imela GIL-a, a je zaradi nenehnih napak v predpomnilniku tekla mučno počasi.

Lahko izgubite GIL, je povzel Hastings, vendar morate imeti način, s katerim zagotovite, da samo ena nit naenkrat spreminja globalne predmete - na primer z namensko nitjo v tolmaču, ki obravnava takšne spremembe stanja.

Dolgoročna dobra novica je, da bodo razvijalci, ki uporabljajo jezik, že pripravljeni na uporabo večnitnosti, če in ko CPython izgubi GIL. Številne spremembe so zdaj vključene v sintakso Pythona, na primer čakalne vrste in asinh/čakati ključne besede za Python 3.5 omogočajo enostavno razporeditev nalog med jedri na visoki ravni.

Kljub temu pa bo potrebno veliko dela, da bo Python brez GIL-a vse prej kot zagotovil, da bo prikazan najprej v ločeni izvedbi, kot je PyPy-STM. Tisti, ki želijo preizkusiti sistem brez GIL, lahko to storijo s takšnimi prizadevanji tretjih oseb, vendar bo prvotni CPython za zdaj verjetno ostal nedotaknjen. Tu upamo, da čakanje še ni dolgo.

$config[zx-auto] not found$config[zx-overlay] not found