Programmering

Multicore Python: Et tøft, verdig og oppnåelig mål

For alle Pythons flotte og praktiske funksjoner forblir ett mål utenfor rekkevidde: Python-apper som kjører på CPython-referansetolken og bruker flere CPU-kjerner parallelt.

Dette har lenge vært en av Pythons største snublesteiner, spesielt siden alle løsningene er klønete. Det haster med å finne en langsiktig løsning på problemet vokser, særlig ettersom kjerneteller på prosessorer fortsetter å øke (se Intels 24-kjerners behemoth).

En lås for alle

I sannhet er det mulig å bruke tråder i Python-applikasjoner - mange av dem gjør det allerede. Hva er det?ikke mulig er at CPython kjører flertrådede applikasjoner med hver tråd som kjøres parallelt på en annen kjerne. CPythons interne minnestyring er ikke trådsikker, så tolken kjører bare en tråd om gangen, bytter mellom dem etter behov og kontrollerer tilgangen til den globale staten.

Denne låsemekanismen, Global Interpreter Lock (GIL), er den største enkeltårsaken til at CPython ikke kan kjøre tråder parallelt. Det er noen formildende faktorer; for eksempel er I / O-operasjoner som disk- eller nettverksavlesning ikke bundet av GIL, slik at de kan kjøre fritt i sine egne tråder. Men alt både flertrådet og CPU-bundet er et problem.

For Python-programmerere betyr dette at tunge beregningsoppgaver som har fordeler av å være spredt over flere kjerner, ikke fungerer bra, og sperrer ikke bruken av et eksternt bibliotek. Bekvemmeligheten ved å jobbe i Python har store ytelseskostnader, som blir vanskeligere å svelge ettersom raskere, like praktiske språk som Googles Go kommer i forgrunnen.

Velg låsen

Over tid har det dukket opp en rekke alternativer som forbedrer - men ikke eliminerer - grensene for GIL. En standard taktikk er å starte flere forekomster av CPython og dele sammenheng og tilstand mellom dem; hver forekomst kjører uavhengig av den andre i en egen prosess. Men som Jeff Knupp forklarer, kan gevinsten ved å løpe parallelt gå tapt ved den innsatsen som trengs for å dele tilstanden, så denne teknikken er best egnet til langvarige operasjoner som samler resultatene over tid.

C-utvidelser er ikke bundet av GIL, så mange biblioteker for Python som trenger hastighet (for eksempel matte- og statistikkbiblioteket Numpy) kan kjøre på tvers av flere kjerner. Men begrensningene i selve CPython forblir. Hvis den beste måten å unngå GIL er å bruke C, vil det føre flere programmerere bort fra Python og mot C.

PyPy, Python-versjonen som kompilerer kode via JIT, blir ikke kvitt GIL, men gjør opp for det ved å bare ha koden raskere. På noen måter er dette ikke en dårlig erstatning: Hvis hastighet er hovedårsaken til at du har sett flertråding, kan PyPy kanskje gi hastigheten uten komplikasjoner av flertråding.

Til slutt ble GIL selv omarbeidet noe i Python 3, med en bedre trådbryterhåndterer. Men alle de underliggende forutsetningene - og begrensningene - forblir. Det er fremdeles en GIL, og den holder fremdeles opp.

Ingen GIL? Ikke noe problem

Til tross for alt dette fortsetter søken etter en GIL-mindre Python, kompatibel med eksisterende applikasjoner. Andre implementeringer av Python har gjort unna GIL helt, men til en pris. Jython, for eksempel, løper på toppen av JVM og bruker JVMs objektsporingssystem i stedet for GIL. IronPython tar samme tilnærming via Microsofts CLR. Men begge lider av inkonsekvent ytelse, og de går noen ganger mye tregere enn CPython. De kan heller ikke lett grensesnitt med ekstern C-kode, så mange eksisterende Python-applikasjoner vil ikke fungere.

PyParallel, et prosjekt opprettet av Trent Nelson fra Continuum Analytics, er en "eksperimentell, proof-of-concept-gaffel av Python 3 designet for å utnytte flere CPU-kjerner optimalt." Det fjerner ikke GIL, men forbedrer effekten ved å erstatte asynkronisering modul, så apper som brukerasynkronisering for parallellisme (for eksempel flertrådet I / O som en webserver) er mest fordelaktig. Prosjektet har ligget i dvale i flere måneder, men dokumentasjonen sier at utviklerne er komfortable med å ta seg tid til å få det riktig, så det kan til slutt bli inkludert i CPython: "Det er ikke noe galt med sakte og stødig så lenge du er på vei i riktig retning. "

Et langvarig prosjekt av PyPys skapere har vært en versjon av Python som bruker en teknikk som kalles "software transactional memory" (PyPy-STM). Ifølge PyPys skapere er fordelen "du kan gjøre mindre tilpasninger av dine eksisterende, ikke-multitrådede programmer og få dem til å bruke flere kjerner."

PyPy-STM høres ut som magi, men den har to ulemper. For det første er det et pågående arbeid som for øyeblikket bare støtter Python 2.x, og for det andre tar det fortsatt et ytelseshit for applikasjoner som kjører på en enkelt kjerne. Siden en av bestemmelsene sitert av Python-skaperen Guido van Rossum for ethvert forsøk på å fjerne GIL fra CPython, er at erstatningen ikke skal forringe ytelsen for enkeltkjerne applikasjoner med en tråd, vil en løsning som dette ikke lande i CPython i sin nåværende tilstand.

Skynd deg og vent

Larry Hastings, en kjerne Python-utvikler, delte noen av sine synspunkter på PyCon 2016 om hvordan GIL kunne fjernes. Hastings dokumenterte sine forsøk på å fjerne GIL og endte dermed med en versjon av Python som ikke hadde GIL, men løp plagsomt sakte på grunn av konstante cache-savner.

Du kan miste GIL, oppsummerte Hastings, men du må ha en eller annen måte å garantere at bare en tråd om gangen endrer globale objekter - for eksempel ved å ha en dedikert tråd i tolken som håndterer slike tilstandsendringer.

Et stykke langsiktige gode nyheter er at hvis og når CPython kaster GIL, vil utviklere som bruker språket allerede være primet for å utnytte multitråding. Mange endringer nå bakt inn i Pythons syntaks, som køer og asynkronisering/avvente nøkkelord for Python 3.5, gjør det enkelt å fordele oppgaver på tvers av kjerner på høyt nivå.

Likevel garanterer mengden arbeid som trengs for å gjøre Python GIL-mindre, men at den først vises i en separat implementering som PyPy-STM. De som ønsker å prøve et GIL-mindre system kan gjøre det gjennom en slik tredjepartsinnsats, men den opprinnelige CPython vil sannsynligvis forbli uberørt for nå. Her håper ventetiden ikke er lenger.

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