3、NPU调度框架概述:调度框架的定义、核心功能与常见调度模型

在Edge AI(边缘人工智能)场景中,NPU(神经网络处理单元)通常承担着实时推理、图像分类、目标检测、语音识别等密集型计算任务。与CPU的多任务分时复用不同,NPU的硬件资源(如MAC阵列、片上SRAM、DMA通道、卷积加速器)具有强专用性和有限并发性。若缺乏统一的调度框架,多个推理任务或来自不同应用的计算请求将直接竞争硬件资源,导致优先级翻转、内存带宽争抢、推理延迟抖动甚至硬件死锁。NPU调度框架正是为了解决这一系列问题而设计的核心软件中间层,它位于应用层与NPU硬件驱动之间,负责将上层计算请求有序、高效、可控地映射到物理执行单元上。本章将系统阐述调度框架的定义、核心功能、常见调度模型及其适用场景,帮助开发者建立从任务提交到硬件执行全链路的调度认知。

NPU调度框架总体架构与调度模型映射 应用层(多租户推理请求) App A: 实时检测 App B: 离线批量 App C: 语音交互 App D: 图像增强 任务提交/同步/异步 NPU调度框架(核心功能模块) 任务分配 • 队列映射 • 硬件引擎绑定 • 内存/带宽分配 • 多NPU负载均衡 优先级管理 • 静态/动态优先级 • 优先级继承/反转 • 抢占/非抢占策略 • 截止时间感知 资源隔离 • 地址空间隔离 • 带宽配额控制 • 故障域隔离 • QoS保障 调度决策(选择队列/模型) 常见调度模型 FIFO(先入先出) 公平、简单、无饥饿 优先级调度 实时优先、可抢占 时间片轮转 公平共享、延迟可控 映射到硬件队列/引擎

3.1 调度框架的定义与设计目标

调度框架(Scheduling Framework)在NPU软件栈中,是指一组协调任务提交、队列管理、资源分配与硬件执行之间关系的软件组件集合。它通常由用户态库(如libnpu)、内核态驱动(Kernel Driver)以及固件中的微调度器(Micro-Scheduler)共同构成。从抽象层次看,调度框架屏蔽了底层硬件寄存器、DMA描述符、中断处理等细节,向上提供统一的推理任务API(如npu_submit_task()、npu_wait_completion()),向下通过命令队列(Command Queue)与硬件交互。

调度框架的设计目标可以归纳为以下四点:

  • 高吞吐与低延迟的平衡:边缘设备往往同时承载多个推理流,调度框架需在批量处理(提升MAC利用率)与快速响应(降低单任务延迟)之间找到平衡点。
  • 确定性(Determinism):对于自动驾驶、工业质检等实时控制场景,任务完成时间必须可预测,调度框架需提供有界延迟保证。
  • 资源利用率最大化:NPU的算力、带宽、片上内存均有限,调度框架需通过任务合并、流水线重叠等手段减少空闲周期。
  • 故障隔离与安全:当某个应用异常(如死循环提交任务)时,调度框架应能限制其影响范围,避免拖垮整个NPU系统。
核心原理:调度框架的本质是一个“多输入单输出”的仲裁器。它将来自不同进程、不同优先级的计算请求,按照既定策略排列成有序的执行序列,并映射到NPU硬件队列(Hardware Queue)上。硬件队列通常有多个(如普通队列、实时队列、DMA专用队列),调度框架负责决定哪个任务进入哪个队列,以及队列之间的切换时机。

3.2 调度框架的核心功能

调度框架的功能可以拆解为三个核心维度:任务分配(Task Allocation)、优先级管理(Priority Management)和资源隔离(Resource Isolation)。三者相互关联,共同决定系统的整体行为。

3.2.1 任务分配

任务分配解决的是“任务去哪里执行”的问题。NPU内部通常包含多个计算引擎(如卷积引擎、池化引擎、激活引擎)和多个内存通道。调度框架需要根据任务类型(卷积密集/内存密集)、输入数据位置(DDR/片上SRAM)以及当前各引擎的负载状态,决定任务的执行路径。具体操作流程包括:

  1. 任务解析:解析上层传入的推理请求,提取模型ID、输入张量地址、输出张量地址、优先级标志等信息。
  2. 队列选择:根据任务属性(实时/普通/批量)选择对应的硬件命令队列。例如,实时任务进入高优先级队列,批量任务进入低优先级队列。
  3. 资源预分配:为任务分配所需的片上缓冲区(如权重缓冲区、激活缓冲区)和DMA通道带宽。
  4. 命令描述符填充:将任务参数封装为硬件可识别的命令描述符(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
实战经验:在瑞芯微RK3588的NPU调度框架中,任务分配通过“多通道描述符列表”实现,每个通道对应一个硬件队列。开发者可以通过设置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),但执行时间短;超分任务执行时间长且无实时要求。因此需要引入优先级调度。

实际操作步骤:

  1. 将NPU硬件队列拆分为3个:高优先级队列(Q0)、中优先级队列(Q1)、低优先级队列(Q2)。
  2. 配置调度策略:Q0采用优先级抢占模型,Q1和Q2采用加权时间片轮转(权重比2:1)。
  3. 将DMS任务绑定到Q0,手势识别绑定到Q1,超分和视频编码绑定到Q2。
  4. 设置Q0的抢占安全点:在DMA传输完成且MAC阵列空闲时允许抢占,避免中断正在执行的卷积计算。
  5. 为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。
总结:NPU调度框架是连接应用与硬件的“交通警察”,其核心价值在于通过合理的任务分配、优先级管理和资源隔离,在有限的硬件资源上实现确定性的服务质量。FIFO、优先级、时间片轮转三种基础模型各有优劣,实际系统通常采用混合调度策略——例如,用优先级模型保证实时任务,用时间片轮转模型保证多路视频流的公平性,用FIFO模型处理后台批量任务。理解这些模型的适用边界,是设计高效Edge AI系统的关键一步。