RK3588与边缘计算 RK3588 边缘 AI 视觉系统架构实战

多模型多实例推理:单块 RK3588 NPU 如何同时跑人员入侵、烟火检测、垃圾分类

分享到微博

上一篇我们分享了零拷贝跨进程通信,让边缘服务和推理引擎之间的图像传输延迟降到 1ms 以内。这一篇我们深入到推理引擎——推理引擎拿到图像帧之后,怎么高效地跑多个模型?RK3588 的 NPU 有 6TOPS 算力,但如果只用单线程单实例推理,NPU 利用率可能只有 30-40%,大量算力被浪费。本文分享我们的多模型、多实例推理架构,以及如何把 NPU 利用率从 40% 提升到 85%。


一、背景:边缘 AI 的多模型需求

做工业 AI 视觉,很少有客户只需要一个算法。真实场景里,一块边缘设备往往要同时跑多个算法模型。

举几个典型场景:

场景一:工厂周界防范

  • 人员入侵检测(实时,10fps)
  • 违章停放检测(工作时间,5fps)
  • 烟火检测(定时,每 30 分钟一帧)
  • 摄像头遮挡检测(定时,每 2 小时一帧)

场景二:智能垃圾分类

  • 可回收物识别(实时)
  • 有害垃圾识别(实时)
  • 厨余垃圾识别(实时)
  • 其他垃圾识别(实时)

场景三:工业质检

  • 表面缺陷检测(实时)
  • 尺寸测量(实时)
  • 字符识别(OCR,按需)
  • 颜色分类(实时)

这些场景有一个共同点:需要多个算法模型同时运行,而且每个模型的特性不同——有的需要高帧率实时推理,有的只需要低频抽帧,有的模型大、有的模型小。

怎么在一块 RK3588 上高效地跑这么多模型?这就是我们要解决的问题。


二、踩坑实录:单实例推理的 NPU 利用率困境

刚开始做推理引擎的时候,我们的方案很简单:每个模型加载一个 RKNN Context,单线程串行推理。

跑起来之后发现性能很差——NPU 利用率只有 30-40%,大量算力被浪费。

为什么单实例推理 NPU 利用率低?

RK3588 的 NPU 是一个专用的张量处理器,它的工作方式和 CPU 不同。理解 NPU 利用率低的原因,要先理解推理的流水线:

```

前处理(CPU) → NPU 推理(NPU) → 后处理(CPU)

```

单线程串行推理时,这个流水线是这样跑的:

```

时间线 →

[CPU前处理][NPU推理][CPU后处理][CPU前处理][NPU推理][CPU后处理]...

↑ NPU工作 ↑ NPU空闲 ↑ NPU工作

```

看到问题了吗?NPU 在 CPU 做前处理和后处理的时候是空闲的。 而且 NPU 推理本身也不是 100% 占满——数据从内存搬运到 NPU、NPU 内部的流水线填充、结果从 NPU 搬回内存,这些环节 NPU 都可能在等待。

实测下来,单实例推理时:

  • NPU 实际工作时间占比:30-40%
  • NPU 等待时间占比:60-70%(等 CPU 前处理/后处理、等数据搬运)

6TOPS 的 NPU,实际只用了 2TOPS 左右,剩下的 4TOPS 全浪费了。

单实例推理的其他问题

除了 NPU 利用率低,单实例推理还有几个问题:

  1. 多模型串行,延迟叠加——如果有 3 个模型要跑,单线程串行就是模型1推理完再跑模型2,模型2完了再跑模型3,总延迟是三个模型延迟之和。对于实时任务来说,延迟太高。
  1. 无法按任务优先级调度——高优先级的任务(如人员入侵)和低优先级的任务(如定时遮挡检测)挤在同一个线程里,低优先级任务可能阻塞高优先级任务。
  1. 模型切换开销——如果多个任务共用一个模型但输入尺寸不同,每次切换都要重新配置 RKNN Context,有额外开销。

单实例推理在 demo 阶段够用,但到了生产环境、多模型多任务场景,性能和灵活性都不够。


三、RK3588 NPU 的硬件能力

在讲我们的方案之前,先了解一下 RK3588 NPU 的硬件能力,因为方案设计是基于硬件特性的。

三核 NPU 架构

RK3588 的 NPU 不是一个单核,而是三个独立的 NPU Core(CORE0、CORE1、CORE2),每个 Core 算力 2TOPS,总计 6TOPS。

三个 Core 之间有高速互联,可以:

  • 单独使用:每个 Core 跑一个独立的推理任务
  • 联合使用:一个大模型自动拆分到多个 Core 并行计算(模型分片)
  • 混合使用:有的 Core 单独跑小模型,有的 Core 联合跑大模型

这个三核架构是 RK3588 NPU 的关键优势——它天然支持多模型并行推理。

RKNN Context 机制

RKNN(Rockchip Neural Network)是瑞芯微的推理框架。每个加载的模型对应一个 RKNN Context,Context 里包含了模型权重、计算图、内存分配等信息。

关键特性:

  • 多 Context 并发:可以同时初始化多个 RKNN Context(不同模型或同一模型的多个实例),多线程并发调用
  • Core 绑定:每个 Context 可以绑定到特定的 NPU Core(或多个 Core),通过 core_mask 配置
  • 异步推理:支持异步推理接口,提交推理任务后不阻塞,等结果就绪后再获取
  • 内存共享:多个 Context 可以共享输入输出内存,减少内存占用

理解了三核架构和 RKNN Context 机制,我们的多模型推理方案就有了硬件基础。


四、我们的方案:三层推理架构 [Yuewell Inside]

我们把推理引擎的架构分成三层:模型层、算法层、实例层

```

┌─────────────────────────────────────────────────────┐

│ 实例层(Instance Layer) │

│ 越微自研多实例并发推理引擎,多线程池,NPU 负载均衡 │

├─────────────────────────────────────────────────────┤

│ 算法层(Algo Layer) │

│ 单模型多算法映射,同一模型的不同 class_id 路由到 │

│ 不同业务任务(人员入侵、违章停放、烟火检测...) │

├─────────────────────────────────────────────────────┤

│ 模型层(Model Layer) │

│ 多个模型文件加载(通用检测、人脸专模、安防专模...) │

└─────────────────────────────────────────────────────┘

```

第一层:模型层——多模型并行加载

模型层负责加载和管理多个模型文件。

我们支持同时加载多个模型:

  • 通用检测模型:YOLOv5/v8,检测人、车、动物等通用目标
  • 烟火检测专模:专门训练的烟雾/火焰检测模型,准确率更高
  • 人脸识别模型:人脸检测 + 特征提取
  • 工业缺陷检测模型:针对特定产品的缺陷检测
  • OCR 模型:文字识别

每个模型加载为一个独立的 RKNN Context,绑定到合适的 NPU Core。模型的加载、卸载、切换由模型层统一管理。

模型层的设计要点:

  • 模型按需加载——不需要的模型不加载,节省内存
  • 模型热切换——运行中可以加载新模型、卸载旧模型,不需要重启服务
  • 模型版本管理——支持模型的版本回滚和 A/B 测试

第二层:算法层——单模型多算法映射 [Yuewell Inside]

这是我们方案中最有特色的一层。很多时候,不同的业务任务其实可以用同一个模型,只是关注的类别不同。

举个例子:通用 YOLO 模型可以检测 80 种物体,其中:

  • class_id = 0(人)→ 对应「人员入侵」任务
  • class_id = 2(汽车)→ 对应「违章停放」任务
  • class_id = 5(公交车)→ 也对应「违章停放」任务
  • class_id = 7(卡车)→ 也对应「违章停放」任务

如果为每个任务都跑一次模型推理,那同一路视频就要跑 2-3 次推理,浪费 NPU 算力。

我们的做法是:模型只推理一次,后处理阶段根据任务 ID 和算法类型,把检测结果分流路由到不同的业务任务。

```

一路视频帧 → 通用 YOLO 模型推理一次 → 输出所有检测结果

┌─────────────┼─────────────┐

↓ ↓ ↓

人员入侵任务 违章停放任务 其他任务

(只取 class=0) (只取 class=2,5,7)

```

单模型多算法映射的好处:

  • 节省 NPU 算力——同一路视频只推理一次,就能支撑多个业务任务,NPU 算力节省 50-70%
  • 降低延迟——不需要为每个任务分别推理,总延迟就是一次推理的延迟
  • 减少内存占用——不需要为每个任务加载独立的模型,一个通用模型就够了
  • 灵活配置——任务和 class_id 的映射关系由配置维护,新增任务不需要改代码、不需要重新加载模型,只需要改配置

注意:不是所有任务都能共用模型。 如果某个任务需要专用模型(如烟火检测、工业缺陷检测),还是要加载独立模型。单模型多算法映射适用于「同一模型能覆盖多个任务」的场景,这在通用目标检测中很常见。

第三层:实例层——单模型多实例并发 [Yuewell Inside]

模型层和算法层解决了「多模型」和「多算法」的问题,实例层解决的是「NPU 利用率」的问题。

核心思路:对高频核心模型,初始化多个 RKNN Context 实例,用越微自研多实例并发推理引擎,多线程池并发推理,把 NPU 喂饱。

```

┌── RKNN Context 1(CORE0)── 线程1

视频帧队列 ────────┼── RKNN Context 2(CORE1)── 线程2

└── RKNN Context 3(CORE2)── 线程3

```

每个 RKNN Context 实例绑定到一个独立的 NPU Core,运行在独立的线程里。视频帧队列里的帧,按轮询(Round-Robin)或负载均衡策略分发给不同的实例线程推理。

这样做的效果:

  • NPU 三核并行——三个 Core 同时推理,算力从 2TOPS 提升到 6TOPS
  • 流水线填满——一个实例在做 CPU 前处理/后处理时,其他实例在做 NPU 推理,NPU 不会空闲
  • 吞吐量提升——单实例 25fps,三实例并发就能到 60-75fps(实际受内存带宽和前处理限制,不会线性增长,但提升显著)

实例数的选择:

  • 不是实例越多越好——实例太多会导致内存占用增大、线程切换开销增大、NPU 调度开销增大
  • 我们的经验是:每个 NPU Core 对应 1-2 个实例,RK3588 三核就是 3-6 个实例
  • 具体数量要根据模型大小、推理延迟、内存占用做压测,找到最优值

实例层的其他设计:

  • 越微自研线程池管理——实例线程由线程池统一管理,支持动态调整线程数
  • 负载均衡——根据每个实例的推理耗时和队列长度,动态分配帧,避免某个实例过载
  • 健康检查——监控每个实例的推理状态,如果某个实例卡死或报错,自动重启该实例
  • 结果排序——多实例并发推理可能导致结果乱序(帧2比帧1先返回),我们用帧序号做排序,保证结果按帧顺序输出

五、多模型推理的内存和算力管理

多模型多实例推理,性能上去了,但也带来了新的挑战——内存管理和算力管理

内存管理

每个 RKNN Context 都要占用内存(模型权重、中间张量、输入输出缓冲区)。多模型多实例下,内存占用会显著增加。

我们的内存管理策略:

  1. 模型按需加载——不需要的模型不加载,需要时才加载,用完可以卸载
  2. 实例数动态调整——根据当前任务量动态调整实例数,任务少的时候减少实例释放内存,任务多的时候增加实例
  3. 输入输出缓冲区池化——预分配一组输入输出缓冲区,推理时从池里取,用完归还,避免频繁分配释放
  4. 内存上限监控——设置内存使用上限,超过上限时拒绝加载新模型或减少实例,防止 OOM

RK3588 通常配 4GB 或 8GB 内存,我们的经验是:8GB 内存可以同时加载 3-5 个中等大小的模型 + 每个模型 2-3 个实例,4GB 内存要更谨慎,模型和实例数都要减少。

算力管理

NPU 总算力是固定的(6TOPS),多模型多实例共享这块算力。怎么分配算力?

我们的策略:

  1. 按任务优先级分配——高优先级任务(实时入侵检测)优先分配 NPU 资源,低优先级任务(定时检测)在高优先级任务不忙的时候用空闲算力
  2. Core 绑定——把高优先级模型绑定到独立的 Core,避免和低优先级模型抢算力
  3. 限流机制——如果总推理请求超过 NPU 承载能力,按优先级限流,先保证高优先级任务,低优先级任务排队或跳帧
  4. 负载指标反馈——推理引擎定期向核心服务反馈 NPU 利用率、队列长度、推理延迟等指标,核心服务根据这些指标调整任务调度(如降低采样频率、暂停低优先级任务)

算力管理的核心原则是:保证关键任务,用好空闲算力,绝不超载崩溃。


六、实战案例:某工厂场景的推理优化

我们在一个客户现场做了推理优化前后的对比。这个场景有 8 路摄像头,每路需要同时跑:

  • 人员入侵检测(实时,10fps)——通用检测模型
  • 违章停放检测(工作时间,5fps)——通用检测模型(和人员入侵共用)
  • 烟火检测(定时,每 30 分钟一帧)——烟火专模
  • 摄像头遮挡检测(定时,每 2 小时一帧)——轻量模型

优化前:单实例推理

  • 通用检测模型:1 个 RKNN Context,单线程,NPU 利用率 35%,推理延迟 40ms/帧
  • 烟火专模:1 个 RKNN Context,单线程
  • 遮挡检测:1 个 RKNN Context,单线程
  • 人员入侵和违章停放分别推理(没有做单模型多算法映射),同一路视频跑两次通用检测
  • 8 路 × 10fps × 2次推理 = 160 次推理/秒,单实例根本扛不住,大量丢帧
  • 实际有效帧率:人员入侵 4-5fps(丢了一半),违章停放 2-3fps
  • NPU 总利用率:40%

优化后:三层推理架构

  • 模型层:通用检测、烟火专模、遮挡检测,三个模型按需加载
  • 算法层:人员入侵和违章停放共用通用检测模型,一次推理分流到两个任务,省了一半推理量
  • 实例层:通用检测模型初始化 3 个 RKNN Context(绑定三个 NPU Core),越微自研多实例并发推理引擎
  • 8 路 × 10fps × 1次推理 = 80 次推理/秒,三实例并发轻松扛住
  • 实际有效帧率:人员入侵 10fps(满帧),违章停放 5fps(满帧)
  • NPU 总利用率:82-87%

优化效果:

  • NPU 利用率从 40% 提升到 85%,翻了一倍多
  • 推理吞吐量从扛不住 8 路 10fps,到轻松支持 8 路 10fps + 其他任务
  • 有效帧率从丢帧一半,到满帧运行
  • 因为做了单模型多算法映射,推理量还减少了一半

客户对这个结果很满意。


七、踩坑实录

多模型多实例推理的实现过程中,我们踩了很多坑,分享几个印象深刻的。

坑一:多实例推理结果乱序

三个实例并发推理,帧1分给实例1,帧2分给实例2,帧3分给实例3。但实例2可能比实例1先返回结果(因为模型推理时间有波动),导致结果乱序——帧2的结果比帧1先到。

结果乱序在实时检测中问题不大(每一帧的结果独立),但在事件融合(连续 N 帧确认)中会出问题——如果帧2的结果比帧1先到,融合状态机可能算错连续确认次数。

解决方案:用帧序号(frame_id)做排序。推理引擎返回结果时带上 frame_id,核心服务收到结果后按 frame_id 排序再处理。我们用了一个小的排序缓冲区(存最近几帧的结果),保证按帧顺序输出。

坑二:NPU Core 绑定不当导致负载不均

一开始我们把三个实例都绑定到 CORE0(默认绑定),结果 CORE0 占满 100%,CORE1 和 CORE2 空闲——三核变成了单核。

后来改成每个实例绑定不同的 Core(实例1→CORE0,实例2→CORE1,实例3→CORE2),三个 Core 负载均衡,NPU 利用率才真正上去。

经验:用多实例的时候,一定要检查每个实例的 Core 绑定,确保分散到不同的 Core,不要都挤在一个 Core 上。

坑三:模型量化精度损失

RKNN 推理用 INT8 量化(把 FP32 模型量化成 INT8,提升推理速度、减少内存占用)。但量化可能导致精度损失——有些模型量化后准确率下降明显,特别是小目标检测、细粒度分类。

我们遇到过一个烟火检测模型,FP32 准确率 95%,INT8 量化后降到 82%,误报率大幅上升。

解决方案:

  • 量化时用有代表性的校准数据集(不要用随机数据),提高量化精度
  • 对精度敏感的层(如输出层、小目标检测层)保留 FP16,其他层用 INT8(混合精度量化)
  • 如果量化后精度确实不达标,就用 FP16 推理(比 INT8 慢,但比 FP32 快,精度损失小)
  • 量化后一定要做精度验证,对比量化前后的检测结果,确认精度在可接受范围内

坑四:多模型同时加载导致内存不足

有一次客户要求同时加载 5 个模型(通用检测、烟火、人脸、缺陷、OCR),每个模型又开了 2-3 个实例,结果内存占用超过 8GB,系统 OOM 崩溃。

解决方案:

  • 实现模型按需加载——不需要的模型不加载,需要时才加载
  • 实例数根据内存情况动态调整——内存紧张时减少实例数
  • 设置内存上限——超过上限时拒绝加载新模型,给出明确提示
  • 建议客户根据实际需求选择模型——不需要的模型不要加载,「模型多」不等于「效果好」

⚠️ 工程坑点与技术壁垒警告

提示:多模型多实例推理的思想不难理解,但工程落地中有几个高壁垒问题:
多实例并发的 NPU 调度死锁:多 RKNN Context 多线程并发调用 NPU,如果调度机制做得不好,在高负载下极易出现 NPU 级别的死锁——所有实例都在等 NPU 资源,但 NPU 被某个实例独占不释放,导致整链卡死且 CPU 层面无法感知。越微自研多实例并发推理引擎做了精细的 NPU 资源调度和死锁检测恢复机制,经过大量压测才确保稳定。
量化精度与推理速度的平衡:INT8 量化能显著提升速度,但精度损失是工程化中的大难题。不是所有模型都适合 INT8,有些模型需要混合精度(部分层 INT8、部分层 FP16),有些模型只能用 FP16。怎么在精度和速度之间找到平衡点,需要大量的实验和调优,不是「一键量化」就能搞定的。
这些细节不是看 RKNN 文档就能搞定的,需要在真实设备上反复调试、压测、验证。越微团队在这上面投入了大量时间,才打磨出稳定的多模型多实例推理引擎。


八、几点经验总结

回头看多模型多实例推理的设计和落地过程,总结几点:

1. 单实例推理是 NPU 利用率的最大敌人

很多人做边缘 AI,把模型跑起来就完事了,不关注 NPU 利用率。实际上单实例推理的 NPU 利用率往往只有 30-40%,大量算力被浪费。多实例并发是提升 NPU 利用率最直接有效的方法——RK3588 三核 NPU,每个 Core 跑一个实例,利用率就能从 40% 提升到 80%+。

2. 单模型多算法映射是被低估的优化手段

很多人不知道,同一个检测模型可以同时支撑多个业务任务(人员入侵、违章停放等),只需要在后处理阶段按 class_id 分流。这个优化不需要额外硬件、不需要额外模型,就能把推理量减少 50-70%。做通用目标检测的场景,一定要想想能不能做单模型多算法映射。

3. 三核 NPU 架构是 RK3588 的关键优势,要用好

RK3588 的 NPU 是三核独立架构,这是它比很多竞品强的地方。但很多人不知道 Core 绑定,把所有实例都绑在默认 Core 上,三核变单核。一定要理解三核架构,合理分配 Core,把三个 Core 都用起来。

4. 多模型推理的瓶颈往往不是算力,而是内存

6TOPS 的 NPU 算力其实很充裕,真正的限制是内存——每个模型、每个实例都要占内存,模型多了、实例多了,内存先不够用。做架构设计时,内存管理和算力管理同等重要。按需加载、动态调整实例数、内存上限监控,这些机制不能少。

5. 量化是双刃剑,速度和精度要平衡

INT8 量化能显著提升推理速度、减少内存占用,但可能导致精度损失。不是所有模型都适合 INT8 量化——精度敏感的场景(如小目标检测、细粒度分类)可能需要 FP16 或混合精度。量化后一定要做精度验证,不能只看速度不看精度。


写在最后

从单实例推理到多模型多实例推理,我们花了不少时间踩坑、调优。最终的结果是:NPU 利用率从 40% 提升到 85%,推理吞吐量翻了一倍多,同一块 RK3588 能支撑更多路视频、更多算法任务。

多模型推理架构的核心,不是「把模型跑起来」,而是「把 NPU 算力用满、把内存用好、把多个任务调度好」。这需要对硬件架构(三核 NPU)、推理框架(RKNN Context)、业务场景(多任务多模型)都有深入的理解。

这些经验都是我们(越微智能)在实际项目中踩坑踩出来的。我们团队一直在做工业 AI 视觉、边缘计算部署、机器人二次开发这些落地工作,边缘 AI 视频分析系统是我们的核心产品之一。下一篇是事件融合与证据链,我们会继续分享实战经验。

如果你也在做边缘 AI 推理、RKNN 优化、多模型部署相关的工作,欢迎交流,我们一起踩坑、一起进步。


关于作者与团队:
越微智能(Yuewell)是一支专注具身智能与工业 AI 视觉落地的技术团队,提供工业级视觉算法定制(30+ 算法)、RK3588 边缘一体机、具身机器人调度管理平台、全品牌机器人二次开发(适配宇树/优必选/智元/傅利叶等)、ROS2 系统开发等产品和服务,支持从算法、硬件到产线实机部署的全栈交付。
我们将这套经过大量模型验证与压测的多模型多实例推理引擎,封装为了工业级边缘 AI 视觉基座(Yuewell Edge Framework)的核心模块,支持硬件/算法快速二次开发,帮助客户跳过最痛苦的推理引擎调优阶段。
📌 获取更多技术白皮书、工业 AI 视觉方案与产品交流,欢迎访问越微智能官网:https://yuewell.com/
下一篇预告: 《事件融合与证据链:从「疑似」到「确认」,我们如何把 AI 视觉误报率降到个位数》,我们将分享 AI 视觉检测的误报痛点、越微自研工业多模态事件去重与时空融合引擎、ROI 区域过滤、实帧证据链(确认时刻真实帧 JPEG 编码,拒绝占位图)、推送冷却机制,以及某园区周界防范从误报率 30% 降到 5% 的实战案例,敬请关注。