Python 在Cython中获取numpy数组子集的最快方法

Python 在Cython中获取numpy数组子集的最快方法,python,arrays,numpy,scipy,cython,Python,Arrays,Numpy,Scipy,Cython,我有一个Cython函数,它接受一个2dnd.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 = ...

我有一个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生成新数组呢?我只想拉出
my_2d\u numpy\u数组的
k
第行,并将其传递给
func()

更新:一个相关的问题:如果我在循环中使用
nd.array
,但在
func
中不需要
nd.array
的全部功能,我是否可以让
func
改为使用类似于静态C数组的东西,并以某种方式处理
nd.array
?这能节省成本吗?假定您不必将对象传递给
func
nd.array
是一个对象)


切片
my\u 2d\u numpy\u数组
而不是索引它可以获得所需形状的视图。

您想使用Cython内存视图。 它们设计用于在属于同一Cython模块的函数之间传递数组片。 您可能需要在Cython模块中内联函数以获得全面的性能优势,但这并非总是必要的。 你可以看一看。 我最近写了一个相当长的答案给另一个关于何时应该使用内存视图的答案。 如果您想更详细地了解为什么切片可以很好地与内存视图配合使用,请查看以下内容

如果不使用内存视图,那么涉及NumPy数组的切片仍然涉及Python调用,并且不会在C中执行

对于您的具体情况,以下是一些想法: 如果在Cython模块中的函数之间传递数组切片,则应该能够使用内存视图来传递切片。 这种方法确实依赖于编译时优化,因此如果需要在两个在不同时间编译的函数之间传递数组,则必须使用指针在函数之间传递数据。 这意味着要做一些仔细的指针运算,但它仍然可以工作。 如果您需要执行切片并使用NumPy函数,您可能最终不得不使用NumPy数组,但是尝试使用查看相同数据的NumPy数组和内存视图可能是值得的。 这样,您就可以将切片作为内存视图传递,而只需在真正需要时创建NumPy数组

另外,我建议将函数
func
设置为C函数,这样在调用Python函数时就不必经历调用Python函数的开销。 您可以使用
cdef
cpdef
关键字来声明它。 如果不需要从模块外部调用,请使用
cdef

如果您想要Python可以访问的C函数和相应的Python包装,请使用
cpdef

您确定
np.array
返回到解释器吗?这是一个内置函数。@user2357112:我认为np.array可以追溯到Python吗?不确定?添加了相关问题。您能否评论一下这是否与np.array不同?我担心使用python风格的索引也可能调用numpy索引的python过程。我想确保我的索引是纯粹的C@user248237dfsf:numpy数组的切片和索引处理是在纯C中完成的。对,但有时Cython代码在未正确完成时会使其成功,因此您将使用Python,然后只调用C中的numpy函数,因此我试图避免这种情况。我知道numpy在CSlicing中实现了索引功能,numpy不是C操作。它调用与Python中相同的切片方法。
func(my_2d_numpy_array[k:k+1])