¿Cython ofrece alguna forma razonablemente fácil y eficiente de iterar matrices de Numpy como si fueran planas?
Digamos que quiero implementar Numpy's
x[:] += 1
en Cython Yo podria escribir
@cython.boundscheck(False)
@cython.wraparoundcheck(False)
def add1(np.ndarray[np.float32_t, ndim=1] x):
cdef unsigned long i
for i in range(len(x)):
x[i] += 1
Sin embargo, esto solo funciona conndim = 1
. Podría usar
add1(x.reshape(-1))
pero esto solo funciona con contiguosx
.
¿Cython ofrece alguna forma razonablemente fácil y eficiente de iterar matrices de Numpy como si fueran planas?
(Reimplementar esta operación en particular en Cython no tiene sentido, ya que el código de Numpy anterior debería ser tan rápido como sea posible; solo estoy usando esto como un ejemplo simple)
ACTUALIZAR:
Comparé las soluciones propuestas:
@cython.boundscheck(False)
@cython.wraparound(False)
def add1_flat(np.ndarray x):
cdef unsigned long i
for i in range(x.size):
x.flat[i] += 1
@cython.boundscheck(False)
@cython.wraparound(False)
def add1_nditer(np.ndarray x):
it = np.nditer([x], op_flags=[['readwrite']])
for i in it:
i[...] += 1
La segunda función requiereimport numpy as np
además decimport
. Los resultados son:
a = np.zeros((1000, 1000))
b = a[100:-100, 100:-100]
%timeit b[:] += 1
1000 loops, best of 3: 1.31 ms per loop
%timeit add1_flat(b)
1 loops, best of 3: 316 ms per loop
%timeit add1_nditer(b)
1 loops, best of 3: 1.11 s per loop
Entonces, son 300 y 1000 veces más lentos que Numpy.
ACTUALIZACIÓN 2:
losadd11
la versión usa unfor
bucle dentro de unfor
bucle, por lo que no itera la matriz como si fuera plana. Sin embargo, es tan rápido como Numpy en este caso:
%timeit add1.add11(b)
1000 loops, best of 3: 1.39 ms per loop
Por otra parte,add1_unravel
, una de las soluciones propuestas, no puede modificar el contenido deb
.