3、NPU调度框架概述:调度框架的定义、核心功能与常见调度模型
在Edge AI(边缘人工智能)场景中,NPU(神经网络处理单元)通常承担着实时推理、图像分类、目标检测、语音识别等密集型计算任务。与CPU的多任务分时复用不同,NPU的硬件资源(如MAC阵列、片上SRAM、DMA通道、卷积加速器)具有强专用性和有限并发性。若缺乏统一的调度框架,多个推理任务或来自不同应用的计算请求将直接竞争硬件资源,导致优先级翻转、内存带宽争抢、推理延迟抖动甚至硬件死锁。NPU调度框架正是为了解决这一系列问题而设计的核心软件中间层,它位于应用层与NPU硬件驱动之间,负责将上层计算请求有序、高效、可控地映射到物理执行单元上。本章将系统阐述调度框架的定义、核心功能、常见调度模型及其适用场景,帮助开发者建立从任务提交到硬件执行全链路的调度认知。
3.1 调度框架的定义与设计目标
调度框架(Scheduling Framework)在NPU软件栈中,是指一组协调任务提交、队列管理、资源分配与硬件执行之间关系的软件组件集合。它通常由用户态库(如libnpu)、内核态驱动(Kernel Driver)以及固件中的微调度器(Micro-Scheduler)共同构成。从抽象层次看,调度框架屏蔽了底层硬件寄存器、DMA描述符、中断处理等细节,向上提供统一的推理任务API(如npu_submit_task()、npu_wait_completion()),向下通过命令队列(Command Queue)与硬件交互。
调度框架的设计目标可以归纳为以下四点:
- 高吞吐与低延迟的平衡:边缘设备往往同时承载多个推理流,调度框架需在批量处理(提升MAC利用率)与快速响应(降低单任务延迟)之间找到平衡点。
- 确定性(Determinism):对于自动驾驶、工业质检等实时控制场景,任务完成时间必须可预测,调度框架需提供有界延迟保证。
- 资源利用率最大化:NPU的算力、带宽、片上内存均有限,调度框架需通过任务合并、流水线重叠等手段减少空闲周期。
- 故障隔离与安全:当某个应用异常(如死循环提交任务)时,调度框架应能限制其影响范围,避免拖垮整个NPU系统。
3.2 调度框架的核心功能
调度框架的功能可以拆解为三个核心维度:任务分配(Task Allocation)、优先级管理(Priority Management)和资源隔离(Resource Isolation)。三者相互关联,共同决定系统的整体行为。
3.2.1 任务分配
任务分配解决的是“任务去哪里执行”的问题。NPU内部通常包含多个计算引擎(如卷积引擎、池化引擎、激活引擎)和多个内存通道。调度框架需要根据任务类型(卷积密集/内存密集)、输入数据位置(DDR/片上SRAM)以及当前各引擎的负载状态,决定任务的执行路径。具体操作流程包括:
- 任务解析:解析上层传入的推理请求,提取模型ID、输入张量地址、输出张量地址、优先级标志等信息。
- 队列选择:根据任务属性(实时/普通/批量)选择对应的硬件命令队列。例如,实时任务进入高优先级队列,批量任务进入低优先级队列。
- 资源预分配:为任务分配所需的片上缓冲区(如权重缓冲区、激活缓冲区)和DMA通道带宽。
- 命令描述符填充:将任务参数封装为硬件可识别的命令描述符(Command Descriptor),写入队列内存。
3.2.2 优先级管理
优先级管理解决的是“谁先执行”的问题。在Edge AI场景中,不同任务的重要性差异巨大:例如,ADAS(高级驾驶辅助系统)的障碍物检测延迟超过50ms可能导致事故,而车载娱乐系统的图像分类延迟500ms也无感知。调度框架需支持以下机制:
- 静态优先级:在任务创建时指定固定优先级(如0-255),高优先级任务优先占用NPU。
- 动态优先级调整:根据任务等待时间、剩余截止时间(Deadline)动态提升优先级,避免低优先级任务饿死。
- 优先级继承:当低优先级任务持有高优先级任务所需的资源(如锁)时,临时提升低优先级任务的优先级,防止优先级反转。
- 抢占(Preemption):高优先级任务到达时,调度框架可暂停当前正在执行的低优先级任务,保存其上下文(中间计算结果、DMA状态),待高优先级任务完成后恢复。NPU抢占比CPU更复杂,因为硬件流水线不能随意中断,通常采用“在安全点抢占”策略。
3.2.3 资源隔离
资源隔离解决的是“如何防止互相干扰”的问题。在多租户(多应用共享NPU)场景下,若不加隔离,一个应用的内存越界可能破坏另一个应用的推理数据,或一个应用大量占用带宽导致其他应用性能骤降。调度框架通过以下手段实现隔离:
| 隔离维度 | 实现机制 | 典型参数 |
|---|---|---|
| 地址空间隔离 | IOMMU(输入输出内存管理单元)为每个应用分配独立的设备虚拟地址空间 | 页表粒度4KB/2MB |
| 带宽配额 | 调度框架监控每个队列的DMA读写带宽,超出配额时降速或排队 | 带宽上限如2GB/s |
| 计算资源配额 | 限制每个应用同时占用的MAC阵列周期数或推理并发数 | 最大并发任务数=4 |
| 故障域隔离 | 当某个队列的任务连续超时或触发硬件错误时,调度框架将该队列标记为“故障”,不再调度新任务,并通知应用 | 超时阈值=100ms |
rknn_core_mask将不同模型绑定到不同NPU核心,实现物理级别的资源隔离,避免相互干扰。
3.3 常见调度模型及适用场景
调度模型决定了任务在队列中的排序与执行方式。不同的模型在公平性、实时性、吞吐量方面各有取舍。以下三种模型是NPU调度框架中最基础的构建块,实际产品中往往组合使用。
3.3.1 FIFO(先入先出)调度模型
原理:任务按照到达时间顺序排列,先到达的任务先执行,后到达的任务排队等待。FIFO模型实现最简单,只需维护一个先进先出的队列指针。
优点:完全公平,无饥饿现象;实现开销几乎为零;适合任务执行时间相近、无严格实时要求的场景。
缺点:一个长任务会阻塞后续所有短任务,导致平均等待时间较长;无法区分任务重要性。
适用场景:离线批量推理(如夜间训练数据预处理)、日志分析、非交互式图像后处理。例如,在智能相册应用中,批量缩略图生成任务使用FIFO即可满足需求。
3.3.2 优先级调度模型
原理:每个任务分配一个优先级数值,调度器始终选择当前就绪队列中优先级最高的任务执行。优先级可以是静态的(创建时固定),也可以是动态的(根据等待时间或截止时间调整)。
优点:能够保证关键任务的实时性;支持抢占式调度,高优先级任务可立即执行。
缺点:低优先级任务可能长时间得不到执行(饥饿);需要额外的机制(如老化)防止饿死;优先级反转问题需要额外处理。
适用场景:ADAS、工业机器人控制、实时视频分析。例如,在智能摄像头中,行人检测任务优先级设为高(10ms内响应),而背景虚化任务优先级设为低(可容忍100ms延迟)。
3.3.3 时间片轮转(Round-Robin)调度模型
原理:将CPU/NPU时间划分为固定长度的时间片(Time Slice),就绪队列中的任务轮流执行一个时间片。若任务在时间片内未完成,则被挂起,放入队尾等待下一轮。
优点:公平性好,所有任务都能获得近似相同的执行时间;响应时间有上界(取决于任务数量和时间片大小);适合交互式场景。
缺点:上下文切换开销较大(需要保存/恢复NPU流水线状态);时间片大小难以确定——太小则切换频繁,太大则退化为FIFO。
适用场景:多路视频流同时解码+推理的场景,如安防监控的16路实时分析。每路视频流分配一个时间片,保证各路视频的推理延迟相对均衡。
| 调度模型 | 公平性 | 实时性 | 吞吐量 | 实现复杂度 | 典型场景 |
|---|---|---|---|---|---|
| FIFO | 高 | 低 | 中 | 极低 | 离线批量、日志处理 |
| 优先级 | 低(可能饥饿) | 高 | 中高 | 中 | ADAS、实时检测 |
| 时间片轮转 | 高 | 中 | 中 | 中 | 多路视频流分析 |
3.4 案例拆解:智能座舱多任务NPU调度设计
下面通过一个完整的案例,展示调度框架在实际Edge AI产品中的设计过程。
背景与约束:某智能座舱域控制器采用一颗算力8TOPS的NPU,需要同时运行以下任务:
- 驾驶员疲劳监测(DMS):每帧耗时8ms,要求端到端延迟≤30ms,优先级最高。
- 手势识别:每帧耗时15ms,要求延迟≤80ms,优先级中。
- 车载娱乐图像超分:每帧耗时40ms,无严格延迟要求,优先级低。
- 行车记录仪视频编码辅助:每帧耗时20ms,要求吞吐稳定,优先级中低。
初始现象:采用单一FIFO队列时,当超分任务(40ms)进入队列后,DMS任务被迫等待,实测DMS延迟飙升至65ms,超出30ms的硬性要求,触发系统告警。
分析过程:通过调度日志发现,FIFO队列中长任务阻塞了短任务。进一步分析任务特征:DMS任务周期固定(每帧间隔33ms),但执行时间短;超分任务执行时间长且无实时要求。因此需要引入优先级调度。
实际操作步骤:
- 将NPU硬件队列拆分为3个:高优先级队列(Q0)、中优先级队列(Q1)、低优先级队列(Q2)。
- 配置调度策略:Q0采用优先级抢占模型,Q1和Q2采用加权时间片轮转(权重比2:1)。
- 将DMS任务绑定到Q0,手势识别绑定到Q1,超分和视频编码绑定到Q2。
- 设置Q0的抢占安全点:在DMA传输完成且MAC阵列空闲时允许抢占,避免中断正在执行的卷积计算。
- 为Q2设置带宽上限为1.5GB/s,防止超分任务占用过多DDR带宽影响其他任务。
结果对比:调整后,DMS延迟稳定在12-18ms,满足30ms要求;手势识别延迟约50ms;超分任务吞吐量下降约15%,但可接受。系统整体CPU占用率降低20%(因为不再需要频繁的软件层任务切换)。
风险与代价:优先级抢占引入了上下文切换开销(约0.5ms/次),且需要驱动层支持“安全抢占点”检测。此外,Q2的带宽限制导致超分任务在4K分辨率下帧率从30fps降至25fps,需产品侧确认可接受。
复盘经验:调度框架设计应遵循“先分类、再定策略”的原则。首先根据任务的实时性、周期性和资源消耗特征进行分类,然后为每个类别选择最合适的调度模型。同时,务必为高优先级队列设置抢占安全点,否则抢占机制无法真正落地。
3.5 调度框架选型与设计要点
在实际项目中,选择或设计NPU调度框架时,需要关注以下关键点:
- 硬件队列深度:队列深度决定了调度器可缓冲的任务数量。深度过小会导致任务提交失败(返回忙),深度过大会增加内存占用和延迟。一般建议队列深度为最大并发任务数的2-4倍。
- 调度决策频率:调度器在什么时机触发决策?常见的有:任务到达时、任务完成时、时间片耗尽时、高优先级任务到达时。决策频率越高,系统响应越快,但CPU开销也越大。
- 与DMA的协同:NPU任务通常涉及多次DMA传输(输入加载、权重加载、输出写回)。调度框架需将DMA传输与计算重叠,避免计算单元等待数据。这要求调度器具备“流水线感知”能力。
- 多NPU扩展:若系统有多个NPU核心,调度框架需支持任务跨核心迁移或负载均衡。例如,当核心0的队列满时,可将任务调度到核心1。