Ich glaube nicht wirklich unterstützt wird, aber wenn Sie dies tun wollen, dann der beste Weg ist wahrscheinlich zu verwenden memoryviews von structs
(die mit numpys benutzerdefinierten dtypes kompatibel sind):
import numpy as np
cdef packed struct Pair1: # packed ensures it matches custom numpy dtypes
# (but probably doesn't matter here!)
double x
double y
# pair 1 matches arrays of this dtype
pair_1_dtype = [('x',np.float64), ('y',np.float64)]
cdef packed struct Pair2:
double data[2]
pair_2_dtype = [('data',np.float64, (2,))]
def pair_func1(Pair1[::1] x):
# do some very basic work
cdef Pair1 p
cdef Py_ssize_t i
p.x = 0; p.y = 0
for i in range(x.shape[0]):
p.x += x[i].x
p.y += x[i].y
return p # take advantage of auto-conversion to a dict
def pair_func2(Pair2[::1] x):
# do some very basic work
cdef Pair2 p
cdef Py_ssize_t i
p.data[0] = 0; p.data[1] = 0
for i in range(x.shape[0]):
p.data[0] += x[i].data[0]
p.data[1] += x[i].data[1]
return p # take advantage of auto-conversion to a dict
und eine Funktion, die Sie zeigen, wie man es nennen:
def call_pair_funcs_example():
# generate data of correct dtype
d = np.random.rand(100,2)
d1 = d.view(dtype=pair_1_dtype).reshape(-1)
print(pair_func1(d1))
d2 = d.view(dtype=pair_2_dtype).reshape(-1)
print(pair_func2(d2))
Die Sache Ich mag würde getan haben ist:
ctypedef double[2] Pair3
def pair_func3(Pair3[::1] x):
# do some very basic work
cdef Pair3 p
cdef Py_ssize_t i
p[0] = 0; p[1] = 0
for i in range(x.shape[0]):
p[0] += x[i][0]
p[1] += x[i][1]
return p # ???
die erfolgreich kompiliert, aber ich konnte jede mögliche Weise nicht gefunden davon aus numpy konvertieren. Wenn Sie herausfinden könnten, wie Sie diese Version zum Laufen bringen, dann wäre das wohl die eleganteste Lösung.
Beachten Sie, dass ich von den Leistungsvorteilen dieser Lösungen nicht überzeugt bin. Ihre beste Bewegung ist wahrscheinlich, Cython mitzuteilen, dass die abschließende Dimension zusammenhängend im Speicher ist (z. B. double [:,::1]
), aber lassen Sie sie eine beliebige Größe haben.
Folgefrage: Wie kann ich die Daten eines numpy Arrays in 'float [2] *' konvertieren? – user1447257
@ user1447257 Was möchten Sie damit erreichen? Es klang so, als ob Sie ein statisch geformtes Array für Performance-Zwecke haben wollten. Wenn dies jedoch nur ein syntaktischer Zucker in Ihrem Code ist, können Sie auch die generische Memory View-Syntax 'float [:,:]' 'verwenden. Da 'numpy' Arrays dynamisch sind, werden sie nicht an' float [2] * 'gebunden, es sei denn, Sie möchten die Daten explizit kopieren. – romeric
Für weniger Cache-Fehler würde ich sowieso auf ein zusammenhängendes Array kopieren, da mein Code mehrmals über die Einträge iteriert. Ich habe mir gedacht, dass eine Umwandlung in einen 'float [2] *' -Datentyp die Leistung ein wenig erhöht, weil der Zeiger vollständig linear inkrementiert werden könnte. – user1447257