第九周开发日志(3.22-3.29)

工作总结

本周的主要工作是实现一个基于 Clang front-end 的 RKNPU 代码生成工具。该工具面向“显式标注 + 代码生成”的使用模式:用户在 C 源码中对可加速代码段进行手工标注,工具负责识别被标注的算法结构,并将其转换为对应的 NPU 任务提交流程,从而把原本由 CPU 执行的计算卸载到 NPU 上。

当前版本已经完成从前端识别到代码生成的基础闭环,但支持范围仍较为有限,仅支持标准形态的 matmul 算子。 代码仓库


本周进展

  • 完成了基于 Clang front-end 的前端识别方案,可以对带有显式标记的 C 代码进行分析。
  • 完成了标准矩阵乘法代码模式的识别与验证,能够从纯 CPU 风格实现中提取出可下沉到 NPU 的计算区域。
  • 实现了面向 RKNPU 的基础代码生成流程,能够将识别后的 matmul 区域转换为对应的 NPU 任务构造与提交流程。
  • 建立了“手工标注 -> 识别分析 -> 代码生成”的最小闭环,为后续扩展更多算子和更复杂的调度机制打下基础。

遇到的问题与分析

本周原计划继续将 NPU 的任务调度粒度进一步细化到单个算子级别,以增加可调度时刻的数量,使单个进程占用 NPU 的最小时间片进一步缩小。

但在分析后发现,这一路径存在明显问题:如果将调度边界压缩到单个算子级别,将显著提高中断触发频率。虽然这样能够提升调度灵活性,但中断处理开销也会同步增大,整体性能收益并不理想,甚至可能得不偿失。

在此基础上,我进一步尝试思考和验证“任意时刻 checkpoint”方案,即在 NPU 运行过程中的任意时刻保存执行状态,并在之后恢复执行。当前主要遇到以下两个核心困难:

  1. 硬件层面缺少统一暂停机制

    现有 RKNPU 硬件接口中,没有看到能够让多个功能部件在同一时刻一致性暂停的机制。因此,即使希望在某一时刻保存状态,也难以保证采集到的是一个全局一致、可恢复的硬件状态快照。

  2. 恢复执行难以做到无副作用

    RKNPU 的启动方式本质上依赖于 PC 寄存器的启动脉冲。也就是说,恢复时并不是“从某个硬件内部断点继续执行”,而更接近一次重新触发执行。如果保存状态时任务正处于某个算子的执行过程中,那么恢复后很可能会导致该算子被重复执行,从而产生任务重放问题,破坏执行语义。


本周结论

本周完成了 RKNPU 代码生成工具链的第一版原型,实现了从 C 代码显式标注到 NPU 任务生成的基本流程,证明了“标准矩阵乘法代码经识别后自动生成 RKNPU 调用代码”这一方向是可行的。