Domanda

Ho giocato in giro con la scrittura dei moduli CFFI in Python, e la loro velocità mi sta facendo meravigliare se sto usando correttamente Python standard.Mi sta facendo passare completamente a c completamente!Sinceramente ci sono alcune grandi biblioteche Python che non potrei mai rimuovermi in c, quindi questo è più ipotetico di qualsiasi altra cosa.

Questo esempio mostra la funzione Sum in Python utilizzata con un array ninpy e quanto è lento è in confronto con una funzione C.C'è un modo più veloce di calcolo della somma di un array ninpy?

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
.

Solo per mostrare la funzione funziona:

numpy says 100.0
cffi says 100.0
.

Ora se sono questa semplice funzione, trovo che Numpy è davvero lento! Sto usando Numpy nel modo corretto?C'è un modo più veloce per calcolare la somma in 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
.

volte:

cffi 0.818415880203
numpy 5.61657714844
.

È stato utile?

Soluzione

Numpy è più lento di c per due motivi: il python overhead (probabilmente simile a cFFI) e generalità. Numpy è progettato per gestire gli array di dimensioni arbitrarie, in un mucchio di diversi tipi di dati. Il tuo esempio con cFFI è stato realizzato per una serie 2D di galleggianti. Il costo stava scrivendo diverse linee di codice VS .sum(), 6 caratteri per salvare meno di 5 microsecondi. (Ma naturalmente, lo sapevi già). Voglio solo sottolineare che il tempo della CPU è economico, molto più economico del tempo di sviluppatore.

Ora, se vuoi attaccare a NutyPy, e vuoi ottenere una performance migliore, la tua migliore opzione è quella di utilizzare Bottleneck . Forniscono alcune funzioni ottimizzate per gli array 1 e 2D di galleggiante e doppi, e stanno bruciando velocemente. Nel tuo caso, 16 volte più veloce, che metterà il tempo di esecuzione in 0,35 o circa due volte più veloce di CFFI.

Per altre funzioni che il collo di bottiglia non ha, è possibile utilizzare cython. Ti aiuta a scrivere codice C con una sintassi più pietonica. Oppure, se vuoi, converti progressivamente Python in c fino a quando non sei felice con la velocità.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top