我有一个 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
,但向其传递一个从另一个二维数组动态创建的二维数组。现在我有:
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 只读取数组而不修改它,我如何才能将数组的 View 作为指针传递给它,而不需要返回到 Python 来创建新数组?我只对取出 my_2d_numpy_array
的第 k
行并将其传递给 func()
更新:一个相关问题:如果我在循环内使用 nd.array
但不需要 nd.array< 的完整功能
在 func
中,我可以让 func
改为采用静态 C 数组之类的东西,并以某种方式将 nd.array
视为那样吗?这样能节省成本吗?想必您不必将对象传递给 func
(nd.array
是一个对象)
最佳答案
您想要使用 Cython 内存 View 。 它们设计用于在属于同一 Cython 模块的函数之间传递数组切片。 您可能需要在 Cython 模块中内联该函数才能获得完整的性能优势,但这并不总是必要的。 你可以看看documentation 。 我最近给另一个question写了一个相当长的答案。它会研究何时应该使用内存 View 。 如果您想更详细地了解为什么切片对内存 View 效果很好,请查看此 blog post .
如果您不使用内存 View ,涉及 NumPy 数组的切片仍然涉及 Python 调用,并且不会在 C 中执行。
针对您的具体情况,以下是一些想法: 如果您在 Cython 模块中的函数之间传递数组切片,您应该能够使用内存 View 来传递切片。 这种方法确实依赖于编译时优化,因此如果您需要在不同时间编译的两个函数之间传递数组,则必须使用指针在函数之间传递数据。 这意味着要进行一些仔细的指针算术,但它应该仍然有效。 如果您需要进行切片并使用 NumPy 函数,您可能最终不得不使用 NumPy 数组,但尝试使用 NumPy 数组和查看相同数据的内存 View 可能是值得的。 这样您就可以将切片作为内存 View 传递,而只需在真正需要时创建 NumPy 数组。
此外,我建议将函数 func
设为 C 函数,这样您在调用 Python 函数时就不必经历调用它的开销。
您可以使用 cdef
或 cpdef
关键字来声明它。
如果不需要从模块外部调用它,请使用cdef
。
如果您想要一个 C 函数和一个可供 Python 访问的相应 Python 包装器,请使用 cpdef。
关于python - 在 Cython 中获取 numpy 数组子集的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21979504/