Dopo aver parlato di Python: l'importanza di rendere efficiente il codice, vediamo una strada abbastanza semplice per eseguire codice C in un programma Python (esistono varie soluzioni alternative, es. Cython che però sconsiglio, oppure procedimenti più "creativi" come nella discussione Mandelbrot: C + Python, per un mondo più colorato).
In questo caso, facciamo uso della libreria CFFI:
C Foreign Function Interface for Python. Interact with almost any C code from Python, based on C-like declarations that you can often copy-paste from header files or documentation
Come benchmark, risolviamo un caso di integrazione numerica (a seconda dell'efficienza, un linguaggio di programmazione avrà un tempo di esecuzione totale diverso, sulla stessa macchina), poi appunto vediamo i risultati di performance.
Python + C tramite CFFI, i passaggi da seguire
- vediamo se la libreria cffi di Python è installata, altrimenti, installazione tramite Pip:
pip install cffi
- il nostro codice C, che salviamo ad esempio in un file function.c. Possiamo anche includere librerie (e ovviamente le varie ottimizzazioni che il linguaggio C consente, rispetto a Python).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float integ(){
register unsigned int N=1000000;
register float ris=0;
register float a=0;
register float b=20;
register float h=(b-a)/N;
register unsigned int i;
for(i=0;i<N;i++){
ris+=pow(M_E,(-0.5*(a+i*h)*(a+i*h)));
}
ris*=pow(1/(2*M_PI),0.5);
return ris;
}
- da terminale:
gcc -fPIC -shared -o function.so function.c
(oppure il nostro "nomefile" al posto di "function"); questa operazione crea un file "shared object", di memoria condivisa, con estesione .so
- ora creiamo il nostro file Python (file.py) e le performance di esecuzone le valutiamo in esso (appunto non ci interessa il risultato dell'operazione in sé, integrale di una semigaussiana, ma il tempo di esecuzione del codice per valutarne le performance rispetto ad una soluzione tradizionale):
from cffi import FFI
import time
ffi = FFI()
ffi.cdef("float integ();")
lib = ffi.dlopen("./function.so")
def my_f():
return lib.integ()
start=time.time()
my_f()
end=time.time()
print(end-start,"s")
- eseguiamo il file Python:
python3 file.py
.... Avrà (incredibilmente) le performance di un programma in C! 🙂
Per comprendere i risultati:
Quindi ad esempio in un programma Python grande e complesso (che resta in Python e non riscriviamo interamente in C/C++), possiamo richiamare alcuni aspetti "critici" in termini di efficienza, tramite l'esecuzione di codice C nel modo che abbiamo visto. Rispetto al codice Python tradizionale, il linguaggio C riesce ad essere almeno 10 volte più veloce, in alcuni casi arriva anche a 100 volte! Una differenza enorme che possiamo "risolvere" ad esempio con questa strada 🙂
Conoscevate questa soluzione? Cosa ne pensate? 🙂