Pregunta

He estado jugando con la escritura de los módulos de CFFI en Python, y su velocidad me está preguntando si estoy usando el Python estándar correctamente.¡Me está haciendo querer cambiar a C por completo!Sinceramente, hay algunas bibliotecas de Python de Gran Python, nunca pude reembolsarme en C, así que esto es más hipotético que nada realmente.

Este ejemplo muestra la función de suma en Python que se usa con una matriz NUTPY, y qué tan lenta está en comparación con una función C.¿Hay una forma pitónica más rápida de calcular la suma de una matriz numerada?

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

Sólo para mostrar las funciones funciona:

numpy says 100.0
cffi says 100.0

¡Ahora, si es hora de esta simple función, encuentro que NOMPY es realmente lento! ¿Estoy usando adormecidos de la manera correcta?¿Hay una manera más rápida de calcular la suma 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

veces:

cffi 0.818415880203
numpy 5.61657714844

¿Fue útil?

Solución

DOMPY es más lento que C por dos razones: la sobrecarga de Python (probablemente similar a CFFI) y la generalidad. NOMPY está diseñado para lidiar con las matrices de dimensiones arbitrarias, en un montón de diferentes tipos de datos. Su ejemplo con CFFI se hizo para una variedad de flotadores 2D. El costo estaba escribiendo varias líneas de código vs .sum(), 6 caracteres para ahorrar menos de 5 microsegundos. (Pero, por supuesto, ya lo sabías). Solo quiero enfatizar que el tiempo de la CPU es barato, mucho más barato que el tiempo de desarrollador.

Ahora, si desea apegarse a adormecido, y desea obtener un mejor rendimiento, su mejor opción es usar Bottleneck . Proporcionan algunas funciones optimizadas para fines 1 y 2D de flotadores y dobles, y están ardiendo rápidamente. En su caso, 16 veces más rápido, lo que pondrá el tiempo de ejecución en 0.35, o aproximadamente el doble de rápido que el CFFI.

Para otras funciones que el cuello de botella no tiene, puede usar el cython. Le ayuda a escribir código C con una sintaxis más Pythonic. O, si lo desea, convertir progresivamente Python en C hasta que esté contento con la velocidad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top