Optimitzant Python amb la llibreria Numba

Com vam comentar al post anterior, Python és un llenguatge de programació molt utilitzat avui en dia, entre altres raons perquè és còmode per programar a alt nivell, té moltes llibreries útils i permet fer codi mantenible i llegible. Tot i aquest nombre d’avantatges, cal destacar que és notòriament lent, per la qual cosa és convenient conèixer algunes eines que permetin accelerar el codi en Python.

Python vs. Numba

Una de les formes amb què es pot accelerar Python és fent servir la llibreria Numba. Per il·lustrar-ho, prendrem com a exemple el càlcul de nombre π utilitzant el mètode de Monte Carlo, de forma similar al que es va fer al post anterior (exemple extret de la pàgina web de Numba)

Accelerar Phyton
Accelerar Phyton

El codi és molt senzill. Es calcula el nombre π fent un mostreig d’un nombre aleatori de punts i utilitzant la proporció entre l’àrea d’un quadrat i un cercle. L’àrea del cercle és estimada com el nombre de punts dintre del cercle, i la del quadrat com el total de punts.

Montecarlo
Montecarlo

Utilitzant 100.000 punts, la funció de Python triga 30.1ms, mentre que fent servir Numba triga 896μms, és a dir, 33.55x vegades més ràpid.

Però… ¿Què és Numba?

Numba és una llibreria de Python que dóna la capacitat de compilar el codi tan aviat com s’executa (és a dir, és un compilador Just-in-Time), aconseguint així velocitats pròpies de codi en C sense sortir de la simplicitat de Python.

I tot això fent modificacions mínimes sobre el codi en Python, com s’ha pogut veure a l’exemple. A més de compilar el codi, Numba té la capacitat de detectar el tipus de processador sobre el que s’està executant i fer ús d’optimitzacions específiques del hardware, a més d’usar diferents threads (cosa que per si sol no pot fer Python).

Per si això no fos poc, Numba està dissenyat per treballar amb Numpy, una de les més famoses llibreries de Python de computació numèrica.

Un dels inconvenients de Numba és que no és amigable amb estructures de dades dinàmiques (és a dir, aquelles que poden incrementar o reduir la seva mida arbitràriament) tals com addició a llistes o diccionaris, a més que pot ser complicat de debuguejar. A més, tot codi escrit amb Numba requereix d’un sistema que suporti el seu compilador JIT.

¿Com fer servir Numba?

Per a que un programa de Python que usa Numba pugui funcionar es necessiten quatre coses, a més de tenir Numba instal·lat, és clar.

(1) Importar la llibreria Numba des del script, així: import numba.

(2) Que el codi que es desitja accelerar estigui clarament definit en una funció. A sobre de dita funció s’afegirà el decorador @numba.njit. Aquest decorador indica a Numba que és aquesta funció la que ha d’intentar compilar. Si per algun motiu no la pot compilar retornarà un error. Si no es vol que retorni un error i es prefereix que faci un fallback a Python normal, aleshores el decorador s’ha de canviar per @numba.jit.

(3) Que el codi no contingui estructures de dades dinàmiques, i preferiblement que les estructures de dades que hi hagi siguin pròpies de Numpy. És a dir, coses tals com .append() a una llista han de ser evitades.

(4) Que els bucles no siguin del tipus for element in elements, sinó que s’iteri pels índexs, tal com for i in range(len(elements)).

Com s’ha pogut observar, usar Numba per parts del codi que puguin ser colls d’ampolla des d’un punt de vista computacional pot proporcionar grans increments en velocitat, i a canvi de molt poc esforç.

 

Esperem que t’hagi estat útil aquest article. Si tens entre mans algun projecte d’enginyeria i creus que podem ajudar-te, aquí et deixo l’enllaç on ens podràs contactar i explicar-nos més a prop d’això.