Programmering

Hva er Cython? Python med hastigheten på C

Python har rykte på seg for å være et av de mest praktiske, rikt utstyrte og rett og slett nyttige programmeringsspråkene. Gjennomføringshastighet? Ikke så mye.

Gå inn i Cython. Cython-språket er et supersett av Python som kompileres til C, og gir ytelsesforbedringer som kan variere fra noen få prosent til flere størrelsesordener, avhengig av oppgaven. For arbeid som er bundet av Pythons opprinnelige objekttyper, vil ikke hastighetene være store. Men for numeriske operasjoner, eller andre operasjoner som ikke involverer Pythons egne interner, kan gevinsten være enorm.

Med Cython kan du skjøre mange av Pythons innfødte begrensninger eller overskride dem helt - uten å måtte gi opp Pythons enkelhet og bekvemmelighet. I denne artikkelen vil vi gå gjennom de grunnleggende konseptene bak Cython og lage et enkelt Python-program som bruker Cython til å akselerere en av funksjonene.

Relatert video: Bruke Cython for å øke hastigheten på Python

Kompiler Python til C

Python-kode kan ringe direkte til C-moduler. Disse C-modulene kan være enten generiske C-biblioteker eller biblioteker bygget spesielt for å fungere med Python. Cython genererer den andre typen modul: C-biblioteker som snakker med Pythons interne, og som kan leveres med eksisterende Python-kode.

Cython-kode ser ut som Python-kode, etter design. Hvis du mater Cython-kompilatoren med et Python-program (Python 2.x og Python 3.x støttes begge), vil Cython godta det som det er, men ingen av Cythons opprinnelige akselerasjoner vil komme til spill. Men hvis du dekorerer Python-koden med typekommentarer i Cythons spesielle syntaks, vil Cython kunne erstatte raske C-ekvivalenter for langsomme Python-objekter.

Merk at Cythons tilnærming ertrinnvis. Det betyr at en utvikler kan begynne med eneksisterende Python-applikasjonen, og øke hastigheten ved å gjøre flekkendringer i koden, i stedet for å omskrive hele applikasjonen fra grunnen av.

Denne tilnærmingen samsvarer med innholdet i problemene med programvareytelse generelt. I de fleste programmer er det store flertallet av CPU-intensiv kode konsentrert i noen få hotspots - en versjon av Pareto-prinsippet, også kjent som "80/20" -regelen. Dermed trenger det meste av koden i et Python-program ikke å være ytelsesoptimalisert, bare noen få kritiske deler. Du kan gradvis oversette disse hot spots til Cython, og så få ytelsesgevinster du trenger der det betyr mest. Resten av programmet kan forbli i Python for enkelhets skyld for utviklerne.

Hvordan bruke Cython

Vurder følgende kode, hentet fra Cythons dokumentasjon:

def f (x):

returner x ** 2-x

def integrate_f (a, b, N):

s = 0

dx = (b-a) / N

for jeg innen rekkevidde (N):

s + = f (a + i * dx)

returner s * dx

Dette er et leketøyeksempel, en ikke veldig effektiv implementering av en integrert funksjon. Som ren Python-kode er den treg, fordi Python må konvertere frem og tilbake mellom maskininnfødte numeriske typer og sine egne interne objekttyper.

Vurder nå Cython-versjonen av den samme koden, med Cythons tillegg understreket:

 cdef dobbel f ​​(dobbel x):

returner x ** 2-x

def integrate_f (doble a, doble b, int N):

cdef int i

cdef dobbel s, x, dx

s = 0

dx = (b-a) / N

for jeg innen rekkevidde (N):

s + = f (a + i * dx)

returner s * dx

Hvis vi eksplisitt erklærer variabeltypene, både for funksjonsparametrene og variablene som brukes i hoveddelen av funksjonen (dobbelt, intosv.), vil Cython oversette alt dette til C. Vi kan også bruke cdef nøkkelord for å definere funksjoner som primært er implementert i C for ekstra hastighet, selv om disse funksjonene bare kan kalles av andre Cython-funksjoner og ikke av Python-skript. (Bare i eksemplet ovenfor integrer_f kan kalles med et annet Python-skript.)

Legg merke til hvor lite vårt faktiskekode har endret seg. Alt vi har gjort er å legge til typedeklarasjoner i eksisterende kode for å få et betydelig ytelsesløft.

Cython fordeler

Bortsett fra å kunne øke hastigheten på koden du allerede har skrevet, gir Cython flere andre fordeler:

Arbeidet med eksterne C-biblioteker kan gå raskere

Python-pakker som NumPy pakker C-biblioteker i Python-grensesnitt for å gjøre dem enkle å jobbe med. Imidlertid kan det gå tregere å gå frem og tilbake mellom Python og C gjennom disse innpakningene. Cython lar deg snakke direkte med de underliggende bibliotekene, uten Python i veien. (C ++ biblioteker støttes også.)

Du kan bruke både C og Python-minnehåndtering

Hvis du bruker Python-objekter, er de minnestyrt og søppel samlet på samme måte som i vanlig Python. Men hvis du vil lage og administrere dine egne C-nivå strukturer, og bruke malloc/gratis for å jobbe med dem, kan du gjøre det. Bare husk å rydde opp etter deg selv.

Du kan velge sikkerhet eller hastighet etter behov

Cython utfører automatisk kjøretidskontroller for vanlige problemer som dukker opp i C, for eksempel tilgang utenfor en grense på en matrise, ved hjelp av dekoratører og kompilatordirektiv (f.eks. @boundscheck (Falsk)). Derfor er C-kode generert av Cython mye tryggere som standard enn håndrullet C-kode, men potensielt på bekostning av rå ytelse.

Hvis du er sikker på at du ikke trenger sjekkene under kjøretid, kan du deaktivere dem for ekstra hastighetsøkninger, enten over en hel modul eller bare for utvalgte funksjoner.

Cython lar deg også få tilgang til Python-strukturer som bruker bufferprotokollen for direkte tilgang til data lagret i minnet (uten mellomkopiering). Med Cythons minnesyn kan du jobbe med disse strukturene i høy hastighet og med sikkerhetsnivået som passer til oppgaven. For eksempel kan rådataene som ligger til grunn for en Python-streng leses på denne måten (raskt) uten å måtte gå gjennom Python-kjøretiden (langsom).

Cython C-kode kan ha nytte av å frigjøre GIL

Pythons Global Interpreter Lock, eller GIL, synkroniserer tråder i tolken, beskytter tilgangen til Python-objekter og styrer striden om ressurser. Men GIL har blitt mye kritisert som en snublestein for en bedre ytelse av Python, spesielt på flerkjernesystemer.

Hvis du har en seksjon med kode som ikke refererer til Python-objekter og utfører en langvarig operasjon, kan du merke den medmed nogil: direktivet for å la det kjøre uten GIL. Dette frigjør Python-tolken til å gjøre andre ting, og lar Cython-koden bruke flere kjerner (med tilleggsarbeid).

Cython kan bruke Python-type hinting-syntaks

Python har en typevisende syntaks som hovedsakelig brukes av linters og code checkers, i stedet for CPython-tolk. Cython har sin egen tilpassede syntaks for kodedekorasjoner, men med de siste revisjonene av Cython kan du bruke Python-type-hinting-syntaks for å gi grunnleggende typetips til Cython også.

Cython kan brukes til å skjule sensitiv Python-kode

Python-moduler er trivielt enkle å dekompilere og inspisere, men kompilerte binærfiler er ikke. Når du distribuerer et Python-program til sluttbrukere, hvis du vil beskytte noen av modulene mot uformell snooping, kan du gjøre det ved å kompilere dem med Cython. Merk, skjønt, dette er en bivirkning av Cythons muligheter, ikke en av dens tiltenkte funksjoner.

Cython begrensninger

Husk at Cython ikke er en tryllestav. Det gjør ikke automatisk hver forekomst av poky Python-kode til sizzling-rask C-kode. For å få mest mulig ut av Cython, må du bruke det med omhu - og forstå begrensningene:

Lite hastighet for konvensjonell Python-kode

Når Cython støter på Python-kode, kan den ikke oversettes til C, den forvandler den koden til en serie C-samtaler til Pythons interner. Dette tilsvarer å ta Pythons tolk ut av utførelsessløyfen, som gir koden en beskjeden hastighet på 15 til 20 prosent som standard. Merk at dette er et best case-scenario; i noen situasjoner ser du kanskje ingen ytelsesforbedring eller til og med en ytelsesforringelse.

Lite hastighet for innfødte Python-datastrukturer

Python tilbyr en rekke datastrukturer - strenger, lister, tupler, ordbøker og så videre. De er veldig praktiske for utviklere, og de kommer med sin egen automatiske minneadministrasjon. Men de er tregere enn ren C.

Med Cython kan du fortsette å bruke alle Python-datastrukturene, men uten mye hastighet. Dette er igjen fordi Cython ganske enkelt kaller C API-er i Python-kjøretiden som oppretter og manipulerer disse objektene. Dermed oppfører Python-datastrukturer seg som Cython-optimalisert Python-kode generelt: Noen ganger får du et løft, men bare litt. For best resultat, bruk C-variabler og strukturer. Den gode nyheten er at Cython gjør det enkelt å jobbe med dem.

Cython-kode går raskest når “ren C”

Hvis du har en funksjon i C merket med cdef søkeord, med alle dets variabler og innebygde funksjonsanrop til andre ting som er ren C, vil den løpe så fort C kan gå. Men hvis denne funksjonen refererer til en hvilken som helst Python-innfødt kode, som en Python-datastruktur eller et anrop til en intern Python API, vil den samtalen være en ytelsesflaskehals.

Heldigvis gir Cython en måte å få øye på disse flaskehalsene: en kildekoderapport som på et øyeblikk viser hvilke deler av Cython-appen din som er ren C og hvilke deler som interagerer med Python. Jo bedre optimalisert appen, jo mindre interaksjon vil det være med Python.

Cython NumPy

Cython forbedrer bruken av C-baserte tredjepartsbaserte nummerbaserte biblioteker som NumPy. Fordi Cython-kode kompileres til C, kan den samhandle med disse bibliotekene direkte, og ta Pythons flaskehalser ut av sløyfen.

Men spesielt NumPy fungerer bra med Cython. Cython har innfødt støtte for spesifikke konstruksjoner i NumPy og gir rask tilgang til NumPy-matriser. Og den samme kjente NumPy-syntaksen du bruker i et konvensjonelt Python-skript, kan brukes i Cython som den er.

Men hvis du vil lage nærmest mulige bindinger mellom Cython og NumPy, må du dekorere koden ytterligere med Cythons tilpassede syntaks. Decimport uttalelse, for eksempel, lar Cython-kode se C-nivå konstruksjoner i biblioteker på kompileringstid for raskest mulige bindinger.

Siden NumPy er så mye brukt, støtter Cython NumPy "out of the box." Hvis du har NumPy installert, kan du bare oppgicimport nummen i koden din, og legg deretter til ytterligere dekorasjon for å bruke de eksponerte funksjonene.

Cython-profilering og ytelse

Du får best ytelse fra hvilken som helst kode ved å profilere den og se på førstehånd hvor flaskehalsene er. Cython gir kroker til Pythons cProfile-modul, slik at du kan bruke Pythons egne profileringsverktøy, som cProfile, for å se hvordan Cython-koden din fungerer.

Det hjelper å huske i alle tilfeller at Cython ikke er magisk - at fornuftige ytelsespraksis fremdeles gjelder. Jo mindre du skysser frem og tilbake mellom Python og Cython, desto raskere vil appen din kjøre.

For eksempel, hvis du har en samling objekter du vil behandle i Cython, må du ikke iterere over den i Python og påkalle en Cython-funksjon ved hvert trinn. Sende hele samlingen til Cython-modulen din og gjenta den der. Denne teknikken brukes ofte i biblioteker som administrerer data, så det er en god modell å etterligne i din egen kode.

Vi bruker Python fordi det gir programmerer praktisk og muliggjør rask utvikling. Noen ganger kommer programmørproduktiviteten på bekostning av ytelsen. Med Cython kan bare litt ekstra innsats gi deg det beste fra begge verdener.

Les mer om Python

  • Hva er Python? Kraftig, intuitiv programmering
  • Hva er PyPy? Raskere Python uten smerter
  • Hva er Cython? Python med hastigheten på C
  • Cython tutorial: Hvordan øke hastigheten på Python
  • Slik installerer du Python på den smarte måten
  • De beste nye funksjonene i Python 3.8
  • Bedre Python-prosjektledelse med poesi
  • Virtualenv og venv: Python virtuelle miljøer forklart
  • Python virtualenv og venv do’s and don'ts
  • Python-tråder og underprosesser forklart
  • Hvordan bruke Python-feilsøkingsprogrammet
  • Hvordan bruke timeit til å profilere Python-kode
  • Hvordan bruke cProfile for å profilere Python-kode
  • Kom i gang med asynkronisering i Python
  • Hvordan bruke asyncio i Python
  • Slik konverterer du Python til JavaScript (og tilbake igjen)
  • Python 2 EOL: Hvordan overleve slutten av Python 2
  • 12 pytoner for ethvert programmeringsbehov
  • 24 Python-biblioteker for alle Python-utviklere
  • 7 søte Python IDEer du kanskje har savnet
  • 3 store Python-mangler - og deres løsninger
  • 13 Python-nettrammer sammenlignet
  • 4 Python-testrammer for å knuse feilene dine
  • 6 flotte nye Python-funksjoner du ikke vil gå glipp av
  • 5 Python-distribusjoner for å mestre maskinlæring
  • 8 flotte Python-biblioteker for naturlig språkbehandling
$config[zx-auto] not found$config[zx-overlay] not found