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.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage