2010-08-03 19 views
7

Sto solo conoscendo Numpy e sono impressionato dalle sue affermazioni sull'efficienza di tipo C con accesso alla memoria nei suoi narghilè. Volevo vedere da solo le differenze tra queste e le liste pitoniche, quindi ho eseguito un rapido test di temporizzazione, eseguendo alcune delle stesse semplici operazioni con Numpy senza di essa. Numpy ha surclassato gli elenchi regolari di un ordine di grandezza nell'allocazione delle operazioni aritmetiche sugli array, come previsto. Ma questo segmento di codice, identico in entrambe le prove, ha richiesto circa 1/8 di secondo con una lista regolare, e un po 'più di 2,5 secondi con NumPy:Come massimizzare l'efficienza con gli array numpy?

file = open('timing.log','w') 
for num in a2: 
    if num % 1000 == 0: 
     file.write("Multiple of 1000!\r\n") 

file.close() 

Qualcuno sa il motivo per cui questo potrebbe essere, e se non ci è qualche altra sintassi che dovrei usare per operazioni come questa per sfruttare al meglio ciò che può fare narray?

Grazie ...

EDIT: Per rispondere a un commento di Wayne ... entrambi ho cronometrato più volte e in diversi ordini e ottenuto risultati praticamente identici ogni volta, quindi dubito che sia un altro processo. Inserisco

start = time()
nella parte superiore del file dopo l'importazione numpy e quindi ho istruzioni come
print 'Time after traversal:\t',(time() - start)
in tutto.

+1

Puoi mostrare come hai misurato il tempo? Hai provato a scambiare quale ordine hai preso? Il fatto che tu stia scrivendo su disco complica il problema del timing (cosa succede se '[insert-process-here]' sta scrivendo su disco con priorità maggiore durante il test di numpys?) –

+0

Grazie per tutte le risposte! Tutto era informativo. Mi dispiace, non ho abbastanza reputazione per votare su di loro! – pr0crastin8r

risposta

9

a2 è un array NumPy, giusto? Una possibile ragione per cui ci vorrebbe tanto tempo in NumPy (se l'attività di altri processi non lo considera come suggerito da Wayne Werner) è che si sta ripetendo l'array usando un loop Python. Ad ogni passo dell'iterazione, Python deve recuperare un singolo valore dall'array NumPy e convertirlo in un intero Python, che non è un'operazione particolarmente veloce.

NumPy funziona molto meglio quando è possibile eseguire operazioni sull'intero array come unità. Nel tuo caso, una possibilità (forse nemmeno il più veloce) sarebbe

file.write("Multiple of 1000!\r\n" * (a2 % 1000 == 0).sum()) 

Prova a confronto che al-Python puro equivalente,

file.write("Multiple of 1000!\r\n" * sum(filter(lambda i: i % 1000 == 0, a2))) 

o

file.write("Multiple of 1000!\r\n" * sum(1 for i in a2 if i % 1000 == 0)) 
6

Sono Non sorprende che NumPy faccia male con w/r/t Python integrato quando si usa il frammento. Una frazione del miglioramento delle prestazioni in NumPy deriva da evitare anse e invece accedere alla matrice da indicizzazione:

In NumPy, è più comune per fare qualcosa di simile:

A = NP.random.randint(10, 100, 100).reshape(10, 10) 
w = A[A % 2 == 0] 
NP.save("test_file.npy", w) 
+3

+1 per A [A% 2 == 0] che è il tipo di linea che l'OP vorrebbe usare, tranne con 1000 invece di 2, ovviamente. – tom10

5

Per-elemento di accesso è molto lento per gli array numpy. Usa le operazioni vettoriali:

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' ' 
> sum(1 for i in a2 if i % 1000 == 0)' 
10 loops, best of 3: 1.53 sec per loop 

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' ' 
> (a2 % 1000 == 0).sum()' 
10 loops, best of 3: 22.6 msec per loop 

$ python -mtimeit -s 'import numpy as np; a2= range(10**6)' ' 
> sum(1 for i in a2 if i % 1000 == 0)' 
10 loops, best of 3: 90.9 msec per loop 
Problemi correlati