将Cython融合类型强制转换为C++指针
Casting Cython fused types to C++ pointers
这是一个关于从Cython融合类型转换为C++类型的一般问题,我将用一个简单的例子来描述它。考虑一下表面的C++函数模板:
template <typename T>
void scale_impl(const T * x, T * y, const T a, const size_t N) {
for (size_t n = 0; n < N; ++n) {
y[n] = a*x[n];
}
}
我希望能够在任何类型和形状的任何numpy ndarray
上调用此函数。使用Cython,我们首先声明函数模板:
cdef extern:
void scale_impl[T](const T * x, T * y, const T a, const size_t N)
然后声明我们希望操作的有效标量类型:
ctypedef fused Scalar:
float
double
...
最后实现实际的Cython垫片:
def scale(ndarray[Scalar] x, Scalar a):
"""Scale an array x by the value a"""
cdef ndarray[Scalar] y = np.empty_like(x)
scale_impl(<Scalar *>x.data, <Scalar *>y.data, a, x.size)
return y
这不起作用有两个原因:
x
只能是一维的,而不是任意(或至少是多个)维的- 转换为
<Scalar *>
会引发错误,因为Scalar
实际上是一个Python对象
人们显然可以明确地推断出专业化:
if Scalar is float:
scale_impl(<float *>x.data, <float *>y.data, a, x.size)
if Scalar is double:
scale_impl(<double *>x.data, <double *>y.data, a, x.size)
if Scalar is ...
但这导致了我必须为容纳多个融合类型的函数手工编写的代码路径的组合数量,并造成了(我认为)引入融合类型是为了避免的情况。
有没有任何方法可以将任意维(在合理范围内)数组传递给Cython函数,并让它推导标量数据的指针类型?或者,使用这种功能最合理的折衷方案是什么?
(另请参阅使用Cython包装c++模板以接受任何numpy数组中给出的答案,这是一个非常相似的问题。)
使用形式&x[0]
而不是尝试强制转换x.data
解决了选择正确模板专用化的问题。2D阵列的问题有点复杂,因为阵列不能保证是连续的或有序的。
我会创建一个对1D数组进行实际操作的函数,并封装一个根据需要进行扁平化的简单函数:
def _scale_impl(Scalar[::1] x, Scalar a):
# the "::1" syntax ensures the array is actually continuous
cdef np.ndarray[Scalar,ndim=1] y = np.empty_like(x)
cdef size_t N = x.shape[0] # this seems to be necessary to avoid throwing off Cython's template deduction
scale_impl(&x[0],&y[0],a,N)
return y
def scale(x, a):
"""Scale an array x by the value a"""
y = _scale_impl(np.ravel(x),a)
return y.reshape(x.shape) # reshape needs to be kept out of Cython
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++