ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Runtime学习之路总结

Runtime学习之路总结

文章目录

  • 前言
  • 一、能力模型
  • 二、知识地图
    • 1.底座:NPU抽象硬件架构、Host/Firmware分工与OS底层机制
    • 2.正确性底座:C++并发与内存
    • 3.Runtime子系统
    • 4.两个闭环
  • 三、学习路径
    • 阶段0:建立硬件直觉与Host/Firmware分工意识
    • 阶段1:打通UMD/KMD/Firmware 与命令下发路径
    • 阶段2:补齐C++正确性底座
    • 阶段3:掌握Runtime核心子系统设计
    • 阶段4:对接上层框架与并发隔离
    • 阶段5:建立Debug/Profile的分层排查能力
  • 四、高优先级
  • 五、学习方法
  • 总结

前言

本文主要记录我在求职 NPU / TPU / GPGPU Runtime 岗位过程中的学习路径与思考。Runtime 的本质,是在用户态与硬件之间搭建一条正确、低延迟、可并发、可观测的指令与数据通路。这条通路决定了几件事:一个算子能否被正确下发,一个计算任务能否被高效调度,一个模型能否在多流多卡环境下稳定并发执行。
因此,学习 Runtime 不能只停留在 OS 与 C++ 的基础概念上,更要建立软硬件协同的工程视角。这条通路从三个方向勾勒出学习路径:

  • 向下,需要理解 NPU 的抽象硬件架构——计算单元、存储层级、搬运单元——以及 UMD/KMD 边界、命令队列与内存映射。在有Firmware的架构中,这条通路并不是“用户态直达硬件”的两段式,而是 Host OS(KMD)与 Device Firmware 分工协作的三段式:KMD 掌握资源管理权与系统交互入口,Firmware 掌握设备内部硬件行为的最终控制权。

  • 向上,需要承接 PyTorch、vLLM、推理引擎以及 Triton/Tilelang DSL 对 kernel 下发、整图执行、多流同步和资源隔离的真实需求。

  • 中间,需要用 C++ 并发与内存模型保证多线程提交、队列生产和事件同步的正确性。

每学习一个知识点,都要能回答三个问题:

  1. 机制是什么:它在硬件、Firmware、驱动、runtime 中处于什么位置?与相邻层通过什么接口交互?

  2. 为什么这样设计:它解决了什么约束和取舍?换一种设计会付出什么代价?

  3. 出问题时怎么排查:超时、挂死、性能不达预期时,如何沿着 Host 调度层、命令队列层、Firmware处理层、Device 执行层、端到端尾延迟逐层定位?

这三个问题贯穿全文,只有把 Runtime 的核心内容——设备管理、指令下发、kernel 调度、任务队列、整图下发、多模型并发、资源隔离、内存分配器、多流/事件同步、异常处理——都落到“机制、取舍、排查”三个维度上,知识体系才能真正收拢,而不是停留在名词清单。


一、能力模型

层级核心能力检验标准
硬件事实层理解NPU计算单元(标量/矢量/矩阵)、存储层级(片外 HBM/GM → 片内 L1/L0/UB)、搬运单元(DMA引擎)、片内/片间互联能画出典型算子的数据通路并指出瓶颈层级
Firmware对端层理解KMD与Firmware的指责切分、邮箱/共享内存通信、设备侧状态机能判断故障发生在HOST提交侧还是Device处理侧
驱动边界层理解UMD/KMD、mmap、ioctl、Ring Buffer+Doorbell、IOMMU能讲清一次任务从用户态到硬件队列的完整路径
正确性底座C++并发、内存序、无锁队列、RAII资源管理能写出无数据竞争、内存序正确的提交队列
Runtime子系统Context/Stream/Event、命令队列与指令下发、整图下沉、内存分配、多流、异常能设计最小Runtime原型并说明取舍
上层与观测PyTorch/vLLM/Triton接口需求、profile分层排查能定位host-bound、device-bound、同步与争用问题

二、知识地图

整个体系可以用“一个底座,一条正确性主线,一组Runtime子系统,两个闭环” 概括。

1.底座:NPU抽象硬件架构、Host/Firmware分工与OS底层机制

  • NPU抽象硬件架构:计算单元、存储层级、搬运单元;理解每一级存储与执行流水线的绑定关系;
    • 最终目标:给定一个算子的数据流,能估算出它在哪一级存储上会成为带宽瓶颈,以及 runtime 应该把 tiling 参数和 DMA 描述符设计成什么样来隐藏搬运延迟。
  • Host OS与Firmware的职责切分:
机制AP CPU侧(Host OS/KMD)NPU侧(Firmware/设备 RTOS)
内存内存分配策略、SMMU页表配置、dma-buf导入导出片上存储分区、本地buffer管理、执行硬件配置
中断接受IRQ、执行ISR、更新任务状态、唤醒上层在任务完成或出错时产生中断/邮箱时间
调度作业级排队、依赖管理、优先级、超时控制作业内硬件编排、上下文切换、微秒级任务派发
通信通过BAR/MMIO写Doorbell、读状态寄存器通过邮箱或共享内存与KMD交换命令与状态

关键认知:KMD 决定“把哪箱货物装上哪辆卡车”,Firmware 决定“货物在卡车上怎么摆放、按什么顺序卸货”。 实时性要求极高的微秒级任务切换和上下文保存恢复,通常由 Firmware 在其 RTOS 或裸机循环中完成,以规避 Host OS 调度延迟的不确定性。

UMD/KMD 分层与用户态直接下发:KMD 负责 PCIe 枚举、BAR 映射、中断、大页物理内存等特权操作;UMD 通过 mmap 映射寄存器与命令队列,实现用户态直接下发。

Ring Buffer + Doorbell:用户态构造命令包,写入环状队列,内存屏障后写 Doorbell 通知硬件。注意:Doorbell 通知的对象在有 Firmware 的架构中往往是 Firmware 而非裸硬件,Firmware 再解析描述符并配置硬件。

ioctl 边界:设备打开、内存分配/mmap/free、job 提交、中断处理与状态更新。

IOMMU/SMMU:IOVA 到物理地址翻译,决定设备可见地址与隔离设计。

DMA 与缓存一致性:Coherent DMA 与 Streaming DMA 的区别,invalidate/flush 的时机,PCIe P2P DMA 的数据通路影响。

邮箱(Mailbox)机制:特权邮箱与用户邮箱的分工、命令与响应的同步、以及 Firmware 状态查询。

2.正确性底座:C++并发与内存

  • 内存模型与内存序:relaxed、acquire/release、seq_cst在多核与设备可见性场景下的实际差异。
  • 无锁数据结构:SPSC队列、ABA问题、内存回收、伪共享对ring buffer性能的影响。
  • 现代C++资源管理:RAII、智能指针边界、hot path 避免不变要分配;Device/Context/Stream/Event句柄的封装与析构同步。

3.Runtime子系统

  • 资源模型:Device、Context、Stream、Event/Notify的归属、隔离与生命周期。
  • 命令队列与指令下发:队列满/空、批量提交、doorbell聚合、多线程提交原子性;命令描述符格式本质是Host KMD与Device Firmware之间的契约。
  • 整图下沉:Capture/Replay模式,固化task序列,消除逐算子下发开销;动态shape与动态tiling参数刷新。
  • 内存分配器:Device Memory Pool、片上buffer pool、按生命周期服用、HBM碎片控制。
  • 多流与Event同步:流内保序、流间依赖、计算与搬运重叠、死锁排查。
  • 多模型并发与资源隔离:计算/HBM/片上buffer争用、Stream优先级、QoS/虚拟通道优先级、抢占粒度。
  • Exception Handling and Timeouts:任务超时、设备挂死、可恢复/不可恢复、abort与复位边界;关键区分故障在Host提交侧、Frimware处理侧还是硬件执行侧。

4.两个闭环

  • 向上接口闭环:PyTorchtorch.compile与图后端、vLLM的Triton kernel路由与fallback、Triton/Tilelang DSL对launch配置和参数buffer的接口需求。
  • 可观测闭环:按Host调度层、命令队列层、Firmware处理层、Device执行层、端到端延迟分层建立排查框架。

三、学习路径

阶段0:建立硬件直觉与Host/Firmware分工意识

  • 目标:能画出NPU的典型数据通路,并说清一次算子执行中数据如何从HBM搬到片上、由哪个计算单元消费、哪一级可能成为瓶颈;同时能画出Host KMD与Device Firmware的写作流程图。
  • 重点:
    • 计算单元、存储层级、DMA引擎、片内/片间互联;
    • 理解“存储层级与执行流水线强绑定”;
    • 理解KMD与Firmware在内存、中断、调度、通信四个维度的职责边界;
    • 理解邮箱机制与Doorbell通知的“对端”是谁;
  • 输出物:
    • 一页纸的NPU数据通路图,标志DMA路径、片上buffer和潜在瓶颈点;
    • 一张Host KMD<–>Firmware协作时序图,覆盖任务提交、执行、完成中断、状态更新。

阶段1:打通UMD/KMD/Firmware 与命令下发路径

  • 目标:能完整讲清一次任务从用户态API调用到硬件队列消费、再到Firmware解析执行的完整路径。
  • 重点:
    • mmap映射寄存器空间与命令队列;
    • Ring Buffer生产/消费模型;
    • Doorbell触发前的内存屏障;
    • ioctl的职责边界;
    • IOMMU地址翻译与设备可见地址;
    • Coherent/Streaming DMA与缓存维护;
    • 邮箱/共享内存通信机制,以及Firmware如何解释命令描述符并配置硬件;
    • 命令格式作为Host-Firmware 契约的设计含义;
  • 输出物:一个用户态SPSC ring buffer模拟提交队列,包含内存屏障、水位检查和批量提交逻辑;附一份“命令描述符字段说明”,标注每个字段由Host填写、由Firmware解释还是由硬件消费。

阶段2:补齐C++正确性底座

  • 目标:能在多线程、弱内存一致性硬件假设下写出正确的runtime提交代码。
  • 重点:
    • std::memory_order的实际语义、无锁SPSC队列、伪共享、ABA与内存回收、RAII句柄管理、hot path分配控制。
  • 输出物:
    • 一个带压测的无锁SPSC队列,并记录不同内存序下的性能与正确性差异。

阶段3:掌握Runtime核心子系统设计

  • 目标:能把岗位职责中的每个子系统当作有约束的工程问题来讨论,而不背API。
  • 重点:
    • Context/Stream/Event资源模型与隔离;
    • 命令队列与多线程提交;
    • Capture/Replay整图下沉及动态参数刷新;
    • 多级内存分配器与碎片控制;
    • 多流同步、计算搬运重叠、死锁排查;
    • 多模型并发下的优先级、QoS与抢占粒度;
    • 超时、abort、设备挂死与恢复边界;
    • 故障定位的“对端分界”:Host提交失败、Firmware无法处理、硬件执行异常,三者的区分方法和各自的排查手段。
  • 输出物:
    • 一个最小runtime原型设计文档,至少覆盖Device/Context/Stream/Event、任务队列、内存池和超时处理;附一张“任务挂死排查决策树”,标注Host侧与Firmware侧的分界检查点。

阶段4:对接上层框架与并发隔离

  • 目标:理解runtime接口形态由上层框架的使用方式决定。
  • 重点:
    • PyTorch与图后端、Graph Capture的嵌入方式;
    • vLLM中Triton kernel路由、补丁机制与fallback;
    • Triton/Tilelang DSL对grid/block launch、参数buffer、动态tiling的接口需求;
    • 多模型并发下的资源争用、优先级反转和隔离手段。
  • 输出物:
    • 一份“上层框架对runtime接口需求清单”,按kernel launch、内存、stream、同步、错误处理分类。

阶段5:建立Debug/Profile的分层排查能力

  • 目标:面对“NPU利用率低”这类问题,能逐层排查而不是直接跳进kernel优化。
  • 排查框架:
层次核心问题典型手段
Host调度层是否host-bound下发间隔、capture/replay命中率、框架开销
命令队列层队列是否满、doorbell是否及时Ringbuffer水位、提交批大小
Firmware处理层Firmware是否取走命令、状态机是否卡住、邮箱是否响应邮箱往返时间、Firmware状态寄存器、命令超时计数
Device执行层kernel是否高效、搬运是否重叠kernel耗时、DMA与计算重叠率、片上buffer命中
端到端多流/多模型尾延迟流间同步等待、资源争用、优先级反转
  • 输出物:
    • 一棵可执行的性能问题排查树,每个分支给出验证方法和可能结论;每个分支明确标注“这是Host还是Firmware侧的问题”。

四、高优先级

  1. UMD/KMD边界+Ring Buffer/Doorbell+内存序;
  2. Host/Firmware职责切分+邮箱通信+命令描述符契约:用于在生产环境中定位跨侧故障;
  3. DMA/IOMMU+缓存一致性+零拷贝:决定能否正确设计数据通路;
  4. C++无锁并发+内存模型:决定队列和同步代码是否正确;
  5. Context/Stream/Event模型+整图下沉;
  6. 内存分配器+多流并发+异常超时;
  7. vLLM/Triton接口侧+profile方法论:体现上下游生态理解和调优闭环;

五、学习方法

建议每个阶段都产出可验证的东西:

  • 一张图:数据通路图/协作时序图;
  • 一个原型:ringbuffer 或者最小runtime设计;
  • 一次压测:不同内存序、不同批提交策略下的性能对比额;
  • 一棵排查树:从host-bound到firmware-stuck到device-bound的定位路径;
  • 一份接口清单:上层框架对runtime的真实需求;
  • 一份契约文档:命令描述符的字段定义与两侧职责标注。

每学习一个机制,额外写一个“失败场景”:如果这个机制缺失或误用,会出现什么现象、如何定位、问题可能落在Host侧还是Firmware侧。


总结

NPU Runtime 的学习之路,可以概括为一条闭环:

硬件事实 → Host/Firmware 分工 → 驱动边界 → C++ 正确性 → Runtime 子系统 → 上层接口 → 可观测与调优 → 回到硬件事实验证。

从“构造一条从用户态到 NPU 的最小任务通路”开始。先把 Ring Buffer、Doorbell、内存屏障、邮箱通信和一次任务下发打通,再逐步扩展内存池、多流、整图下沉、多模型并发和 profile 能力。每扩展一个模块,都回到三个问题:机制是什么、为什么这样设计、出问题怎么排查;并且多问一句:这个问题在 Host 侧还是 Firmware 侧?

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进