Cython中MemoryviewSlice与C数组兼容问题及GROUP BY实现问询
问题:如何让Cython的memoryview函数同时兼容NumPy数组和C静态数组?
我定义了一个接受memoryview输入的Cython函数base_func用于处理NumPy数组,但将纯C定义的临时float数组传入时,报错Operation not allowed without gil。需要修改base_func使其同时兼容numpy.array和cdef C数组。
项目背景
计划将1D或2D np.ndarray的GROUP BY操作Cython化,设计Python接口如group_mean(data, group),通过FuncWrapper封装C函数(如c_group_mean)实现,还可扩展c_group_std等函数对应group_std接口。
已遇问题与处理思路
- 形状对齐与NAN输入:
data可能为(m,n)形状、group为(n,)形状,需对齐并通过np.where将data为NAN的group设为-1。 - 2D数组处理:C函数仅支持1D输入,需用
prange并行处理每行,因此需要NOGIL模式。 - 结果形状适配:(m,n)输入的输出形状可能为(m, group_number)(如
group_mean)或(m,n)(如group_demean),需不同的FuncWrapper。 - Python包装器无法接收C函数指针:参考相关内容创建
CFuncWrapper(cdef类)封装C函数。 - 临时C数组初始化与函数复用:在
c_group_mean中需临时数组存储分组求和与计数,当前模板在Windows 11报错但macOS可用,且无法将临时float数组传入c_mean作为result参数。
相关代码
cdef void base_func(float[:] vec1) noexcept nogil: return def python_entry(vec: np.ndarray): cdef float[:] vec_view = vec base_func(vec_view) cdef void cfunc(float[:] vec2) noexcept nogil: cdef float[10] tmp_vec base_func(tmp_vec)
错误信息
cdef void cfunc(float[:] vec2) noexcept nogil: cdef float[10] tmp_vec base_func(tmp_vec) ^ ------------------------------------------------------------ c_test.pyx:21:14: Operation not allowed without gil
代码模板示例
cdef void c_mean (float[:] data, int[:] group, float[:] result, const int length, const int group_number): float[group_num] sum_up int[group_num] count
后续思考
- 是否需将
float[group_num] sum_up改为float* sum_up = <float*>malloc(...)以适配Windows 11? - 是否需修改C函数模板以同时支持memoryviewslice和float*传入,或调整架构为:
1. Python Interface: group_mean 2. FuncWrapper: pass in different base function, like c_group_mean 3. CFuncWrapper: make sure python object FuncWrapper can accept cdef functions 4. TODO: convert MemoryviewSlice to float*? 5. base c functions: c_group_mean, c_group_std
内容的提问来源于stack exchange,提问作者LeonM
相关产品推荐
相关产品推荐

