Question

J'ai joué avec l'écriture de modules cffi en python, et leur vitesse me fait me demander si j'utilise correctement python standard.Cela me donne envie de passer complètement au C !Honnêtement, il existe d'excellentes bibliothèques Python que je ne pourrais jamais réimplémenter moi-même en C, donc c'est plus hypothétique qu'autre chose en réalité.

Cet exemple montre la fonction sum en python utilisée avec un tableau numpy et sa lenteur par rapport à une fonction c.Existe-t-il un moyen pythonique plus rapide de calculer la somme d'un tableau numpy ?

def cast_matrix(matrix, ffi):
    ap = ffi.new("double* [%d]" % (matrix.shape[0]))
    ptr = ffi.cast("double *", matrix.ctypes.data)
    for i in range(matrix.shape[0]):
        ap[i] = ptr + i*matrix.shape[1]                                                                
    return ap 

ffi = FFI()
ffi.cdef("""
double sum(double**, int, int);
""")
C = ffi.verify("""
double sum(double** matrix,int x, int y){
    int i, j; 
    double sum = 0.0;
    for (i=0; i<x; i++){
        for (j=0; j<y; j++){
            sum = sum + matrix[i][j];
        }
    }
    return(sum);
}
""")
m = np.ones(shape=(10,10))
print 'numpy says', m.sum()

m_p = cast_matrix(m, ffi)

sm = C.sum(m_p, m.shape[0], m.shape[1])
print 'cffi says', sm

juste pour montrer que la fonction fonctionne :

numpy says 100.0
cffi says 100.0

maintenant, si je chronomètre cette fonction simple, je trouve que numpy est vraiment lent !Est-ce que j'utilise numpy de la bonne manière ?Existe-t-il un moyen plus rapide de calculer la somme en python ?

import time
n = 1000000

t0 = time.time()
for i in range(n): C.sum(m_p, m.shape[0], m.shape[1])
t1 = time.time()

print 'cffi', t1-t0

t0 = time.time()
for i in range(n): m.sum()
t1 = time.time()

print 'numpy', t1-t0

fois:

cffi 0.818415880203
numpy 5.61657714844
Était-ce utile?

La solution

Numpy est plus lent que C pour deux raisons :la surcharge Python (probablement similaire à cffi) et la généralité.Numpy est conçu pour traiter des tableaux de dimensions arbitraires, dans un ensemble de types de données différents.Votre exemple avec cffi a été réalisé pour un tableau 2D de flotteurs.Le coût était d'écrire plusieurs lignes de code par rapport à .sum(), 6 caractères pour gagner moins de 5 microsecondes.(Mais bien sûr, vous le saviez déjà).Je veux juste souligner que le temps CPU est bon marché, beaucoup moins cher que le temps du développeur.

Maintenant, si vous souhaitez vous en tenir à Numpy et obtenir de meilleures performances, votre meilleure option est d'utiliser Goulot.Ils fournissent quelques fonctions optimisées pour les tableaux 1 et 2D de float et de doubles, et ils sont extrêmement rapides.Dans votre cas, 16 fois plus rapide, ce qui mettra le temps d'exécution à 0,35, soit environ deux fois plus rapide que cffi.

Pour d'autres fonctions qui n'ont pas de goulot d'étranglement, vous pouvez utiliser Cython.Il vous aide à écrire du code C avec une syntaxe plus pythonique.Ou, si vous préférez, convertissez progressivement Python en C jusqu'à ce que vous soyez satisfait de la vitesse.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top