Programmēšana

Cython apmācība: kā paātrināt Python

Python ir spēcīga programmēšanas valoda, kuru ir viegli iemācīties un ar kuru viegli strādāt, taču tā ne vienmēr ir ātrākā, it īpaši, ja nodarbojaties ar matemātiku vai statistiku. Trešās puses bibliotēkas, piemēram, NumPy, kas iesaiņo C bibliotēkas, var ievērojami uzlabot dažu darbību veiktspēju, taču dažreiz jums vienkārši nepieciešams C neapstrādāts ātrums un jauda tieši Python.

Cython tika izstrādāts, lai atvieglotu Python C paplašinājumu rakstīšanu un ļautu esošo Python kodu pārveidot par C. Turklāt Cython ļauj optimizēto kodu nosūtīt kopā ar Python lietojumprogrammu bez ārējām atkarībām.

Šajā apmācībā mēs iepazīsimies ar darbībām, kas nepieciešamas, lai esošo Python kodu pārveidotu par Cython un izmantotu to ražošanas lietojumprogrammā.

Saistītais videoklips: Cython izmantošana, lai paātrinātu Python

Cython piemērs

Sāksim ar vienkāršu piemēru, kas ņemts no Cython dokumentācijas, nevis ļoti efektīvas integrālās funkcijas ieviešanas:

def f (x):

atgriešanās x ** 2-x

def integrēt_f (a, b, N):

s = 0

dx = (b-a) / N

i diapazonā (N):

s + = f (a + i * dx)

atgriešanās s * dx

Kods ir viegli lasāms un saprotams, bet darbojas lēni. Tas ir tāpēc, ka Python ir pastāvīgi jāpārveido turp un atpakaļ starp saviem objektu tipiem un mašīnas neapstrādātiem skaitliskajiem tipiem.

Tagad apsveriet tā paša koda Cython versiju, pasvītrojot Cython papildinājumus:

 cdef f (dubultā x):

atgriešanās x ** 2-x

def integrēt_f (dubultā a, dubultā b, int N):

cdef int i

cdef dubultā s, x, dx

s = 0

dx = (b-a) / N

i diapazonā (N):

s + = f (a + i * dx)

atgriešanās s * dx

Šie papildinājumi ļauj mums skaidri deklarēt mainīgos tipus visā kodā, lai Cython kompilators varētu pārtulkot šos “dekorētos” papildinājumus C valodā.

Saistītais video: kā Python atvieglo programmēšanu

Ideāli piemērots IT, Python vienkāršo daudzu veidu darbu, sākot no sistēmas automatizācijas līdz darbam tādās modernās jomās kā mašīnmācīšanās.

Cython sintakse

Atslēgvārdi, kas tiek izmantoti Cython koda noformēšanai, nav sastopami parastajā Python sintaksē. Tie tika īpaši izstrādāti Cython, tāpēc jebkurš ar tiem dekorēts kods nedarbosies kā parasta Python programma.

Šie ir visizplatītākie Cython sintakses elementi:

Mainīgie veidi

Daži no Cython izmantotajiem mainīgo tipiem ir pašu Python tipu atbalsis, piemēramint, peldēt, un ilgi. C, piemēram, ir atrodami arī citi Cython mainīgo veidi char vai struktur, tāpat kā tādas deklarācijas neparakstīts ilgi. Un citi ir līdzīgi tikai Cython bint, Python C līmeņa attēlojums Patiesa / nepatiesa vērtības.

The cdef un cpdef funkciju veidi

The cdef atslēgvārds norāda Cython vai C tipa izmantošanu. To izmanto arī, lai definētu funkcijas līdzīgi kā jūs darītu Python.

Funkcijas, kas rakstītas Cython, izmantojot Python’s def atslēgvārds ir redzams citam Python kodam, taču par to tiek piemērots izpildes sods. Funkcijas, kas izmanto cdef atslēgvārds ir redzams tikai citiem Cython vai C kodiem, taču tos izpilda daudz ātrāk. Ja jums ir funkcijas, kuras iekšēji izsauc tikai no Cython moduļa, izmantojiet cdef.

Trešais atslēgvārds, cpdef, nodrošina saderību gan ar Python kodu, gan ar C kodu tādā veidā, ka C kods var piekļūt deklarētajai funkcijai ar pilnu ātrumu. Tomēr šīs ērtības ir par maksu:cpdef funkcijas ģenerē vairāk koda un tām ir nedaudz vairāk zvanu pieskaitāmo vērtību nekā cdef.

Citi Cython atslēgvārdi

Citi Cython atslēgvārdi nodrošina kontroli pār programmas plūsmas un uzvedības aspektiem, kas nav pieejami Python:

  • gil un nogil. Tie ir konteksta pārvaldnieki, ko izmanto, lai noteiktu koda sadaļas, kurām nepieciešams (ar gil:) vai neprasa (ar nogil:) Python's Global Interpreter Lock jeb GIL. C kods, kas neizsauc Python API, var darboties ātrāk a nogil bloķēt, it īpaši, ja tā veic ilgstošu darbību, piemēram, lasīšanu no tīkla savienojuma.
  • cimportTas liek Cython importēt C datu tipus, funkcijas, mainīgos un paplašinājumu veidus. Piemēram, tiek izmantotas Cython lietotnes, kas izmanto NumPy vietējos C moduļus cimport lai piekļūtu šīm funkcijām.
  • iekļaut. Tas ievieto viena Cython faila avota kodu citā, tāpat kā C. Ņemiet vērā, ka Cython ir sarežģītāks veids, kā koplietot deklarācijas starp citiem Cython failiem, nevis tikai iekļauts.
  • ctypedef. Izmanto, lai atsauktos uz tipu definīcijām ārējos C galvenes failos.
  • ārpuse. Lieto kopā ar cdef atsaukties uz C funkcijām vai mainīgajiem, kas atrodami citos moduļos.
  • public / api. Izmanto, lai izveidotu deklarācijas Cython moduļos, kas būs redzami citiem C kodiem.
  • rindā. Lieto, lai norādītu, ka konkrētajai funkcijai ātruma labad vienmēr jābūt iezīmētai vai tās kodam vienmēr jābūt ievietotam izsaucošās funkcijas pamattekstā. Piemēram, f funkcija iepriekš minētajā koda piemērā varētu būt dekorēta ar rindā lai samazinātu tā funkciju izsaukuma pieskaitāmās izmaksas, jo to izmanto tikai vienā vietā. (Ņemiet vērā, ka kompilators C, iespējams, automātiski veic savu ieklāšanu, bet rindā ļauj precīzi norādīt, vai kaut kas jāieraksta.)

Nav nepieciešams iepriekš zināt visus Cython atslēgvārdus. Cython kodu mēdz rakstīt pakāpeniski - vispirms jūs uzrakstāt derīgu Python kodu, pēc tam pievienojat Cython rotājumu, lai to paātrinātu. Tādējādi jūs varat paņemt Cython paplašināto atslēgvārdu sintaksi pa daļām, kā jums tas nepieciešams.

Sastādiet Cython

Tagad, kad mums ir kāda ideja par to, kā izskatās vienkārša Cython programma, un kāpēc tā izskatās tā, apskatīsim soļus, kas nepieciešami, lai Cython apkopotu darbīgā binārā failā.

Lai izveidotu darbīgu Cython programmu, mums būs nepieciešamas trīs lietas:

  1. Python tulks. Ja iespējams, izmantojiet jaunāko laidiena versiju.
  2. Cython pakete. Jūs varat pievienot Cython Python, izmantojot pip pakotņu pārvaldnieks: pip instalēt cython
  3. C kompilators.

3. vienums var būt sarežģīts, ja kā attīstības platformu izmantojat Microsoft Windows. Atšķirībā no Linux, Windows standarta komplektācijā nav iekļauts C kompilators. Lai to novērstu, paņemiet Microsoft Visual Studio kopienas izdevuma kopiju, kas ietver Microsoft kompilatoru C un neko nemaksā.

Ņemiet vērā, ka šajā rakstā jaunākā Cython laidiena versija ir 0.29.16, taču ir pieejama lietošanai Cython 3.0 beta versija. Ja jūs izmantojat pip instalēt cython, tiks instalēta visjaunākā versija, kas nav beta versija. Ja vēlaties izmēģināt beta versiju, izmantojiet pip instalēt cython> = 3.0a1 lai instalētu jaunāko Cython 3.0 filiāles izdevumu. Cython izstrādātāji iesaka izmēģināt Cython 3.0 filiāli, kad vien iespējams, jo dažos gadījumos tas ģenerē ievērojami ātrāku kodu.

Cython programmas izmanto .pyx faila paplašinājums. Jaunā direktorijā izveidojiet failu ar nosaukumu num.pyx kurā ir iepriekš parādītais Cython koda piemērs (otrais koda paraugs sadaļā “A Cython piemērs”) un fails ar nosaukumu main.py kas satur šādu kodu:

no num importēt integrēt_f

drukāt (integrēt_f (1.0, 10.0, 2000))

Šī ir parasta Python programma, kas izsauks integrēt_f funkcija atrastanum.pyx. Python kods “redz” Cython kodu kā vēl vienu moduli, tāpēc jums nav jādara nekas cits, kā tikai importēt kompilēto moduli un palaist tā funkcijas.

Visbeidzot, pievienojiet failu ar nosaukumu setup.py ar šādu kodu:

from distutils.core importēšanas iestatīšana no distutils.extension importēšanas paplašinājums no Cython. Veidojiet importēšanas cythonize ext_modules = [Extension (r'num ', [r'num.pyx']),] setup (name = "num", ext_modules = cythonize (ext_modules),

)

setup.py parasti Python izmanto, lai instalētu moduli, ar kuru tas ir saistīts, un to var arī izmantot, lai novirzītu Python uz šī moduļa C paplašinājumu apkopošanu. Šeit mēs izmantojam setup.py lai apkopotu Cython kodu.

Ja izmantojat Linux un jums ir instalēts C kompilators (parasti tas ir gadījums), varat kompilēt .pyx failu C, izpildot komandu:

python setup.py build_ext --inplace

Ja izmantojat Microsoft Windows un Microsoft Visual Studio 2017 vai labāku versiju, jums jāpārliecinās, vai jums ir jaunākā versija iestatīšanas rīki instalēta Python (šī raksta versija 46.1.3), pirms šī komanda darbosies. Tas nodrošina, ka Python izveides rīki varēs automātiski noteikt un izmantot instalēto Visual Studio versiju.

Ja kompilācija ir veiksmīga, direktorijā vajadzētu parādīties jauniem failiem: num.c (Cython ģenerētais C fails) un fails ar vai nu a .o paplašinājums (operētājsistēmā Linux) vai a .pyd paplašinājums (operētājsistēmā Windows). Tas ir binārs, kurā ir apkopots C fails. Varat arī redzēt a \būvēt apakšdirektorijs, kurā ir būvniecības procesa artefakti.

Palaist python main.py, un jums vajadzētu redzēt, ka atbildē ir atgriezta šāda informācija:

283.297530375

Tā ir kompilētās integrālās funkcijas izeja, uz kuru atsaucas mūsu tīrais Python kods. Mēģiniet spēlēt ar parametriem, kas funkcijai nodoti main.py lai redzētu, kā izeja mainās.

Ņemiet vērā, ka ikreiz, kad veicat izmaiņas .pyx failu, jums tas būs jāpārkompilē. (Visas izmaiņas, ko veicat parastajā Python kodā, stāsies spēkā nekavējoties.)

Iegūtajam kompilētajam failam nav atkarību, izņemot Python versiju, kurai tas tika kompilēts, un tāpēc to var apvienot binārā ritenī. Ņemiet vērā, ka, ja jūs savā kodā atsaucaties uz citām bibliotēkām, piemēram, NumPy (skatiet tālāk), jums tās būs jānorāda kā daļa no lietojumprogrammas prasībām.

Kā izmantot Cython

Tagad, kad jūs zināt, kā kodēt “Cythonize”, nākamais solis ir noteikt, kā jūsu Python lietojumprogramma var gūt labumu no Cython. Kur tieši jums tas jāpielieto?

Lai iegūtu labākos rezultātus, izmantojiet Cython, lai optimizētu šāda veida Python funkcijas:

  1. Funkcijas, kas darbojas saspringtā lokā vai prasa ilgu apstrādes laiku vienā koda “karstajā vietā”.
  2. Funkcijas, kas veic skaitliskas manipulācijas.
  3. Funkcijas, kas darbojas ar objektiem, kurus var attēlot tīrā C, piemēram, pamata skaitliskie veidi, masīvi vai struktūras, nevis Python objektu tipi, piemēram, saraksti, vārdnīcas vai kopas.

Python tradicionāli ir bijis mazāk efektīvs cilpās un skaitliskās manipulācijās nekā citas, netulkotas valodas. Jo vairāk jūs izrotājat savu kodu, lai norādītu, ka tam jāizmanto pamata skaitliskie tipi, kurus var pārvērst par C, jo ātrāk tas veiks skaitļu krokošanu.

Izmantojot Python objektu tipus Cython, pati par sevi nav problēmu. Cython funkcijas, kas izmanto Python objektus, joprojām tiks kompilētas, un Python objekti var būt vēlamāki, ja veiktspēja nav galvenā uzmanība. Bet jebkuru kodu, kas izmanto Python objektus, ierobežos Python izpildlaika veiktspēja, jo Cython ģenerēs kodu, lai tieši adresētu Python API un ABI.

Vēl viens cienīgs Cython optimizācijas mērķis ir Python kods, kas tieši mijiedarbojas ar C bibliotēku. Jūs varat izlaist tieši Python “iesaiņotāja” kodu un saskarni ar bibliotēkām.

Tomēr Cython to dara automātiski ģenerēt pareizās zvanu saskarnes šīm bibliotēkām. Jums būs nepieciešams, lai Cython bibliotēkas galvenes failos atsaucas uz funkciju parakstiem, izmantojot a cdef extern no deklarāciju. Ņemiet vērā, ka, ja jums nav galvenes failu, Cython ir pietiekami piedodošs, lai ļautu jums deklarēt ārējo funkciju parakstus, kas aptuveni atbilst sākotnējām galvenēm. Bet, lai būtu drošībā, pēc iespējas izmantojiet oriģinālus.

Viena ārēja C bibliotēka, kuru Cython var izmantot uzreiz no kastes, ir NumPy. Lai izmantotu Cython ātrās piekļuves NumPy masīviem priekšrocības, izmantojiet cimport numpy (pēc izvēles ar kā np lai tā nosaukumvieta būtu atšķirīga) un pēc tam izmantojiet cdef paziņojumus, lai deklarētu NumPy mainīgos, piemēram, cdef np.raksts vai np.indarray.

Cython profilēšana

Pirmais solis, lai uzlabotu lietojumprogrammas veiktspēju, ir tās profils - lai izveidotu detalizētu pārskatu par vietu, kur tiek pavadīts izpildes laikā. Python nodrošina iebūvētus mehānismus kodu profilu ģenerēšanai. Cython ne tikai piesaista šos mehānismus, bet tam ir arī savi profilēšanas rīki.

Paša Python profilētājs, cProfils, ģenerē pārskatus, kas parāda, kuras funkcijas attiecīgajā Python programmā aizņem visvairāk laika. Pēc noklusējuma Cython kods šajos pārskatos neparādās, taču jūs varat iespējot profilēšanu Cython kodā, ievietojot kompilatora direktīvu .pyx fails ar funkcijām, kuras vēlaties iekļaut profilēšanā:

# cython: profile = True

Varat arī iespējot rindas pa rindai izsekošanu Cython ģenerētajam C kodam, taču tas uzliek daudz papildu izmaksu, un tāpēc tas pēc noklusējuma ir izslēgts.

Ņemiet vērā, ka profilēšana uzliek veiktspējas trāpījumu, tāpēc noteikti noņemiet profilēšanu kodam, kas tiek piegādāts ražošanai.

Cython var arī ģenerēt kodu pārskatus, kas norāda, cik daudz no dotā .pyx fails tiek pārveidots par C, un cik daudz no tā paliek Python kods. Lai to redzētu darbībā, rediģējiet setup.py failu mūsu piemērā un augšpusē pievienojiet šādas divas rindas:

importēt Cython.Compiler.Options

Cython.Compiler.Options.annotate = True

(Varat arī izmantot setup.py direktīvu, lai iespējotu anotācijas, taču ar iepriekš minēto metodi bieži ir vieglāk strādāt.)

Dzēst .c faili, kas ģenerēti projektā, un atkārtoti palaidiet setup.py skripts, lai visu pārkompilētu. Kad esat pabeidzis, tajā pašā direktorijā jums vajadzētu redzēt HTML failu, kas koplieto jūsu .pyx faila nosaukumu - šajā gadījumānum.html. Atveriet HTML failu, un jūs redzēsiet, ka koda daļas, kas joprojām ir atkarīgas no Python, ir iezīmētas dzeltenā krāsā. Jūs varat noklikšķināt uz dzeltenajiem apgabaliem, lai redzētu pamatā esošo C kodu, ko ģenerējis Cython.

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