在cython中,可以使用數組視圖,例如,cython靜態形狀數組視圖
cdef void func(float[:, :] arr)
在我的用法中,第二個維度的形狀應該總是2.我可以告訴cython嗎?我正在考慮類似的東西:
cdef void func(float[:, 2] arr)
但這會導致無效的語法;或者可能有更類似於C++的東西,例如
cdef void func(tuple<float, float>[:] arr)
在此先感謝!
在cython中,可以使用數組視圖,例如,cython靜態形狀數組視圖
cdef void func(float[:, :] arr)
在我的用法中,第二個維度的形狀應該總是2.我可以告訴cython嗎?我正在考慮類似的東西:
cdef void func(float[:, 2] arr)
但這會導致無效的語法;或者可能有更類似於C++的東西,例如
cdef void func(tuple<float, float>[:] arr)
在此先感謝!
您可以改用2D靜態數組。只需使用指針表示法。這裏是你如何實現它
def pyfunc():
# static 1D array
cdef float *arr1d = [1,-1, 0, 2,-1, -1, 4]
# static 2D array
cdef float[2] *arr2d = [[1,.2.],[3.,4.]]
# pass to a "cdef"ed function
cfunc(arr2d)
# your function signature would now look like this
cdef void cfunc(float[2] *arr2d):
print("my 2D static array")
print(arr2d[0][0],arr2d[0][1],arr2d[1][0],arr2d[1][1])
調用它,你得到:
>>> pyfunc()
my 2D static array
1.0, 2.0, 3.0, 4.0
我不認爲這是真正的支持,但如果你想這樣做,則最好的辦法可能是使用的structs
memoryviews(這與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] *'數據類型的轉換會提高性能,因爲指針可以完全線性增加。 – user1447257