【问题标题】:Correct way to return numpy friendly arrays using typed memoryviews in Cython?在 Cython 中使用类型化的 memoryviews 返回 numpy 友好数组的正确方法?
【发布时间】:2014-04-02 20:22:25
【问题描述】:

我正在尝试使用 Cython memoryviews 创建或获取 numpy 数组,这样我就不必使用 numpy 进行编译,但我想返回 Python 端可以是 ' cast' 成 numpy 数组。例如我有这个函数,它接受一个二维数组并返回一个新的一维数组:

cimport cython
from cython.view cimport array as cvarray

cpdef int[:] myfunc(int[:,:] input_arr, int arr_len):
   cdef int i
   # allocate new int array
   cdef int[:] new_arr = cvarray(shape=(arr_len,), itemsize=sizeof(int), format="i") 
   for i in xrange(arr_len):
      if input_arr[i, 0] == 1:
         new_arr[i] = 0
      else:
         new_arr[i] = 1
   return new_arr

现在从 Python 我实际上想将一个 numpy 数组传递给函数并将结果作为一个 numpy 数组查看:

# From Python
import numpy as np
data = np.array([[0,0,0],[1,0,1]], dtype=np.dtype("i"))
result = myfunc(data, data.shape[0])
# How do I make 'result' accessible as numpy array here??
# ...
result = np.array(result)  # one possibility

如何做到这一点?我的方式正确吗?更具体的问题:

  1. 引用new_arr[x] 会返回Python 吗?我希望它是数组的纯 C 索引
  2. cdef int[:] new_arr = ...cdef int[::1] new_arr = ... 之间有区别吗?后者看不懂
  3. cvarray 是在这里分配内存的最佳方式,还是clone?对于 numpy 数组,我会使用 np.empty 并且我试图在这里获得同样高效的东西。另外,为什么在cvarray 调用中需要format="i"
  4. 最后,如果clone 是正确的语法,它如何用于二维数组?不清楚https://github.com/cython/cython/blob/f94ad59754a0f0b1cef4a334b988a21392a738c0/Cython/Includes/cpython/array.pxd

这与这篇文章(What is the recommended way of allocating memory for a typed memory view?)有关,我没有完全理解。

【问题讨论】:

  • 您避免使用 cimport numpy 是否有特殊原因?如果您没有同时指定 dtype=np.int 和 copy=False,那么在底部执行 np.array 将会制作一个副本。使用平台本机 int 也要小心,那里漂浮着烦人的问题:stackoverflow.com/questions/589575/size-of-int-long-etc
  • @meawoppl:我不想需要 numpy 头文件等。我想要简单的 Cython 数组,不想用 Cython 编译 numpy 头文件。我不介意在 Python 端制作副本。
  • 我明白了,除此之外,我会注意到标头随 numpy 一起提供,并且将对相同库进行所有相同的调用。 Numpy 数组只是内存块的向下视图。如果您在数组创建步骤中指定形状,或者运行 reshape() ,它只会返回一个 strides 属性不同的视图,因此可以读取不同维度的访问。一种选择是对这个数组的大小/形状进行所有计算。另一种选择是传入一个 numpy 数组并在您的函数中对其进行变异。这可能是最简单的,因为它也避免了烦人的 refcounting 语义
  • @meawoppl:你提到的重塑方案的一个例子会有所帮助,因为我不确定我是否遵循。如果我使用 cython 数组,那不会消除所有编译器警告和其他问题(如不推荐使用的 numpy api)吗?我认为如果我不在任何地方使用np 并且不在 setup.py 中使用np.include_header(),我将不再使用 numpy,这是我的目标。在编译 Cython 生成的 *.c 文件时,我根本不想依赖 numpy C API
  • 您可以使用numpy.arraynumpy.asarray 从 Cython 内存视图中获取 NumPy 数组。 np.asarray 实际上只是 numpy.array 的一个薄包装。不过,我不太确定您将如何分配新数组。如果您正在复制内存视图,则其他答案中给出的示例似乎不起作用。

标签: c arrays numpy cython


【解决方案1】:

除非您需要在 Cython 的其他地方使用此功能,否则您应该使用 def 而不是 cpdef。要返回numpy数组可以使用np.asarray(),如下图:

import numpy as np
cimport cython
from cython.view cimport array as cvarray

def myfunc(int[:,:] input_arr, int arr_len):
   cdef int i
   # allocate new int array
   cdef int[:] new_arr = cvarray(shape=(arr_len,), itemsize=sizeof(int), format="i") 
   for i in xrange(arr_len):
      if input_arr[i, 0] == 1:
         new_arr[i] = 0
      else:
         new_arr[i] = 1
   return np.asarray(new_arr)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-10
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多