Я не думаю, что это действительно работает, но если вы хотите сделать это, то самый лучший способ, вероятно, использовать memoryviews из structs
(которые совместимы с numpys пользовательских dtypes):
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
и функцию, чтобы показать вам, как это назвать:
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))
То, что я хотел бы сделать это:
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 # ???
Это успешно компилируется, но я не мог найти способ превращения его из NumPy. Если бы вы могли решить, как заставить эту версию работать, я думаю, что это будет самое элегантное решение.
Обратите внимание, что я не убежден в преимуществах производительности любого из этих решений. Ваш лучший способ, вероятно, рассказать Cython о том, что конечное измерение смежно в памяти (например, double [:,::1]
), но пусть оно будет любого размера.
Следующий вопрос: как преобразовать данные из массива numpy в 'float [2] *'? – user1447257
@ user1447257 Что вы хотите достичь с этим. Это звучало так, будто вы хотели иметь статическую форму для достижения производительности. Но если это всего лишь синтаксический сахар в вашем коде, вы можете также использовать синтаксис представления общей памяти 'float [:,:]'. Поскольку массивы 'numpy' являются динамическими, они не будут связываться с' float [2] * ', если вы не хотите явно скопировать данные. – romeric
Для меньшего количества пропусков в кеш я буду делать копирование в смежный массив в любом случае, так как мой код повторяется через записи несколько раз. Я думал, что, возможно, приведение в '' float [2] * 'data-type приведет к увеличению производительности бит, поскольку указатель может быть увеличен полностью линейно. – user1447257