3、帧率与延迟的关系:吞吐量与延迟的权衡、实时性要求分类
好,咱们接着聊。上一节我们讲了帧率怎么算,缓存怎么管。但有个问题一直绕不开——帧率高了,延迟就一定低吗?
不一定。我当年刚入行时也这么以为,结果被现实狠狠教育了一回。
当时做一个高速检测项目,相机能跑到 120fps,我心想这延迟肯定没问题。结果一测,从图像采集到输出结果,整整花了 80 毫秒。客户说:「你们这系统,看着挺快,实际反应慢半拍。」
嗯,这就是典型的高帧率、高延迟。帧率和延迟,从来不是一回事。
3.1 吞吐量与延迟:一对欢喜冤家
先明确两个概念:
- 吞吐量(Throughput):单位时间内能处理多少帧。比如 30 FPS,就是每秒吞吐 30 帧。
- 延迟(Latency):从图像采集到结果输出,单帧花了多少时间。比如 50 毫秒。
你想想看,吞吐量高,不一定延迟低。为什么?
因为系统可以并行处理。比如流水线架构:
- 第 1 帧在采集
- 第 2 帧在预处理
- 第 3 帧在推理
- 第 4 帧在后处理
这样每帧的处理时间可能是 100 毫秒,但流水线跑起来,每秒照样能出 30 帧。吞吐量上去了,但单帧延迟还是 100 毫秒。
核心结论:高吞吐量 ≠ 低延迟。两者是不同维度的指标,需要分别优化。
我在项目中遇到过一种情况:为了提升吞吐量,把 batch size 从 1 调到 4。结果吞吐量确实翻倍了,但单帧延迟从 20 毫秒飙到了 80 毫秒。为什么?因为要等 4 帧凑齐了才能一起推理。
这就是典型的吞吐量与延迟的权衡。你不可能既要马儿跑,又要马儿不吃草。
3.2 延迟的构成:到底慢在哪?
要优化延迟,得先知道延迟从哪来。我一般把延迟拆成三块:
| 阶段 | 典型耗时 | 说明 |
|---|---|---|
| 采集延迟 | 5-30 ms | 相机曝光、传感器读出、传输到内存 |
| 处理延迟 | 10-200 ms | 预处理、推理、后处理 |
| 输出延迟 | 1-10 ms | 结果编码、网络传输、显示刷新 |
你看,处理延迟往往是最大的大头。尤其是深度学习推理,动不动就几十上百毫秒。
我曾经优化过一个缺陷检测系统,发现推理占了 70% 的时间。换了个轻量级模型,延迟从 120 毫秒降到了 35 毫秒。嗯,效果立竿见影。
我的习惯:拿到一个新系统,先做延迟拆解。用 time.time() 或者 profiling 工具,把每个阶段的耗时打出来。哪里慢,优化哪里。
3.3 实时性要求分类:硬实时 vs 软实时
说到延迟,就绕不开「实时性」这个词。但很多人把它理解错了。
实时性不是说「快」,而是说可预测。系统必须在规定时间内完成处理,不能超时。
我把它分成两类:
硬实时(Hard Real-Time)
超时 = 系统失效。后果很严重。
- 典型场景:自动驾驶紧急制动、工业机器人碰撞检测、医疗手术机器人
- 延迟要求:毫秒级,且必须保证最坏情况下的延迟
- 设计思路:专用硬件(FPGA、ASIC)、实时操作系统(RTOS)、任务优先级抢占
举个例子。自动驾驶的 AEB(自动紧急制动)系统,从摄像头捕捉到障碍物到刹车执行,必须在 100 毫秒内完成。超了?那就撞上了。
注意:硬实时系统不能用「平均延迟」来评估。你得看「最坏情况延迟」。我见过一个项目,平均延迟 30 毫秒,但偶尔会跳到 200 毫秒。这种系统用在硬实时场景,就是定时炸弹。
软实时(Soft Real-Time)
超时 = 体验下降,但系统不会崩溃。
- 典型场景:视频监控、人脸门禁、直播美颜
- 延迟要求:几十到几百毫秒,偶尔超时可以接受
- 设计思路:GPU 加速、流水线并行、丢帧策略
比如视频监控。画面延迟 200 毫秒,人眼基本感觉不到。但要是延迟到 2 秒,那就明显卡顿了。不过系统不会因此崩溃,顶多被用户吐槽。
我做过一个门禁项目,要求人脸识别在 500 毫秒内出结果。一开始用大模型,延迟 800 毫秒。后来换了 MobileNet,降到 150 毫秒。嗯,软实时场景,够用就行,不用追求极致。
3.4 如何在实际项目中做权衡?
好,理论讲完了。咱们聊聊实战。
我一般按这个思路来:
- 先定需求:客户要的是高吞吐,还是低延迟?还是两者都要?
- 再测基线:把当前系统的吞吐量和延迟打出来。用
perf或者自己写计时器。 - 找瓶颈:延迟主要卡在哪?是推理太慢,还是 I/O 阻塞?
- 针对性优化:
- 要提吞吐:加流水线、增大 batch、用异步处理
- 要降延迟:换轻量模型、用 GPU 推理、减少预处理步骤
- 验证效果:改完后重新测,看吞吐和延迟的变化。注意,不要只看平均值,要看 P99 甚至 P999 的延迟。
一个经验:如果吞吐和延迟都要优化,先保延迟,再提吞吐。因为延迟是用户体验的底线,吞吐可以通过加机器来解决。延迟不行,物理定律摆在那。
我曾经接手过一个项目,系统延迟 300 毫秒,吞吐 15 FPS。客户要求延迟降到 100 毫秒以内,吞吐提到 30 FPS。我先把模型从 ResNet-50 换成 MobileNet-V3,延迟降到 80 毫秒。然后加了两级流水线,吞吐提到 35 FPS。嗯,搞定。
说白了,帧率和延迟的关系,就像开车。你可以开得很快(高帧率),但遇到红灯你得停(延迟)。你不能一边飙车一边说「我零延迟」。现实世界,总得有个取舍。
我的建议:设计系统时,先把实时性要求定清楚。是硬实时还是软实时?延迟上限是多少?然后倒推帧率、缓存策略、模型选型。别一上来就追求 120 FPS,结果延迟一塌糊涂。
好,这一节就到这。下一节我们聊聊缓存管理的实战技巧——怎么用环形缓冲区、双缓冲、三缓冲来平衡帧率和延迟。到时候我会拿几个踩过的坑出来说,保证有用。