Programmering

Hvad er Cython? Python med C-hastighed

Python har ry for at være et af de mest bekvemme, rigt udstyrede og ligefrem nyttige programmeringssprog. Udførelseshastighed? Ikke så meget.

Gå ind i Cython. Cython-sproget er et supersæt af Python, der kompileres til C, hvilket giver ydeevne boosts, der kan variere fra et par procent til flere størrelsesordener, afhængigt af den aktuelle opgave. For arbejde, der er bundet af Pythons oprindelige objekttyper, vil speedups ikke være store. Men for numeriske operationer eller andre operationer, der ikke involverer Pythons egne interner, kan gevinsterne være enorme.

Med Cython kan du overføre mange af Pythons oprindelige begrænsninger eller overskride dem helt - uden at skulle opgive Pythons lethed og bekvemmelighed. I denne artikel gennemgår vi de grundlæggende koncepter bag Cython og opretter en simpel Python-applikation, der bruger Cython til at fremskynde en af ​​dens funktioner.

Relateret video: Brug af Cython til at fremskynde Python

Kompilér Python til C

Python-kode kan foretage opkald direkte til C-moduler. Disse C-moduler kan enten være generiske C-biblioteker eller biblioteker bygget specielt til at arbejde med Python. Cython genererer den anden type modul: C-biblioteker, der taler med Pythons interner, og som kan bundtes med eksisterende Python-kode.

Cython-kode ligner meget Python-kode efter design. Hvis du fodrer Cython-kompilatoren med et Python-program (Python 2.x og Python 3.x understøttes begge), accepterer Cython det som det er, men ingen af ​​Cythons native accelerationer kommer i spil. Men hvis du dekorerer Python-koden med typebetegnelser i Cythons specielle syntaks, vil Cython være i stand til at erstatte hurtige C-ækvivalenter med langsomme Python-objekter.

Bemærk, at Cythons tilgang erinkrementel. Det betyder, at en udvikler kan begynde med eneksisterende Python-applikation, og fremskynd den ved at foretage punktændringer i koden i stedet for at omskrive hele applikationen fra bunden.

Denne tilgang stemmer overens med arten af ​​problemer med softwareydelse generelt. I de fleste programmer er langt størstedelen af ​​CPU-intensiv kode koncentreret i nogle få hot spots - en version af Pareto-princippet, også kendt som "80/20" -reglen. Således behøver det meste af koden i et Python-program ikke at blive ydeevneoptimeret, bare et par kritiske stykker. Du kan gradvist oversætte disse hot spots til Cython, og så få de præstationsgevinster, du har brug for, hvor det betyder mest. Resten af ​​programmet kan forblive i Python af hensyn til udviklerne.

Sådan bruges Cython

Overvej følgende kode hentet fra Cythons dokumentation:

def f (x):

returnere x ** 2-x

def integrere_f (a, b, N):

s = 0

dx = (b-a) / N

for jeg inden for rækkevidde (N):

s + = f (a + i * dx)

returner s * dx

Dette er et legetøjseksempel, en ikke særlig effektiv implementering af en integreret funktion. Som ren Python-kode er den langsom, fordi Python skal konvertere frem og tilbage mellem maskinindfødte numeriske typer og dens egne interne objekttyper.

Overvej nu Cython-versionen af ​​den samme kode, med Cythons tilføjelser understreget:

 cdef dobbelt f (dobbelt x):

returnere x ** 2-x

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

cdef int i

cdef dobbelt s, x, dx

s = 0

dx = (b-a) / N

for jeg inden for rækkevidde (N):

s + = f (a + i * dx)

returner s * dx

Hvis vi eksplicit erklærer variabeltyperne, både for funktionsparametrene og de variabler, der bruges i funktionens brødtekst (dobbelt, intosv.), Cython oversætter alt dette til C. Vi kan også bruge cdef nøgleord for at definere funktioner, der primært implementeres i C for yderligere hastighed, selvom disse funktioner kun kan kaldes af andre Cython-funktioner og ikke af Python-scripts. (Kun i ovenstående eksempel integrer_f kan kaldes med et andet Python-script.)

Bemærk, hvor lidt vores faktiske erkode har ændret. Alt hvad vi har gjort er at tilføje typedeklarationer til eksisterende kode for at få et betydeligt præstationsforøg.

Cython fordele

Bortset fra at være i stand til at fremskynde den kode, du allerede har skrevet, giver Cython flere andre fordele:

Arbejdet med eksterne C-biblioteker kan gå hurtigere

Python-pakker som NumPy indpakker C-biblioteker i Python-grænseflader for at gøre dem nemme at arbejde med. At gå frem og tilbage mellem Python og C gennem disse indpakninger kan dog bremse tingene. Cython lader dig tale direkte med de underliggende biblioteker uden Python i vejen. (C ++ biblioteker understøttes også.)

Du kan bruge både C og Python-hukommelsesstyring

Hvis du bruger Python-objekter, er de hukommelsesstyret og indsamlet skrald det samme som i almindelig Python. Men hvis du vil oprette og administrere dine egne strukturer på C-niveau og bruge dem malloc/ledig at arbejde med dem, kan du gøre det. Husk bare at rydde op efter dig selv.

Du kan vælge sikkerhed eller hastighed efter behov

Cython udfører automatisk runtime-kontrol af almindelige problemer, der dukker op i C, såsom adgang uden for grænserne på en matrix ved hjælp af dekoratører og compiler-direktiver (f.eks. @boundscheck (Falsk)). Derfor er C-kode genereret af Cython meget sikrere som standard end håndrullet C-kode, dog potentielt på bekostning af rå ydelse.

Hvis du er sikker på, at du ikke har brug for disse kontroller under kørsel, kan du deaktivere dem for yderligere hastighedsgevinster, enten på tværs af et helt modul eller kun på udvalgte funktioner.

Cython giver dig også mulighed for indbygget adgang til Python-strukturer, der bruger bufferprotokollen til direkte adgang til data, der er gemt i hukommelsen (uden mellemliggende kopiering). Cythons hukommelsesvisninger giver dig mulighed for at arbejde med disse strukturer i høj hastighed og med det sikkerhedsniveau, der passer til opgaven. For eksempel kan de rå data, der ligger til grund for en Python-streng, læses på denne måde (hurtigt) uden at skulle gå igennem Python-runtime (langsom).

Cython C-kode kan drage fordel af at frigive GIL

Pythons Global Interpreter Lock, eller GIL, synkroniserer tråde inden for tolken, beskytter adgangen til Python-objekter og styrer konflikt om ressourcer. Men GIL er blevet bredt kritiseret som en anstødssten til en bedre udførende Python, især på multicore-systemer.

Hvis du har et afsnit med kode, der ikke refererer til Python-objekter og udfører en langvarig operation, kan du markere det medmed nogil: direktiv, så det kan køre uden GIL. Dette frigør Python-tolk til at gøre andre ting, og giver Cython-kode mulighed for at gøre brug af flere kerner (med yderligere arbejde).

Cython kan bruge syntaks af antydning af Python-type

Python har en type-antydende syntaks, der hovedsagelig bruges af linters og code checkers, snarere end CPython-tolken. Cython har sin egen brugerdefinerede syntaks til kodedekorationer, men med nylige ændringer af Cython kan du også bruge Python-type-antydende syntaks til også at give grundlæggende tip til Cython.

Cython kan bruges til at tilsløre følsom Python-kode

Python-moduler er trivielt lette at dekompilere og inspicere, men kompilerede binære filer er det ikke. Når du distribuerer et Python-program til slutbrugere, kan du gøre det ved at kompilere dem med Cython, hvis du vil beskytte nogle af dets moduler mod afslappet snooping. Bemærk dog, dette er en side effekt af Cythons muligheder, ikke en af ​​dens tilsigtede funktioner.

Cython begrænsninger

Husk, at Cython ikke er en tryllestav. Det omdanner ikke automatisk hver forekomst af poky Python-kode til en hurtig C-kode. For at få mest muligt ud af Cython skal du bruge det klogt - og forstå dets begrænsninger:

Lille hastighed til konventionel Python-kode

Når Cython støder på Python-kode, kan den ikke oversættes fuldstændigt til C, den omdanner den kode til en række C-opkald til Pythons interner. Dette svarer til at tage Pythons tolk ud af eksekveringssløjfen, hvilket giver kode en beskeden hastighed på 15 til 20 procent som standard. Bemærk, at dette er et bedste tilfælde; i nogle situationer ser du muligvis ingen præstationsforbedring eller endda en forringelse af ydeevnen.

Lille hastighed til oprindelige Python-datastrukturer

Python leverer en række datastrukturer - strenge, lister, tupler, ordbøger og så videre. De er meget bekvemme for udviklere, og de kommer med deres egen automatiske hukommelsesstyring. Men de er langsommere end ren C.

Cython giver dig mulighed for at fortsætte med at bruge alle Python-datastrukturer, dog uden meget hastighed. Dette er igen, fordi Cython simpelthen kalder C API'erne i Python-runtime, der opretter og manipulerer disse objekter. Således opfører Python-datastrukturer sig meget som Cython-optimeret Python-kode generelt: Du får nogle gange et boost, men kun lidt. Brug de C-variabler og strukturer for de bedste resultater. Den gode nyhed er, at Cython gør det nemt at arbejde med dem.

Cythonkode kører hurtigst, når "ren C"

Hvis du har en funktion i C mærket med cdef nøgleord med alle dets variabler og inline-funktionskald til andre ting, der er ren C, vil den køre så hurtigt som C kan gå. Men hvis denne funktion refererer til en hvilken som helst Python-indbygget kode, som en Python-datastruktur eller et opkald til en intern Python API, vil dette opkald være en præstationsflaskehals.

Heldigvis giver Cython en måde at få øje på disse flaskehalse: en kildekoderapport, der med et overblik viser, hvilke dele af din Cython-app, der er ren C, og hvilke dele der interagerer med Python. Jo bedre optimeret appen, jo mindre interaktion vil der være med Python.

Cython NumPy

Cython forbedrer brugen af ​​C-baserede tredjeparts-nummer-knasende biblioteker som NumPy. Fordi Cython-kode kompileres til C, kan den interagere med disse biblioteker direkte og tage Pythons flaskehalse ud af sløjfen.

Men især NumPy fungerer godt sammen med Cython. Cython har indbygget support til specifikke konstruktioner i NumPy og giver hurtig adgang til NumPy-arrays. Og den samme velkendte NumPy-syntaks, som du bruger i et konventionelt Python-script, kan bruges i Cython som det er.

Men hvis du vil oprette de tættest mulige bindinger mellem Cython og NumPy, skal du yderligere dekorere koden med Cythons tilpassede syntaks. Detcimport erklæring tillader f.eks. Cython-kode at se konstruktioner på C-niveau i biblioteker på kompileringstidspunktet for de hurtigst mulige bindinger.

Da NumPy er så udbredt, understøtter Cython NumPy "ud af kassen." Hvis du har NumPy installeret, kan du bare angivecimport bedøvet i din kode, og tilføj derefter yderligere dekoration for at bruge de eksponerede funktioner.

Cython-profilering og ydeevne

Du får den bedste ydeevne fra ethvert stykke kode ved at profilere det og se på førstehånd, hvor flaskehalse er. Cython leverer kroge til Pythons cProfile-modul, så du kan bruge Pythons egne profilværktøjer, som cProfile, for at se, hvordan din Cython-kode fungerer.

Det hjælper med at huske i alle tilfælde, at Cython ikke er magisk - at fornuftige præstationspraksis stadig gælder. Jo mindre du skifter frem og tilbage mellem Python og Cython, jo hurtigere kører din app.

For eksempel, hvis du har en samling objekter, du vil behandle i Cython, skal du ikke gentage det i Python og påberåbe en Cython-funktion ved hvert trin. Passere hele samlingen til dit Cython-modul og gentag der. Denne teknik bruges ofte i biblioteker, der administrerer data, så det er en god model at efterligne i din egen kode.

Vi bruger Python, fordi det giver programmerer bekvemmelighed og muliggør hurtig udvikling. Nogle gange kommer programmørens produktivitet til at koste prisen. Med Cython kan bare en lille ekstra indsats give dig det bedste fra begge verdener.

Læs mere om Python

  • Hvad er Python? Kraftfuld, intuitiv programmering
  • Hvad er PyPy? Hurtigere Python uden smerter
  • Hvad er Cython? Python med C-hastighed
  • Cython tutorial: Sådan fremskyndes Python
  • Sådan installeres Python på den smarte måde
  • De bedste nye funktioner i Python 3.8
  • Bedre Python-projektstyring med Poetry
  • Virtualenv og venv: Python virtuelle miljøer forklaret
  • Python virtualenv og venv do's and don'ts
  • Python-gevind og underprocesser forklaret
  • Sådan bruges Python debugger
  • Sådan bruges timeit til at profilere Python-kode
  • Sådan bruges cProfile til profilering af Python-kode
  • Kom godt i gang med async i Python
  • Sådan bruges asyncio i Python
  • Sådan konverteres Python til JavaScript (og tilbage igen)
  • Python 2 EOL: Sådan overlever du slutningen af ​​Python 2
  • 12 pythoner til ethvert programmeringsbehov
  • 24 Python-biblioteker til alle Python-udviklere
  • 7 søde Python IDE'er, du måske har gået glip af
  • 3 store Python-mangler - og deres løsninger
  • 13 Python-webrammer sammenlignet
  • 4 Python testrammer til at knuse dine bugs
  • 6 fantastiske nye Python-funktioner, som du ikke vil gå glip af
  • 5 Python-distributioner til mastering af maskinlæring
  • 8 fantastiske Python-biblioteker til naturlig sprogbehandling