我有一个Cython函数,它接受一个2d nd.array
(numpy数组)的整数,并返回一个1d numpy数组,其长度与输入的2d数组相同。
import numpy as np
cimport numpy as np
np.import_array()
cimport cython
def func(np.ndarray[np.float_t, dim=2] input_arr):
cdef np.ndarray[np.float_t, ndim=1] new_arr = ...
# do stuff
return new_arr
在程序的另一个循环中,我想调用func
,但是传递一个从另一个2d数组动态创建的2d数组。现在我有:
my_2d_numpy_array = np.array([[0.5, 0.1], [0.1, 10]]) # assume this is defined
cdef int N = 10000
cdef int k
for j in xrange(N)
# find some element k of interest
# create a 2d array on fly containing just the k-th to func()
func(np.array([my_2d_numpy_array[k]], dtype=float)) # KEY LINE
这有效,但我认为每次在循环内调用np.array
会产生巨大的开销,因为它会回到Python。由于func
只读取数组而不修改它,我怎样才能将数组视图作为指针传递给它,而不是通过回到Python来创建一个新数组?我只想提取k
my_2d_numpy_array
行func()
并将其传递给nd.array
更新:一个相关问题:如果我在循环中使用nd.array
但在func
中不需要func
的完整功能,我可以让nd.array
取而代之的是静态C数组,并以某种方式对待func
吗?这会节省成本吗?大概那么你不必将对象传递给nd.array
({{1}}是一个对象)
答案 0 :(得分:4)
您想使用Cython内存视图。 它们被设计用于在作为同一Cython模块一部分的函数之间传递数组切片。 您可能需要在Cython模块中内联函数以获得完整的性能优势,但这并非总是必要的。 你可以看一下documentation。 我最近给另一个question写了一个相当冗长的答案,它会查看应该使用内存视图的时间。 如果您想更详细地检查为什么切片适用于内存视图,请查看此blog post。
如果你不使用内存视图,涉及NumPy数组的切片仍然涉及Python调用,并且不是在C中执行。
针对您的具体情况,以下是一些想法: 如果要在Cython模块中的函数之间传递数组切片,则应该能够使用内存视图来传递切片。 这种方法确实依赖于编译时优化,因此如果需要在两个不同时间编译的函数之间传递数组,则必须使用指针在函数之间传递数据。 这意味着要做一些仔细的指针算法,但它仍然可以工作。 如果你需要切片并使用NumPy函数,你可能最终不得不使用NumPy数组,但是值得尝试使用NumPy数组和查看相同数据的内存视图。 这样你就可以将切片作为内存视图传递,而只需要在你真正需要时创建NumPy数组。
另外,我建议将函数func
作为一个C函数,以便在调用它时不必经历调用Python函数的开销。
您可以使用cdef
或cpdef
关键字来声明它。
如果您不需要从模块外部调用它,请使用cdef
。
如果需要C函数和Python可访问的相应Python包装器,请使用cpdef
。
答案 1 :(得分:0)
func(my_2d_numpy_array[k:k+1])
切片my_2d_numpy_array
而不是索引它可以获得您想要的视图所需的视图。