如何从numba-JIT编译函数返回混合类型一维结构化数组?
报错原因
- 直接触发点:构造numpy数组时传入的是
[(元组内容)],多套了一层列表,导致NumPy生成的是二维数组,和你在签名里声明的一维结构化数组返回类型不匹配,和报错信息里提示的维度冲突完全对应。另外你的测试代码本身有笔误:解包时写的是a,b,c,d,f漏了e,打印时又多写了一个e,运行时也会触发变量不存在的错误。 - 根本问题:实现思路绕了远路。Numba nopython模式原生支持多元素元组作为返回值,不需要借助numpy结构化数组实现多返回值,额外封装结构化数组反而会带来不必要的类型适配开销,也容易触发类型不匹配问题。
推荐写法(原生元组返回)
直接返回Python元组即可,性能比封装结构化数组更好,写法也最简洁。如果需要显式声明类型签名,直接对应元组类型即可:
import numba as nb # 显式声明签名的版本 @nb.njit(nb.types.Tuple((nb.int64, nb.int64, nb.float64, nb.float64, nb.int64))(nb.int64)) def foo(ii: int): return 1 + ii, 2 + ii, 3.0 + ii, 4.0 + ii, 5 + ii # 也可以不写签名,让Numba第一次调用时自动推导类型,代码更短 # @nb.njit # def foo(ii: int): # return 1 + ii, 2 + ii, 3.0 + ii, 4.0 + ii, 5 + ii a, b, c, d, e = foo(0) print(a, b, c, d, e) # 运行输出:1 2 3.0 4.0 5
特殊场景:必须返回结构化数组的修正方案
如果有业务需求必须返回numpy结构化类型而非元组,只要去掉构造数组时多余的外层列表,同时修正签名匹配返回的结构化标量类型即可:
import numpy as np import numba as nb struct_dtype = np.dtype('i8,i8,f8,f8,i8') # 注意这里返回的是单个结构化标量,不是数组,不要加[:]标记 @nb.njit(nb.from_dtype(struct_dtype)(nb.int64)) def foo(ii): return np.array( ( 1 + ii, 2 + ii, 3.0 + np.float64(ii), 4.0 + np.float64(ii), 5 + ii, ), dtype=struct_dtype ) res = foo(0) # 结构化标量需要按字段名取值 a, b, c, d, e = res['f0'], res['f1'], res['f2'], res['f3'], res['f4'] print(a, b, c, d, e)
内容的提问来源于stack exchange,提问作者s-m-e
相关产品推荐
相关产品推荐

