Cython este o superset de Python care vă permite să îmbunătățiți în mod semnificativ viteza codului. Puteți adăuga declarații de tip opțional pentru beneficii și mai mari. Cython traduce codul dvs. la C / C ++ optimizat care se compilează într-un modul extensie Python.
În acest tutorial veți afla cum să instalați Cython, obțineți gratuit o creștere imediată a performanței codului dvs. Python și apoi cum să profitați de Cython prin adăugarea de tipuri și modelare a codului. În cele din urmă, veți afla despre subiecte mai avansate, cum ar fi integrarea cu codul C / C ++ și NumPy, pe care o puteți explora în continuare pentru câștiguri mai mari.
Pitagoras a fost matematician și filosof grec. El este renumit pentru teorema lui Pitagora, care afirmă că într-un triunghi cu unghi drept, suma pătratelor picioarelor triunghiurilor este egală cu pătratul de hypotenuse. Pitlura triplele sunt oricare trei numere întregi pozitive a, b și c astfel încât a² + b² = c²
. Iată un program care găsește toate triplele Pythagorean ale căror membri nu sunt mai mari decât limita furnizată.
timpul limită: rezultatul = 0 pentru un interval (1, limita + 1): pentru b în intervalul (a + 1, limita + 1): pentru c în intervalul (b + : dacă c * c> a * a + b * b: pauză dacă c * c == (a * a + b * b): rezultat + = 1 rezultat returnat dacă __name__ == '__main__': start = time.time () result = count (1000) duration = time.time () - început de imprimare (rezultat, durată) Output: 881 13.883624076843262
Se pare că există 881 de triple și programul a durat puțin mai puțin de 14 secunde pentru a afla. Nu este prea lung, dar suficient de lung pentru a fi enervant. Dacă vrem să găsim mai multe triple până la o limită superioară, ar trebui să găsim o modalitate de a face să meargă mai repede.
Se pare că există algoritmi în mod substanțial mai buni, dar astăzi ne concentrăm pe a face Python mai rapid cu Cython, nu pe cel mai bun algoritm pentru găsirea triplelor Pythagorean.
Cea mai simplă modalitate de a utiliza Cython este să utilizați caracteristica specială a lui pymmport. Aceasta este o declarație care compilează codul dvs. Cython în zbor și vă permite să vă bucurați de beneficiile optimizării native fără prea multe probleme.
Trebuie să puneți codul în sincronizare în modulul său, să scrieți o linie de configurare în programul dvs. principal și apoi să îl importați ca de obicei. Să vedem cum arată. Am mutat funcția în propriul fișier numit pythagorean_triples.pyx. Extensia este importantă pentru Cython. Linia care activează Cython este import pyximport; pyximport.install ()
. Apoi, doar importă modulul cu numara() și mai târziu îl invocă în funcția principală.
timpul importului pyximport import; () rezultă = pythagorean_triples.count (1000) duration = time.time () - începe imprimarea (rezultat, durată) dacă __name__ == '__main__': () Output: 881 9.432806253433228
Funcția Python pură a funcționat cu 50% mai mult. Avem acest impuls prin adăugarea unei singure linii. Nu-i rău deloc.
În timp ce pyximport este foarte convenabil în timpul dezvoltării, funcționează numai pe modulele Python pure. Adesea, când optimizați codul, doriți să consultați bibliotecile native C sau modulele de extensie Python.
Pentru a le sprijini și, de asemenea, pentru a evita compilarea dinamică pe fiecare rulare, puteți să vă construiți propriul modul de extensie Cython. Trebuie să adăugați un mic fișier setup.py și să vă amintiți să îl construiți înainte de a rula programul ori de câte ori modificați codul Cython. Aici este fișierul setup.py:
din setarea de import distutils.core de la Cython.Build import cythonize setup (ext_modules = cythonize ("pythagorean_triples.pyx"))
Apoi trebuie să-l construiți:
$ python setup.py build_ext --locația Compilarea pythagorean_triples.pyx pentru că sa schimbat. [1/1] Cythonizing pythagorean_triples.pyx care rulează build_ext clădire 'pythagorean_triples' extensie creare construi construire build / temp.macosx-10.7-x86_64-3.6 gcc -Wno-unused-rezultat -Wsign-compare -Wunreachable-code -DNDEBUG -g - fwrapv -O3 -Wall -Westrict-prototipuri -I / Users / gigi.sayfan / miniconda3 / envs / py3 / include -arch x86_64 -I / Utilizatori / gigi.sayfan / miniconda3 / envs / py3 / include -arch x86_64 -I / Utilizatorii / gigi.sayfan / miniconda3 / envs / py3 / include / python3.6m -c pythagorean_triples.c -o build / temp.macosx-10.7-x86_64-3.6 / pythagorean_triples.o gcc -bundle -definit dynamic_lookup -L / gigi.sayfan / miniconda3 / envs / py3 / lib -L / Utilizatori / gigi.sayfan / miniconda3 / envs / py3 / lib -arch x86_64 build / temp.macosx-10.7-x86_64-3.6 / pythagorean_triples.o -L / gigi.sayfan / miniconda3 / envs / py3 / lib -o pythagorean_triples.cpython-36m-darwin.so
După cum puteți vedea din ieșire, Cython a generat un fișier C numit pythagorean_triples.c și îl compilează pe un fișier de tip .so, specific pentru platformă, modulul de extensie pe care Python îl poate importa acum ca orice alt modul de extensie nativă.
Dacă sunteți curios, faceți o privire asupra codului C generat. Este foarte lung (2789 linii), obtuză și conține multe lucruri suplimentare necesare pentru a lucra cu Python API. Să renunțăm la pyximport și să ne reluăm programul:
importul timpului de import pythagorean_triples Definiție principală (): start = time.time () rezultat = pythagorean_triples.count (1000) duration = time.time () 881 9.507064819335938
Rezultatul este aproape la fel ca în cazul lui pyximport. Cu toate acestea, rețineți că măsoară numai durata de execuție a codului cythonized. Nu măsoară cât timp este nevoie de Pyximport pentru a compila codul cyntonizat în zbor. În programele mari, acest lucru poate fi semnificativ.
Să mergem la nivelul următor. Cython este mai mult decât Python și adaugă tastarea opțională. Aici, definesc doar toate variabilele ca numere întregi, iar performanța urcă:
# cutoff int = 0 cdef int a = 0 cdef int b = 0 cdef int c = 0 pentru a în intervalul (1, limita + 1): pentru b în intervalul (a + 1 , limită + 1): pentru c în intervalul (b + 1, limita + 1): dacă c * c> a * a + b * b: pauză c * c == (a * a + b * b): rezultatul + = 1 rezultat retur ---------- # main.py timp de import import pyximport; () rezultă = pythagorean_triples.count (1000) duration = time.time () - începe imprimarea (rezultat, durată) dacă __name__ == '__main__': () Output: 881 0.056414127349853516
Da. Este corect. Prin definirea unei perechi de numere întregi, programul rulează în mai puțin de 57 de milisecunde, comparativ cu mai mult de 13 secunde cu Python pur. Asta înseamnă aproape o îmbunătățire de 250X.
Am folosit modulul Timp al lui Python, care măsoară timpul de perete și este destul de bun de cele mai multe ori. Dacă doriți o sincronizare mai precisă a fragmentelor de coduri mici, luați în considerare utilizarea modulului timeit. Iată cum să măsurați performanța codului utilizând timeit:
>>> timeit.timeit ('count (1000)', setup = "din numărul de importuri pythagorean_triples", number = 1) 0.05357028398429975 # Running de 10 ori >>> timeit.timeit ('count (1000)' , setup = "din numărul de importuri pythagorean_triples", number = 10) 0.5446877249924
timeit ()
funcția ia o declarație de executat, un cod de instalare care nu este măsurat și numărul de timpuri pentru executarea codului măsurat.
Tocmai am zgâriat suprafața. Puteți face mult mai mult cu Cython. Iată câteva subiecte care pot îmbunătăți în continuare performanța codului dvs. sau pot permite Cython să se integreze cu alte medii:
Cython poate produce două ordini de ameliorare a performanței pentru efort foarte mic. Dacă vă dezvoltați software non-trivial în Python, Cython este un non-brainer. Ea are foarte puțin aeriene, și o puteți introduce treptat la baza de cod.
În plus, nu ezitați să vedeți ce avem la dispoziție pentru vânzare și pentru a studia pe piață și nu ezitați să întrebați orice întrebări și să furnizați feedback-ul valoros utilizând feedul de mai jos.