Numba 并行编译报 Illegal IR, del found,检查内联 argmax 组合
Numba 0.68.0 的强制内联、结构化字段视图和嵌套 argmax 归约组合可能触发非法 IR。可先退回串行 JIT,保留输入和算法,再按结果与耗时评估是否恢复并行。
Numba 0.68.0 编译带结构化数组的并行函数时,可能停在 native parfor lowering,而不是得到业务结果:
CompilerError: Failed in nopython mode pipeline
Illegal IR, del found at: del ...
一条明确的组合是:外层 parallel=True 与 prange,一个 inline="always" 辅助函数返回结构化 dtype 的字段视图,另一个强制内联辅助函数在末尾调用 np.argmax(),两者又以 outer(inner(...)) 直接嵌套。
这里的 del 指编译器中间表示里的清理节点,不表示用户源码里一定写了 del。去业务文件搜索并删除同名变量,通常改不到触发校验的那一层。
先退回串行 JIT,保留算法与输入
如果当前任务允许暂时放弃并行,先同时去掉外层并行选项和 prange。下面给出结构化字段取最大值的简化串行结构,说明修改位置;它不是完整故障复现:
import numba
import numpy as np
@numba.njit(inline="always")
def weights_of(record):
return record["weights"]
@numba.njit(inline="always")
def choose(values):
return np.argmax(values)
@numba.njit(parallel=False)
def choose_rows(records):
result = np.empty(len(records), dtype=np.intp)
for index in range(len(records)):
result[index] = choose(weights_of(records[index]))
return result
示例要求 records 是含 weights 字段的 NumPy 结构化数组,每条字段都是非空的一维数值数组。实际程序仍应保留原来的输入检查、概率归一化或其他计算,不要为了让示例编译而删除必要算法。
串行 JIT 不等于关闭整个 JIT。它避开这次涉及的并行转换路径,但可能明显增加运行时间;若原算法使用随机数,线程调度和随机序列也可能变化,不能要求与旧并行运行逐项随机结果相同。应按业务的确定性结果或统计约束验收。
必须并行时,减少触发组合后再比较结果
可以在隔离分支评估取消不必要的强制内联,或将这条内部 argmax 归约改为适合业务的串行实现。后者必须保留空数组、最大值并列及 NaN 等语义;一个只比较 > 的小循环不自动等价于 NumPy 对所有输入的行为。
Numba 的并行优化器会将支持的 np.argmax 展开为并行归约。当前 0.68.0 的相关清理流程与嵌套 parfor 组合仍可能保留不该存在的清理节点;不能把修改库内私有 IR 清理函数当作应用的常规修复,也不能仅凭开发分支修补建议判断某个正式版已解决。
保留一个能定位此组合的小输入,再覆盖原有计算结果、写入数组和异常分支。采用串行方案时记录可接受的耗时上限;后续恢复并行时重新比较结果与资源占用。若错误发生在普通类型推断、输入 dtype 不匹配等阶段,则应按新的堆栈处理,不把所有 Numba 编译失败归到这项 IR 问题。


