NPU的编译器开发:BYOC(Bring Your Own Codegen)
一个让我熬夜到凌晨三点的bug
去年做某款RISC-V NPU的编译器后端时,遇到一个诡异的推理错误——模型在x86上跑得好好的,一部署到NPU上,某个卷积层的输出就全变成了NaN。查了两天,最后发现是BYOC框架里一个算子注册的优先级问题,导致编译器把本该走NPU加速的算子,错误地fallback到了CPU上的一个未实现版本。
这个坑让我意识到:BYOC(Bring Your Own Codegen)虽然是个好东西,但用不好就是给自己挖坟。今天聊聊这东西到底怎么玩。
BYOC到底解决什么问题
传统TVM或MLIR的编译流程里,你要支持一个新NPU,得改整个编译器堆栈——从IR定义到调度器再到代码生成器,动辄几万行代码。BYOC的思路是:你只需要告诉编译器“这个子图归我管”,然后自己写一个代码生成器把子图翻译成NPU指令就行。
说白了,BYOC就是编译器里的“外包”——你定义接口,我实现后端,互不干扰。
核心架构:三个关键组件
1. 算子标注器(Annotator)
这是BYOC的入口。编译器遍历计算图,找到那些能跑在NPU上的算子组合,打上“此子图归NPU管”的标签。