Cython és un llenguatge de programació que actua com un compilador estàtic que serveix per a optimitzar tant el llenguatge de programació de Python com el llenguatge de programació estés de Cython (el qual està basat en Pyrex). Aquest permet escriure extensions de C per Python amb la mateixa dificultat amb la qual escriuríem en el propi Python.
És una extensió d'un llenguatge de programació que té com a propòsit ajudar a un compilador de Cython per transformar els codis que són de Python a un tipus de codis de C. El codi de C es genera un cop i es compila mitjançant els principals compiladors de C / C++ a CPython 2.6, 2.7 (2.4+ amb Cython 0.20.x), així com 3.3 i totes les posteriors versions d'aquest.
Definició El llenguatge de Cython és un superconjunt de Python el qual també permet crides de funcions de C, la declaració de variables tipus C i atributs de classes. Tot això fa que el compilador pugui generar codi de tipus C molt eficient a partir de codi de tipus Cython.
Regularment s'executen proves d'integració en totes les versions que són compatibles amb CPython i les últimes branques que es troben en desenvolupament per tal d'assegurar que el codi que ha estat generat sigui perfectament compatible i ben adaptat a cada versió.
El suport de PyPy és un treball que es troba en progrés i el qual es considera majoritàriament utilitzable des de Cython 0.17. Tot això fa que Cython sigui el llenguatge de programació ideal per a biblioteques externes de C, agregar CPython en aplicacions que ja existeixen i també per a mòduls ràpids de C que permeten accelerar l'execució d'un codi de Python.
Utilitats Cython t'atorga la possibilitat de realitzar les següents tasques (les quals ajunten funcions tant de Python com de C):
Poder escriure el codi de Python que va d'anada i tornada des del codi de C o C++ de forma nativa a qualsevol punt. Sintonitzar fàcilment el codi llegible de Python en el rendiment simple de C agregant declaracions de tipus estàtic, també en sintaxis de Python. Utilitzar la depuració combinada del nivell de codi font per a poder trobar errors en el codi de Python, Cython i també C. Crear ràpidament les aplicacions dins del sistema de CPython. Interactuar de manera efectiva amb grans conjunts de dades utilitzant matrius de NumPy multidimensionals. Integrar de manera nativa amb codi i dades ja existents d'aplicacions, heretades i de biblioteques d'alt o baix nivell.
Història Cython és un derivat del llenguatge anomenat Pyrex i alhora suporta més funcions i optimitzacions d'aquesta. Cython fou bifurcat de Pyrex l'any 2007 pels desarrolladors del paquet d'àlgebra de computadors de Sage perquè estaven descontents amb les limitacions de Pyrex i no podien obtenir “patches” de l'encarregat de Pyrex, Greg Ewing, el qual va imaginar un abast molt més petit per a la seva eina que la que van tenir els desenvolupadors de Sage. Aleshores, aquests desenvolupadors de Sage, van bifurcar Pyrex com a SageX. Quan van descobrir que les persones descarregaven Sage només per poder obtenir SageX i els desenvolupadors de paquets (Stefan Behnel inclòs, el qual manté la XML biblioteca LXML) també seguien mantenint les agulles de Pyrex, SageX es va separar del projecte de Sage i es va fusionar amb cython-lxml per finalment convertir-se en Cython.
Disseny Cython funciona produint un mòdul estàndard de Python. Tanmateix, el comportament difereix de Python estàndard en què el codi del mòdul, originalment escrit en Python, es tradueix en C. Mentre que el codi resultant de C és ràpid, fa moltes crides a l'intèrpret CPython i a les biblioteques estàndard de CPython per realitzar treballs reals. Aquestes crides van estalviar considerablement el temps de desenvolupament de Cython, però els mòduls depenen en gran manera de la biblioteca estàndard i de l'intèrpret de Python.
Tot i que la majoria del codi està basat en C, normalment cal un petit carregador de tests escrit en Python. Tot i això, aquest no és un problema important a causa de la presència de l'intèrpret de Python. miniatura|Passos per a la creació d'un programa executable de Ctyhon|vora|286x286pxCython té una interfície de funció externa per invocar rutines de C / C ++ i la capacitat de declarar el tipus estàtic de paràmetres i resultats de subrutina, variables locals i atributs de classe.
Un programa Cython que implementi el mateix algorisme que un programa Python corresponent pot consumir menys recursos informàtics com ara memòria bàsica i cicles de processament a causa de diferències entre els models d'execució CPython i Cython. Un programa de Python bàsic és carregat i executat per la màquina virtual CPython, de manera que tant el temps d'execució com el propi programa consumeixen recursos informàtics. Un programa de Cython es compila amb codi C, que es compila més al codi de màquina, de manera que la màquina virtual només s'utilitza breument quan es carrega el programa.
Cython utilitza:
Declaració de tipus (opcional).
Despesa baixa en estructures de control.
Despesa baixa en crides a funcions.
El rendiment depèn tant del codi C generat per Cython com de la composició d'aquest codi.
Per programar en Cython seguim els passos següents:
Escriure un fitxer de codi Cython (.pyx) Fer servir el compilador de Cython (cythonize) per generar un fitxer en C Fer servir un compilador de C per generar codi màquina Fer servir el interpret de Python i importar el mòdul compilat
Avantatges L'avantatge essencial d'aquest enfocament, és que al barrejar perfectament codi Python/C (és a dir, C usant <python.h>) és que el codi Python existent es pot ajustar a gairebé la velocitat de C amb només afegir uns quants tipus estàtics a les declaracions i fent algunes adaptacions en els bucles crítics -sense necessitat d'una interfície complicada o molt invasiva del codi. La velocitat de codificació i la llegibilitat del codi segueix sent comparable a la del codi Python.
A causa de reducció del consum general en les estructures de control (especialment els bucles), les optimitzacions optimistes i la inferència de tipus, el codi Python compilat amb Cython normalment s'executa més ràpid que en l'intèrpret CPython 2.6.x, encara que les millores absolutes depenen en gran manera el codi. Amb les declaracions de tipus estàtics, l'acceleració típica en càlculs numèrics/matricials és de 100x-1000x En comparació a la típica optimització amb Psyco (Python JIT compiler) què és entre 4x-100x.Psyco - Introduction
Compatibilitat Cython està escrit en Python, així que treballa en Windows, Linux, i MacOS X.
Declaració de variables Per millorar l'eficiència del codi Cython sovint és útil definir les variables definint el seu tipus de forma estàtica. D'aquesta manera ajudarem a Cython a escapar de la natura dinàmica de Python i generar un codi en C molt més ràpid. Aquestes declaracions poden fer que el codi resulti menys entenedor de cara a l'usuari i, per tant, no és recomanable fer-ne ús sense coneixement previ, pero si se'n fa un ús lògic de les seves eines s'arriba a resultats molt més ràpids.
La declaració estàtica del tipus de cada variable segueix la següent estructura:
cdef <type> <variable>
Cython permet la declaració de tots els tipus de variables disponibles en codi C. +Sintaxi de declaració de variablesTipusDeclaracióint cdef int n = 10float cdef float n = 255.0complex cdef float complex fc = 1+1jstruct cdef struct Eduardo: int age float heightunion cdef union Food: char *spam float *eggsclass cdef class Teacher: cdef int age, height
def __init__(self, a, s): self.age = a self.subject = s
def describe(self): print("Our teacher is", self.age, "years old and teaches", self.subject)list cdef list llista = []ctuple cdef (int, double) tupla = (1, 2.0)
Cython converteix de manera automàtica i correcte el tipus de la variable en Python al tipus especificat a la assignació a la variable en C. Això també inclou el tipus d'enters arbitraris de la mida per defecte de Python, on els desbordaments de valors en la conversió a un tipus C provocaran un “PythonOverflowError” en temps d'execució. El codi generat en C podrà manipular correctament i de manera segura amb les mides de les variables assignades. D'aquesta manera podem definir les variables que hagin de representar nombre enters com a int, i el propi Cython s'encarregarà de dictaminar si es tracta d'un char, un int, un long, etc.
De tot el llistat de possibles tipologies de les variables allistades anteriorment les més típiques són dues: int i float. En C i, per tant, en Cython, la mida de les variables de tipus int es determina en funció del valor que hagi de representar i, per tant, el nombre bits necessaris. Tenim char (8 bits, 256 valors), int (32 bits, 2³² valors) i long (64 bits, 2⁶⁴ valors). Pel que respecta als floats, distingim entre float (32 bits) i double (64 bits). Les variables double tenen major precisió a l'hora de realitzar càlculs més precisos, pero aquests són computacional més cars.
Definició de funcions Cython permet 3 maneres diferents de declarar funcions:
def: és la definició d'una funció en llenguatge Python. El codi tractarà aquestes funcions com a codi Python pur: és a dir, no guanyarem ni velocitat ni optimització de memòria respecte Python. Es fa servir quan la funció pren arguments que són objectes de Python o quan volem retornar un objecte Python.
cdef: és una definició similar a la de Python però on tots els tipus de variables han de ser declarats. S'ha d'anar amb compte ja que realment el codi interpreta aquest tipus de funcions com funcions en C.
cpdef: és una combinació de les dues anteriors, és a dir, es pot comportar com una funció "cdef" si utilitza fonaments de C o com una funció "def" si rep objectes Python. #La funció suma_deu pren un nombre enter com a paràmetre i li suma deu unitats #funció definida amb def def suma_deu(nombre): int resultat = 0 resultat = nombre + 10 return resultat
#Funció definida amb cdef cdef int suma_deu(int nombre): int resultat = 0 resultat = nombre + 10 return resultat
#Funció definida amb cpdef cpdef suma_deu(int nombre): int resultat = 0 resultat = nombre + 10 return resultat
Accés a memòria A part de la conversió entre tipus de Python i C, un segon possible coll d'ampolla que empitjora el rendiment del codi són els accessos i assignaments a memòria. Per poder accedir a aquests elements fent servir codi C i, per tant, molt més ràpidament farem ús dels memoryview. D'aquesta manera estarem declarant el tipus de totes les variables dins l'array de forma estàtica.
Numpy Els memoryview són estructures de C amb un apuntador a un Numpy array i totes les dades necessàries per fer un accés segur i ràpid als elements d'aquest (dimensions, tipus de les variables, …). El que estem creant no és una còpia d'aquest array, sinó una forma més eficaç d'accedir als elements d'aquest.
Quan declarem un memoryview seguirem la següent sintaxi: +Declaració de memoryviewsDeclaracióDimensionscdef <type> [:] <variable>1Dcdef <type> [:,:] <variable>2Dcdef <type> [:,:,:] <variable>3D Per millorar-ne encara més l'eficiència, si sabem que els elements de l'array són contigus a memoria podem fer la següent declaració: +Declaració de memoryviews contigusDeclaracióDimensions i eixcdef <type> [::1] <variable>1D, contigu en filacdef <type> [:,::1] <variable>2D, contigu en filacdef <type> [::1,:] <variable>2D, contigu en columna Com els elements del Numpys arrays sempre es troben contigus a memòria, l'ús d'aquests en combinació amb la declaració contigua a memòria suposen una gran millora en el rendiment.
Directives per al compilador Cython permet l'ús de directives que indiquen al compilador com ha de compilar el codi. Podem assignar aquestes directives a nivell global o a nivell local per una funció.
Algunes de les directives que permet Cython són les següents: