# Edge 推理结构优化说明 ## 目标 本次优化只调整 `security-ai-edge` 内部实时推理链路,目标是: - 保持现有功能不变 - 保持与其他项目的现有对接方式不变 - 提升单卡场景下的实时稳定性 - 降低解码线程被 CPU 预处理拖慢的风险 - 在高并发下优先处理最新帧,避免旧帧堆积 本次未修改以下外部行为: - WVP 下发摄像头与 ROI 配置的方式 - Redis / MQTT / HTTP 对接协议 - 告警生成、告警去重、截图回调、心跳上报的外部接口 - TensorRT engine 文件加载方式 ## 改动概览 ### 1. 解耦读帧线程与推理预处理 优化前: - `RTSPStreamReader` 读到帧后,直接通过回调进入 `_process_frame` - `_process_frame` 内部会做 ROI 遍历、裁剪、预处理、入推理队列 - 当 ROI 多、CPU 紧张时,读帧线程容易被预处理阻塞 优化后: - `RTSPStreamReader` 只负责读帧和保存“最新帧” - 新增中心调度线程 `FrameScheduler` - 调度线程从每路流提取最新帧,再统一调用 `_process_frame` 收益: - 解码线程不再承担重 CPU 预处理 - 拉流稳定性更高 - 更符合实时视频系统“最新帧优先”的处理模型 ### 2. 每路流改为“最新帧消费” 优化前: - `get_latest_frame()` 通过清空队列获取最后一帧 - 在高并发下,队列遍历和频繁出队会增加额外开销 优化后: - 流对象内部维护 `_latest_frame` - 调度线程直接消费这份最新帧引用 - 中间帧天然被覆盖,不再积压到后面阶段 收益: - 获取最新帧成本更低 - 更适合实时系统而非离线批处理 ### 3. ROI 预处理结果复用 优化前: - 同一 ROI 下如果绑定多个算法,会重复执行 `preprocess_single` 优化后: - 先筛出启用的 `bind` - 对每个 ROI 只执行一次预处理 - 多个 `bind` 复用同一份裁剪图和缩放信息 收益: - 降低 CPU crop / resize / normalize 开销 - ROI 绑定越多,收益越明显 ### 4. 推理队列增加拥塞保护 优化前: - ROI 任务持续追加到 `_batch_roi_queue` - 在输入高于推理吞吐时,可能出现旧任务堆积 优化后: - 为 `_batch_roi_queue` 增加最大挂起量限制 - 超限时丢弃最旧 ROI 任务 收益: - 控制排队长度 - 避免系统在高压时持续处理过期画面 说明: - 这是实时系统常见策略,目标是“宁可丢旧帧,不处理过期帧” ### 5. TensorRT 设备选择修正 优化前: - `TensorRT` 初始化时固定使用 `cuda.Device(0)` - 即使配置里指定了 `device_id`,实际也不会生效 优化后: - 改为使用 `self.config.device_id` 收益: - 保留现有单卡行为 - 为后续指定 GPU 设备提供正确基础 ## 当前结构 优化后的主链路为: 1. `RTSPStreamReader` 拉流并保存最新帧 2. `FrameScheduler` 周期性轮询所有流 3. `_process_frame` 生成 ROI 推理任务 4. `_batch_roi_queue` 聚合任务并做拥塞保护 5. `InferenceWorker` 做小批量 TensorRT 推理 6. `PostProcessor` + `AlgorithmManager` 输出业务告警 7. `ResultReporter` / `AlarmUploadWorker` 继续负责上报 ## 兼容性说明 本次优化没有改变这些关键约束: - 摄像头仍然按 ROI 配置启动和停用 - 算法处理入口 `_handle_detections` 不变 - 现有告警冷却、ROI 去重、resolve 机制不变 - 现有外部平台无需修改配置或接口 因此它属于“内部调度优化”,而不是“系统集成改造”。 ## 新增运行指标 `get_status()` 新增了以下统计项: - `dropped_frames` - `dropped_roi_tasks` - `inference_batches` - `scheduler_cycles` 这些指标用于判断: - 是否存在旧帧丢弃 - 是否出现 ROI 队列拥塞 - 推理批次是否稳定 - 调度线程是否持续运行 ## 仍可继续优化的方向 本次改造重点是“在当前架构下提升实时性和稳定性”,后续还可以继续做: - 将 OpenCV/FFmpeg CPU 解码切换到 GPU 硬解 - 将调度参数做成配置项,例如最大帧年龄、调度周期、最大挂起 ROI 数 - 为不同摄像头增加优先级调度 - 为高频 ROI 增加更细粒度缓存和复用 - 为推理链路补充阶段耗时统计:调度、预处理、推理、后处理 ## 适用场景 这版结构更适合: - 单卡部署 - 多路 RTSP 并发 - 小 batch 实时推理 - 需要低延迟而非离线全量处理的场景 如果后续要切到 GPU 解码,当前这版调度结构也更容易继续演进,因为“读帧”和“处理帧”已经拆开了。