2012-02-09 32 views
9

Necesito realizar algunos cálculos con una gran lista de números.Python numpy array vs list

¿Los arreglos array.array o numpy.array ofrecen un aumento significativo del rendimiento sobre los arreglos típicos?

no tengo que hacer manipulaciones complicadas en las matrices, sólo hay que ser capaz de acceder y modificar los valores,

por ejemplo,

import numpy 
x = numpy.array([0] * 1000000) 
for i in range(1,len(x)): 
    x[i] = x[i-1] + i 

Así que no voy a necesitar realmente concatenación, rebanado, etc.

Además, parece que array genera un error si se intenta asignar valores que no encajan en C:

largo
import numpy 
a = numpy.array([0]) 
a[0] += 1232234234234324353453453 
print(a) 

en la consola me sale:

a[0] += 1232234234234324353453453 
OverflowError: Python int too large to convert to C long 

¿hay una variación de la matriz que me permite poner en unbo enteros de Python separados ¿O lo haría de esa manera quitando el punto de tener matrices en primer lugar?

+0

Véase también [cpython vs cython vs numpy array performance] (http://stackoverflow.com/questions/22514730/cpython-vs-cython-vs-numpy-array-performance) – Trilarion

Respuesta

8

Su primer ejemplo podría ser la aceleración. El ciclo de Python y el acceso a elementos individuales en una matriz numpy son lentos. Utilizar operaciones vectorizadas lugar:

import numpy as np 
x = np.arange(1000000).cumsum() 

Usted puede poner números enteros Python sin límites a la matriz numpy:

a = np.array([0], dtype=object) 
a[0] += 1232234234234324353453453 

operaciones aritméticas en comparación con los números enteros C de tamaño fijo sería más lento en este caso.

11

Primero necesita comprender la diferencia entre matrices y listas.

Una matriz es un contiguo bloque de memoria que consta de elementos de algún tipo (por ejemplo, enteros).

No puede cambiar el tamaño de una matriz una vez que se haya creado.
Por lo tanto, se deduce que cada elemento entero en una matriz tiene un tamaño fijo, p. Ej. 4 bytes.

Por otra parte, una listaes simplemente un "array" de direcciones (que también tiene un tamaño fijo).

Pero entonces cada elementocontiene la dirección de algo otra cosa en la memoria, que es el actual número entero que desea trabajar. Por supuesto, el tamaño de este entero es irrelevante para el tamaño de la matriz. Por lo tanto, siempre puede crear un entero nuevo (más grande) y "reemplazar" el anterior sin afectar el tamaño de la matriz, que simplemente contiene la dirección de un número entero.

Por supuesto, esta comodidad de una lista tiene un costo: Realización de aritmética sobre los enteros ahora requiere un acceso a memoria a la matriz, más un acceso a la memoria al propio número entero, más el tiempo que se tarda en asigne más memoria (si es necesario), más el tiempo requerido para eliminar el número entero anterior (si es necesario). Entonces sí, puede ser más lento, así que debes tener cuidado con lo que estás haciendo con cada entero dentro de una matriz.

+0

El último párrafo se aplica igualmente a las matrices numpy de enteros de tamaño fijo si no usa operaciones vectorizadas (como en el primer ejemplo del OP). Es * no * la razón por la cual las matrices numpy pueden ser más rápidas. – jfs

0

¿Las matrices.array o numpy.array ofrecen un aumento significativo del rendimiento sobre las matrices típicas?

Puede, dependiendo de lo que esté haciendo.

¿O lo haría de esa manera quitando el punto de tener matrices en primer lugar?

Bastante, sí.

1

No array.array o numpy.array oferta importante aumento de rendimiento sobre matrices típicas?

Me trataron de probar esta un poco con el siguiente código:

import timeit, math, array 
from functools import partial 
import numpy as np 

# from the question 
def calc1(x): 
    for i in range(1,len(x)): 
     x[i] = x[i-1] + 1 

# a floating point operation 
def calc2(x): 
    for i in range(0,len(x)): 
     x[i] = math.sin(i) 

L = int(1e5) 

# np 
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20))) 
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20))) 

# np but with vectorized form 
vfunc = np.vectorize(math.sin) 
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20))) 

# with list 
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20))) 
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20))) 

# with array 
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20))) 
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20))) 

y los resultados fueron que la lista se ejecuta más rápido aquí (Python 3.3, NumPy 1.8):

np 1: 2.14277 s 
np 2: 0.77008 s 
np 2 vectorized: 0.44117 s 
list 1: 0.29795 s 
list 2: 0.66529 s 
array 1: 0.66134 s 
array 2: 0.88299 s 

Qué parece ser contradictorio. No parece haber ninguna ventaja al usar numpy o array sobre list para estos ejemplos simples.

0

usa a=numpy.array(number_of_elements, dtype=numpy.int64) que debería darte una matriz de enteros de 64 bits. Estos pueden almacenar cualquier número entero entre -2^63 y (2^63) -1 (aproximadamente entre -10^19 y 10^19) que suele ser más que suficiente.

2

Para la mayoría de los usos, las listas son útiles. A veces, trabajar con matrices numpy puede ser más conveniente, por ejemplo.

a=[1,2,3,4,5,6,7,8,9,10] 

b=[5,8,9] 

Considérese una lista de 'a' y si desea acceder a los elementos de una lista en índices discretos que figuran en la lista 'B' escribir

b[a] 

no va a funcionar.

pero cuando se utilizan como matrices, simplemente hay que escribir

b[a] 

para obtener el resultado como una matriz ([6,9,10]).