Bietet Cython eine einigermaßen einfache und effiziente Möglichkeit, Numpy-Arrays so zu iterieren, als wären sie flach?
Sagen wir, ich möchte Numpy's implementieren
x[:] += 1
n Cython. Ich könnte schreiben
@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
Das funktioniert aber nur mitndim = 1
. Ich könnte benutze
add1(x.reshape(-1))
Aber das funktioniert nur mit zusammenhängendenx
.
Bietet Cython eine einigermaßen einfache und effiziente Möglichkeit, Numpy-Arrays so zu iterieren, als wären sie flach?
(Diese spezielle Operation in Cython erneut zu implementieren macht keinen Sinn, da der obige Code von Numpy so schnell wie möglich sein sollte - ich verwende ihn nur als einfaches Beispiel)
AKTUALISIEREN
Ich habe die vorgeschlagenen Lösungen verglichen:
@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
Die zweite Funktion benötigtimport numpy as np
zusätzlich zucimport
. Die Ergebnisse sind:
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
So, sie sind 300 und 1000 mal langsamer als Numpy.
UPDATE 2:
Dasadd11
-Version verwendet einfor
Schleife innerhalb einesfor
loop und iteriert das Array nicht so, als wäre es flach. In diesem Fall ist es jedoch so schnell wie Numpy:
%timeit add1.add11(b)
1000 loops, best of 3: 1.39 ms per loop
Auf der anderen Seite,add1_unravel
, eine der vorgeschlagenen Lösungen, kann den Inhalt von @ nicht ändeb
.