16、多路Camera调度与QoS:CPU/GPU/DSP资源分配、优先级管理、带宽保障
各位做车载Camera的朋友,咱们今天聊一个很实际的问题——多路Camera的调度。
你想想看,现在的智能汽车,少说也有4-6个摄像头。环视、DMS、OMS、ADAS感知……这些摄像头同时工作,CPU、GPU、DSP、ISP全都在抢资源。怎么保证每个摄像头都能拿到它需要的算力和带宽?这就是QoS要解决的问题。
我个人习惯把这个问题拆成三个层面来看:资源分配、优先级管理、带宽保障。咱们一个一个说。
16.1 资源分配:谁该拿多少算力?
先说CPU。多路Camera进来,每一路都要做预处理、格式转换、算法推理。CPU资源是有限的,你不能让一路Camera把CPU吃满,其他路饿死。
我在项目中遇到过这样一个坑:某款车型的环视系统,4路摄像头同时工作,结果有一路因为CPU被抢走,帧率从30fps掉到了12fps。后来一查,是某个算法模块没有做CPU亲和性绑定,导致它被调度到了同一个核心上。
解决方案其实不复杂:
- CPU亲和性绑定:把关键线程绑定到特定核心上,避免被其他线程干扰。
- CPU使用率上限:给每个Camera pipeline设置CPU使用率上限,比如不超过30%。
- GPU/DSP负载均衡:能丢给DSP做的,就别让CPU做。比如图像预处理、色彩校正这些,DSP效率高得多。
关键点:资源分配不是简单的“平均分”,而是“按需分”。比如ADAS摄像头需要高帧率、低延迟,那它就应该拿到更多的CPU和GPU资源。而环视摄像头对延迟要求没那么高,可以适当降低优先级。
16.2 优先级管理:谁先谁后?
优先级管理说白了就是:当资源不够时,谁先上,谁等着。
我记得有一次调试DMS摄像头,发现它总是丢帧。后来一查,是因为它和ADAS摄像头共享同一个ISP pipeline,而ADAS的优先级更高,导致DMS的帧被丢弃了。
这里我建议的做法是:
- 定义Camera优先级等级:比如ADAS > DMS > 环视 > 娱乐摄像头。
- 使用实时线程:高优先级的Camera pipeline使用SCHED_FIFO或SCHED_RR调度策略。
- 优先级继承:当低优先级线程持有高优先级线程需要的锁时,临时提升它的优先级,避免优先级反转。
小技巧:我曾经在项目中用了一个“优先级门限”机制——当CPU使用率超过80%时,自动降低非关键Camera的优先级。这样既保证了关键功能,又不会让系统崩溃。
16.3 带宽保障:数据通路不能堵
带宽问题,说白了就是数据能不能及时从摄像头传到处理器。这里涉及三个环节:
- MIPI CSI带宽:每个摄像头占用的MIPI lane数量和速率。
- 内存带宽:多路Camera同时写入DDR,会不会造成带宽瓶颈?
- ISP带宽:ISP的处理能力能不能跟上所有Camera的帧率?
我遇到过最头疼的问题,就是内存带宽被打满。4路1080p@30fps的Camera同时写入DDR,再加上GPU在做渲染,结果内存带宽直接爆了。系统卡顿,Camera掉帧,甚至出现画面撕裂。
解决方案:
- 使用ION内存分配器:为Camera分配专用的物理连续内存,避免碎片化。
- 设置内存带宽上限:通过DMA-BUF的QoS接口,限制每路Camera的内存带宽使用量。
- 使用硬件压缩:比如NV12转NV21时,用硬件压缩减少带宽占用。
注意:带宽问题不是简单的“加带宽”就能解决的。有时候是总线仲裁策略的问题,有时候是内存控制器配置的问题。我曾经花了两周时间,最后发现是DDR的page policy配置不对,导致多路写入时冲突严重。
16.4 整体调度框架
说了这么多,咱们来看一个实际的调度框架图。这个图是我在某个项目中用过的,效果还不错。
这个框架的核心思路是:先分配,再调度,最后监控反馈。每一路Camera进来,QoS调度器根据它的优先级和资源需求,分配CPU核心、GPU/DSP时间片、内存带宽。然后通过监控模块实时反馈,动态调整参数。
16.5 代码示例:QoS配置
最后,给一段实际代码。这是我在Android HAL层配置Camera QoS的片段:
// Camera QoS配置结构体
typedef struct {
int32_t camera_id;
int32_t priority; // 0-255, 越高越优先
int32_t cpu_affinity; // CPU亲和性掩码
int32_t cpu_usage_max; // CPU使用率上限(%)
int32_t gpu_time_slice; // GPU时间片(ms)
int32_t mem_bandwidth_max; // 内存带宽上限(MB/s)
int32_t mipi_lane_count; // MIPI lane数量
int32_t mipi_freq; // MIPI频率(MHz)
} camera_qos_config_t;
// 配置ADAS摄像头
camera_qos_config_t adas_qos = {
.camera_id = 0,
.priority = 200,
.cpu_affinity = 0x0F, // 绑定到核心0-3
.cpu_usage_max = 40,
.gpu_time_slice = 10,
.mem_bandwidth_max = 800,
.mipi_lane_count = 4,
.mipi_freq = 1200
};
// 配置环视摄像头
camera_qos_config_t surround_qos = {
.camera_id = 1,
.priority = 100,
.cpu_affinity = 0xF0, // 绑定到核心4-7
.cpu_usage_max = 20,
.gpu_time_slice = 5,
.mem_bandwidth_max = 400,
.mipi_lane_count = 2,
.mipi_freq = 800
};
// 应用QoS配置
int ret = camera_qos_apply(&adas_qos);
if (ret != 0) {
// 处理失败
}
避坑指南:我曾经在配置CPU亲和性时,把ADAS和DMS绑定到了同一个核心上。结果两个高优先级线程互相抢资源,导致系统响应变慢。后来我改成每个关键Camera独占一个核心,问题就解决了。
嗯,关于多路Camera调度与QoS,今天就聊这么多。核心就三句话:资源要按需分配,优先级要明确,带宽要保障。你想想看,如果这三条都做到了,多路Camera系统基本上就不会出大问题。
公众号:蓝海资料掘金营,微信deep3321