2010-08-03 11 views
7

Estoy empezando a conocer numpy, y estoy impresionado por sus afirmaciones de eficiencia tipo C con acceso a la memoria en sus ndarrays. Quería ver las diferencias entre estas y las listas de Pythonic para mí, así que ejecuté una prueba de tiempo rápida, realizando algunas de las mismas tareas simples con numpy sin ella. Numpy superó las listas regulares por un orden de magnitud en la asignación de operaciones aritméticas en matrices, como se esperaba. Sin embargo, este segmento de código, idéntico en ambas pruebas, tomó alrededor de 1/8 de segundo con una lista regular, y un poco más de 2,5 segundos con numpy:¿Cómo puedo maximizar la eficiencia con las matrices numpy?

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

file.close() 

¿Alguien sabe por qué esto podría ser, y si hay ¿Hay alguna otra sintaxis que debería usar para operaciones como esta para aprovechar mejor lo que el ndarray puede hacer?

Gracias ...

EDIT: Para contestar el comentario de Wayne ... me gustan los dos cronometrado en varias ocasiones y en diferentes órdenes y dieron resultados casi idénticos cada vez, así que dudo que es otro proceso. Puse

start = time()
en la parte superior del archivo después de la importación numpy y luego tengo declaraciones como
print 'Time after traversal:\t',(time() - start)
en todas partes.

+1

¿Puede mostrar cómo midió la hora? ¿Intentó cambiar el orden que tomó? El hecho de que esté escribiendo en un disco complica el problema del tiempo (¿qué pasaría si '[insert-process-here]' escribiera en el disco con mayor prioridad durante la prueba de numpys?) –

+0

¡Gracias por todas las respuestas! Todos fueron informativos. ¡Lo siento, no tengo suficiente reputación para votar sobre ellos! – pr0crastin8r

Respuesta

9

a2 es una matriz NumPy, ¿verdad? Una posible razón por la que podría tomar tanto tiempo en NumPy (si la actividad de otros procesos no lo tiene en cuenta, como sugirió Wayne Werner) es que está iterando sobre la matriz mediante un ciclo de Python. En cada paso de la iteración, Python tiene que extraer un valor único de la matriz NumPy y convertirlo a un número entero de Python, que no es una operación particularmente rápida.

NumPy funciona mucho mejor cuando puede realizar operaciones en toda la matriz como una unidad. En su caso, una opción (tal vez ni siquiera el más rápido) sería

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

que intente comparar al equivalente en Python puro,

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

estoy No me sorprende que NumPy tenga pocos recursos incorporados en Python cuando usa su fragmento. Una gran parte de la mejora en el rendimiento en NumPy surge de evitar los bucles y en lugar de acceder a la matriz mediante la indexación:

En NumPy, es más común de hacer algo como esto:

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

+1 para A [A% 2 == 0] que es el tipo de línea que el OP desearía utilizar, excepto con 1000 en lugar de 2, por supuesto. – tom10

5

por elemento es muy lento para matrices numpy. Use operaciones vectoriales:

$ 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 
Cuestiones relacionadas