Ohjelmointi

Moniytiminen Python: Kova, kelvollinen ja saavutettavissa oleva tavoite

Kaikille Pythonin upeille ja käteville ominaisuuksille yksi tavoite ei ole saavutettavissa: Python-sovellukset, jotka toimivat CPython-viitetulkilla ja käyttävät useita CPU-ytimiä rinnakkain.

Tämä on pitkään ollut yksi Pythonin suurimmista kompastuskivistä, varsinkin kun kaikki kiertotavat ovat kömpelöitä. Kiireellisyys löytää pitkäaikainen ratkaisu ongelmaan kasvaa, etenkin kun prosessoreiden ydinlaskenta kasvaa edelleen (ks. Intelin 24-ytiminen behemoth).

Yksi lukko kaikille

Todellisuudessa on mahdollista käyttää ketjuja Python-sovelluksissa - monet niistä jo tekevät. Mitä?ei on mahdollista, että CPython suorittaa monisäikeisiä sovelluksia jokaisen ketjun suorituksen yhteydessä rinnakkain eri ytimessä. CPythonin sisäinen muistihallinta ei ole langattomasti turvallinen, joten tulkki suorittaa vain yhden ketjun kerrallaan, vaihtamalla niiden välillä tarpeen mukaan ja valvomalla pääsyä globaaliin tilaan.

Tämä lukitusmekanismi, Global Interpreter Lock (GIL), on ainoa suurin syy siihen, miksi CPython ei voi suorittaa ketjuja rinnakkain. On joitain lieventäviä tekijöitä; esimerkiksi I / O-toiminnot, kuten levyn tai verkon lukeminen, eivät ole GIL-sidottuja, joten ne voivat toimia vapaasti omissa säikeissään. Mutta kaikki sekä monisäikeinen että suorittimeen sidottu on ongelma.

Python-ohjelmoijille tämä tarkoittaa, että raskaat laskennalliset tehtävät, jotka hyötyvät jakautumisesta useisiin ytimiin, eivät toimi hyvin, mikä estää ulkoisen kirjaston käytön. Pythonissa työskentelyn mukavuudesta aiheutuu suuria suorituskykykustannuksia, joita on yhä vaikeampaa niellä, kun nopeammat, yhtä kätevät kielet kuin Google's Go tulevat esiin.

Valitse lukko

Ajan myötä on tullut joukko vaihtoehtoja, jotka parantavat - mutta eivät poista - GIL: n rajoja. Yksi tavallinen taktiikka on käynnistää useita CPython-esiintymiä ja jakaa konteksti ja tila niiden välillä; kukin esiintymä toimii toisistaan ​​riippumatta erillisessä prosessissa. Mutta kuten Jeff Knupp selittää, rinnakkaisajon tarjoamat voitot voidaan menettää tilan jakamiseen tarvittavilla ponnisteluilla, joten tämä tekniikka soveltuu parhaiten pitkäaikaisiin operaatioihin, joissa tulokset yhdistetään ajan myötä.

GIL ei sido C-laajennuksia, joten monet Pythonin kirjastot, jotka tarvitsevat nopeutta (kuten Numpy-matematiikka- ja tilastokirjasto), voivat kulkea useiden ytimien yli. Mutta itse CPythonin rajoitukset pysyvät. Jos paras tapa välttää GIL on käyttää C: tä, se ajaa enemmän ohjelmoijia pois Pythonista ja kohti C.

PyPy, Python-versio, joka kokoaa koodin JIT: n kautta, ei pääse eroon GIL: stä, mutta korvaa sen yksinkertaisesti antamalla koodin suorittaa nopeammin. Joillakin tavoin tämä ei ole huono korvike: Jos nopeus on tärkein syy, miksi olet katsonut monisäikeisyyttä, PyPy saattaa pystyä tarjoamaan nopeuden ilman monimutkaisen monimutkaisen monimutkaisuuden.

Lopuksi GIL itse muokattiin jonkin verran Python 3: ssa paremmalla langankytkimen käsittelijällä. Mutta kaikki sen oletukset - ja rajoitukset - pysyvät. GIL on edelleen olemassa, ja se viivästyttää edelleen menettelyä.

Ei GIL: ää? Ei ongelmaa

Kaikesta tästä huolimatta pyrkimys nykyisiin sovelluksiin yhteensopivaan GIL: ää sisältämättömään Pythoniin jatkuu. Muut Pythonin toteutukset ovat poistaneet GIL: n kokonaan, mutta kustannuksella. Esimerkiksi Jython juoksee JVM: n päällä ja käyttää JVM: n objektinseurantajärjestelmää GIL: n sijaan. IronPython noudattaa samaa lähestymistapaa Microsoftin CLR: n kautta. Mutta molemmat kärsivät epäjohdonmukaisesta suorituskyvystä, ja joskus ne toimivat paljon hitaammin kuin CPython. Ne eivät myöskään voi helposti liittyä ulkoiseen C-koodiin, joten monet olemassa olevat Python-sovellukset eivät toimi.

PyParallel, Trent Nelsonin, Continuum Analyticsista luoma projekti, on "kokeellinen, käytännöllinen Python 3 -haarukka, joka on suunniteltu hyödyntämään optimaalisesti useita suorittimen ytimiä". Se ei poista GIL: ää, mutta lieventää sen vaikutusta korvaamalla GIL asynkronoitu moduuli, joten sovellukset, jotka käyttävätasynkronoitu rinnakkaisuudesta (kuten monisäikeinen I / O kuten verkkopalvelin) on eniten hyötyä. Projekti on ollut lepotilassa useita kuukausia, mutta sen dokumentaatiossa todetaan, että sen kehittäjät viettävät mukavasti aikaa saadakseen sen oikein, joten se voidaan lopulta sisällyttää CPythoniin: "Hitaalla ja tasaisella ei ole mitään vikaa niin kauan kuin olet menossa oikeaan suuntaan. "

Yksi PyPyn luojien pitkäaikainen projekti on ollut Python-versio, joka käyttää tekniikkaa nimeltä "ohjelmiston transaktiomuisti" (PyPy-STM). PyPyn luojien mukaan etuna on "voit tehdä pieniä parannuksia olemassa oleviin, monisäikeisiin ohjelmiin ja saada ne käyttämään useita ytimiä".

PyPy-STM kuulostaa taikuudelta, mutta sillä on kaksi haittapuolta. Ensinnäkin, se on keskeneräinen työ, joka tällä hetkellä tukee vain Python 2.x: tä, ja toiseksi se vie edelleen suorituskyvyn osuman sovelluksille, jotka toimivat yhdessä ytimessä. Koska yksi Python-luojan Guido van Rossumin mainitsemista ehdoista yrittää poistaa GIL CPythonista on, että sen korvaaminen ei saisi heikentää suorituskykyä yhden ytimen, yksisäikeisissä sovelluksissa, tällainen korjaus ei laske CPythoniin sen nykyisessä tilassa.

Kiire ja odota

Larry Hastings, Pythonin ydinkehittäjä, jakoi joitain näkemyksiään PyCon 2016: ssa siitä, kuinka GIL voitaisiin poistaa. Hastings dokumentoi yrityksensä poistaa GIL ja teki näin Python-version, jolla ei ollut GIL: ää, mutta joka juoksi tuskallisen hitaasti jatkuvien välimuistihäviöiden takia.

Voit menettää GIL: n, Hastings tiivistää, mutta sinulla on oltava jokin tapa taata, että vain yksi ketju kerrallaan muokkaa globaaleja objekteja - esimerkiksi siten, että tulkkissa on oma ketju hoitamaan tällaisia ​​tilamuutoksia.

Yksi pitkäaikainen hyvä uutinen on, että jos ja kun CPython irrottaa GIL: n, kieltä käyttävät kehittäjät ovat jo valmiita hyödyntämään monisäikeisyyttä. Monet muutokset ovat nyt leipoutuneet Pythonin syntaksiksi, kuten jonot ja asynkronoitu/odottaa avainsanat Python 3.5: lle, helpottavat tehtävien jakamista ytimien välillä korkealla tasolla.

Silti työmäärä, joka tarvitaan Pythonin GIL-vähemmän tekemiseen, mutta takaa, että se näkyy ensin erillisessä toteutuksessa, kuten PyPy-STM. Ne, jotka haluavat kokeilla GIL-järjestelmää, voivat tehdä niin kolmannen osapuolen pyrkimyksillä, mutta alkuperäinen CPython on todennäköisesti toistaiseksi koskematon. Toivomme, että odotus ei ole paljon pidempi.