【发布时间】: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
如何做到这一点?我的方式正确吗?更具体的问题:
- 引用
new_arr[x]会返回Python 吗?我希望它是数组的纯 C 索引 -
cdef int[:] new_arr = ...和cdef int[::1] new_arr = ...之间有区别吗?后者看不懂 -
cvarray是在这里分配内存的最佳方式,还是clone?对于 numpy 数组,我会使用np.empty并且我试图在这里获得同样高效的东西。另外,为什么在cvarray调用中需要format="i"。 -
最后,如果
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.array或numpy.asarray从 Cython 内存视图中获取 NumPy 数组。np.asarray实际上只是numpy.array的一个薄包装。不过,我不太确定您将如何分配新数组。如果您正在复制内存视图,则其他答案中给出的示例似乎不起作用。