繁体   English   中英

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

[英]Fastest way to get subset of numpy array in Cython

我有一个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的调用np.array产生巨大的开销,因为它可以追溯到Python。 由于func仅读取数组并且不对其进行修改,因此如何仅将数组的视图作为指针传递给它,而不必回到Python来创建新数组呢? 我只想提取出my_2d_numpy_arrayk行并将其传递给func()

更新 :一个相关的问题:如果我在循环中使用nd.array但不需要funcnd.array的全部功能,我可以使func代替静态C数组,并以某种方式处理nd.array 这样可以节省成本吗? 大概然后就不nd.array对象传递给funcnd.array是一个对象)

您想使用Cython内存视图。 它们旨在在同一Cython模块的一部分函数之间传递数组切片。 您可能需要在Cython模块中内联该函数以获得全部性能优势,但这并不总是必要的。 您可以看一下文档 我最近为另一个问题写了一个相当冗长的答案,该问题探讨了何时应该使用内存视图。 如果您想更详细地研究切片为何能很好地与内存视图配合使用,请参阅此博客文章

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

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

另外,我建议将函数func设为C函数,这样您在调用它时就不必承担调用Python函数的开销。 您可以使用cdefcpdef关键字进行声明。 如果不需要从模块外部调用cdef ,请使用cdef 如果需要C函数和Python可访问的相应Python包装器,请使用cpdef

func(my_2d_numpy_array[k:k+1])

切片my_2d_numpy_array而不是对其进行索引,即可获得所需形状的所需视图。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM