【发布时间】:2018-12-01 12:39:32
【问题描述】:
我想为使用 ctypedef 定义的 memoryview 分配堆栈内存,并将其作为 numpy ndarray 返回。 This question 讨论了一些分配方法,但问题是我不知道如何以编程方式将我的自定义 ctypedef 映射到分配所需的相应 numpy dtype 或 Python 类型代码。
例如:
from cython cimport view
import numpy as np
ctypedef int value_type # actual type subject to change
# np.empty requires me knowing that Cython int maps to np.int32
def test_return_np_array(size_t N):
cdef value_type[:] b = np.empty(N, dtype=np.int32)
b[0]=12 # from ctypedef int ^
return np.asarray(b)
# or, Cython memoryview requires the type code 'i'
def test_return_np_array(size_t N):
cdef value_type[:] b = view.array(shape=(N,), itemsize=sizeof(int), format="i")
b[0]=12 # from ctypedef int ^
return np.asarray(b)
我正在使用 typedef,以便可以灵活地更改实际数据类型(例如从 int 到 long long),而无需修改所有代码。
在纯 Python 中,类型检查很容易:
value_type = int
print(value_type is int) # True
print(value_type is float) # False
在 numpy 中,这也可以通过将 dtype 参数化为字符串来轻松实现,例如 value_type="int32" 然后调用 np.empty(N, dtype=value_type)。使用我的 ctypedef,Cython 不会编译 np.empty(N, dtype=value_type),并抱怨“'value_type' 不是常量、变量或函数标识符”。是否有可能在编译时实现这样的目标?
用户不必管理返回的内存,因此malloc 将不是一个选项。
我想出了一个使用 C++ 向量的 hack:<value_type[:N]>vector[value_type](N).data(),但这似乎会导致内存错误。
【问题讨论】:
-
我的解决方法是手动定义运行时类型和相应的编译时类型,如
value_type = np.int32和ctypedef np.int32_t value_type_t(可以轻松更改为value_type = np.int64和ctypedef np.int64_t value_type_t),基于在/Cython/Includes/numpy/__init__.pxd中的映射。还提到了here。 -
你说得对,这是最简单的解决方案。我已经根据一些考虑更新了我的答案,这解释了为什么更强大的方法可能值得麻烦。