Cython中memoryviewslice转ndarray报错及布尔mask类型定义问题
问题解答
1. 类型转换错误的原因与修复
你遇到的TypeError: Cannot convert _cython_magic_xxx._memoryviewslice to numpy.ndarray,根源是参数类型标注与后续代码的类型不匹配:
- 当给
potential标注np.float64_t[:, :]时,Cython会自动将传入的numpy数组包装为内存视图(memoryview),而非原生numpy数组。 - 代码中
cdef np.ndarray[np.float64_t, ndim=2] input_matrix = potential.copy()这一行,potential.copy()返回的是内存视图的切片对象,无法直接赋值给np.ndarray类型变量,因此触发转换错误。
修复方案二选一:
方案A:将input_matrix改为内存视图类型
直接把input_matrix的类型定义为内存视图,适配参数类型:
cdef np.float64_t[:, :] input_matrix = potential.copy()
后续对input_matrix的下标访问操作无需修改,内存视图支持该操作。
方案B:先将内存视图转回numpy数组
如果需要保留input_matrix的numpy数组类型,先把potential转成ndarray再复制:
cdef np.ndarray[np.float64_t, ndim=2] pot_arr = np.asarray(potential) cdef np.ndarray[np.float64_t, ndim=2] input_matrix = pot_arr.copy()
2. 为mask参数定义布尔数组类型
在Cython中,numpy布尔数组对应的类型是np.npy_bool,直接给mask标注二维内存视图类型即可:
def SOR_potential(np.float64_t[:, :] potential, np.npy_bool[:, :] mask, int max_iter, float error_threshold, float alpha):
同时注意测试代码要传入numpy布尔数组,不能用原生列表:
test = np.array([[True, False], [True, False]], dtype=np.bool_) pot = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float64) SOR_potential(pot, test, 50, 0.1, 0.0)
修改后的完整Cython代码示例
%%cython cimport cython import numpy as np cimport numpy as np from libc.math cimport pi, fabs #SOR function @cython.boundscheck(False) @cython.wraparound(False) @cython.initializedcheck(False) @cython.nonecheck(False) def SOR_potential(np.float64_t[:, :] potential, np.npy_bool[:, :] mask, int max_iter, float error_threshold, float alpha): cdef int height = potential.shape[0] cdef int width = potential.shape[1] cdef int it = 0 cdef float error = 0.0 cdef float sor_adjustment # 使用内存视图类型的input_matrix cdef np.float64_t[:, :] input_matrix = potential.copy() if alpha == 0.0: alpha = 2/(1+(pi/((height+width)*0.5))) cdef int row, col while True: for row in range(1, height-1): for col in range(1, width-1): if not(mask[row][col]): potential[row][col] = 0.25*(input_matrix[row-1][col] + input_matrix[row+1][col] + input_matrix[row][col-1] + input_matrix[row][col+1]) sor_adjustment = alpha * (potential[row][col] - input_matrix[row][col]) input_matrix[row][col] = sor_adjustment + input_matrix[row][col] # 用libc的fabs替代np.abs,提升性能 error += fabs(input_matrix[row][col] - potential[row][col]) if error < error_threshold or it > max_iter: break error = 0 it +=1 # 返回时将内存视图转成numpy数组 return np.asarray(input_matrix), error, it
内容的提问来源于stack exchange,提问作者Mephistopheles Faust
相关产品推荐
相关产品推荐

