结论
S100P 的 BPU 同一时间只能调度 1 个模型实例进行推理,无法真正实现多模型并发。
核心限制
1. 硬件架构
- S100P 的 BPU 是单一物理加速器,不支持硬件级虚拟化或多实例隔离
- 社区确认:
CONFIG_VFIO is not set,无法通过 VFIO 实现 BPU 透传(参考 BPU 虚拟化讨论) - 与 X3 的双核 BPU 不同,S100P 的 BPU 设计为独占式资源
2. 调度机制
- BPU 驱动采用排队调度:当多个进程/线程同时请求 BPU 时,驱动会串行化处理
- 即使你启动多个
hrt_model_exec进程,实际也是交替执行,而非并行 - 参考 压力测试案例:多进程测试时 BPU 利用率仍为单实例水平
3. 内存带宽瓶颈
- BPU 推理需要独占 DDR 带宽,多模型并发会导致:
- IOMMU MAP 失败(参考 Qwen2.5 报错)
- 内存争抢,推理延迟激增
调度策略与最佳实践
虽然无法真正并发,但可以通过以下方式优化多模型切换效率:
方案 1:时间分片调度(推荐)
# 伪代码:手动时间分片
import threading
import time
class BPUScheduler:
def __init__(self):
self.current_model = None
self.lock = threading.Lock()
def run_model(self, model_name, input_data):
with self.lock:
# 加载模型(如果未加载)
if self.current_model != model_name:
self.load_model(model_name)
self.current_model = model_name
# 执行推理
result = self.infer(input_data)
return result
# 使用示例
scheduler = BPUScheduler()
result1 = scheduler.run_model("yolo", frame1)
result2 = scheduler.run_model("resnet", frame2)
效果:
- 总帧率 ≈ 单模型帧率 / 模型数量
- 延迟可控,无资源冲突
方案 2:模型融合(高级)
将多个模型合并为单一多任务模型:
- 共享 Backbone(如 ResNet)
- 多输出头(检测 + 分类)
- 一次 BPU 推理完成所有任务
优点:真正的"并发",BPU 利用率最高
缺点:需重新训练/转换模型
方案 3:CPU+BPU 混合部署
# BPU 运行 YOLOv2(重模型)
hrt_model_exec --model yolo.hbm &
# CPU 运行 ResNet18(轻模型)
python3 resnet_cpu_infer.py &
适用场景:一个模型较重(YOLO),一个较轻(分类)
监控与验证
# 1. 查看 BPU 状态
hrut_somstatus
# 2. 测试多进程调度(预期串行)
hrt_model_exec --model model1.hbm --loop 1000 &
hrt_model_exec --model model2.hbm --loop 1000 &
# 3. 观察 BPU 利用率
watch -n 1 "hrut_somstatus | grep ratio"
预期结果:ratio 不会超过单实例的最大值,说明是串行调度。
总结对比
| 调度方式 | 最大模型数 | 真正并发 | 实现难度 | 推荐度 |
|---|---|---|---|---|
| 时间分片 | N 个(交替) | |||
| 模型融合 | 1 个(多任务) | |||
| CPU+BPU 混合 | 2 个(异构) | |||
| 多进程并发 | N 个(排队) |
建议
- 优先使用时间分片:实现简单,稳定性高
- 如需真正并发:考虑模型融合或 CPU 卸载
- 避免多进程硬抢 BPU:可能导致 IOMMU 报错或系统不稳定
下一步:如果你的应用场景对延迟敏感,建议提供具体需求(帧率、模型类型),我可以帮你设计最优调度方案。