TT Lab
博客

한국어 English 日本語 中文

开始
博客

博客

33ms 的预算:端到端延迟与吞吐量是不同的指标

状态:草稿 (2026-10-16),部分实测。 阶段耗时是在一台配备单张 8GB 级笔记本 GPU 的服务器上,通过临时 Pod(限制 4 个 CPU 核心)测量的(预热 30 次后的 300 次运行中位数)。手机端的捕获与编码耗时以及网络区间属于 未测量。队列模拟使用的是笔记本 CPU 示例(code/01_latency_queue.py,大约 1 秒左右)。 系列《阅读视觉模型 3:实时运行》第 1 篇。本系列探讨了如何在 阅读视觉模型 1·2中看到的模型在 规定时间内 运行的方法。

目录

1. “实时”的两个数字

乒乓球记分牌应用要做到“实时”,必须同时满足两个条件:

这两者经常被混为一谈,但它们是不同的数字。吞吐量由“最慢的一个阶段”决定,而延迟则是“所有阶段的总和 + 在队列中等待的时间”。30fps 的帧间隔 1000 ÷ 30 = 33.3ms 是吞吐量的预算,而不是延迟的上限。如果重叠执行各个阶段,即使延迟超过 33ms 也能达到 30fps;相反,即使延迟只有 10ms,如果队列堆积,用户看到的也是 1 秒前的结果。

한 프레임의 일생: 지연과 처리량 ① 끝단 지연 = 찍힌 순간부터 화면에 나올 때까지의 합 카메라 잡기 전처리 줄이기 추론 모델 후처리 공 찾기 화면 그리기 단계 시간의 합 + 줄에서 기다린 시간 ② 단계를 겹치면 처리량이 는다 — 한 프레임의 지연은 그대로 전처리 추론 후처리 1 2 3 1 2 3 1 2 3 시간 → 추론이 쉬지 않고 돌면 처리량 = 1 ÷ 추론 시간 ③ 추론이 예산보다 느릴 때 1 2 3 4 5 6 줄 세우기: 1부터 차례로 → 지연이 계속 는다 1 2 3 4 5 6 최신만: 2–5 를 버리고 6 → 지연이 묶인다
图:从相机到屏幕的五个阶段与端到端延迟、通过重叠阶段增加吞吐量但保持单帧延迟不变的流水线、推理拥堵时排队与仅处理最新帧的区别

2. 重叠阶段:吞吐量增加,延迟保持不变

如果按顺序执行 8ms 的预处理和 25ms 的推理,一帧需要 33ms,每秒可处理 30.3 张。如果在另一个线程中提前做好预处理(流水线化),GPU 就可以不间断地只进行推理,从而使每秒处理量达到 40 张。然而,单帧所经历的时间仍然是 8 + 25 = 33ms。

처리량  = 1 ÷ (가장 느린 단계의 시간)
지연    = 단계 시간의 합 + 줄에서 기다린 시간
리틀의 법칙: 처리 중인 프레임 수 = 처리량 × 지연   (40장/초 × 0.033초 = 1.32장)

利特尔法则(排队论的基本公式)也可以反过来使用。如果吞吐量是固定的,但“当前正在处理或等待的帧数”增加,则意味着延迟也相应增加。

3. 拥堵时:排队等待还是直接丢弃

推理时间每次都会略有不同。如果平均为 25ms,通常在预算范围内,但如果平均值超过预算达到 36ms 会发生什么呢?我们模拟了 60 秒的 30fps 相机场景(code/01_latency_queue.out.txt,推理时间呈对数正态分布,数字为说明性质的假设)。

推理平均值 规则 处理 fps 丢弃的帧数 延迟中位数 · p99 60秒后的最后一帧延迟
25ms 排队等待 30.0 0% 24.6 · 44.1ms 21.3ms
25ms 仅最新 30.0 0% 24.6 · 44.1ms 21.3ms
36ms 排队等待 27.9 0% 2,068.7 · 4,465.7ms 4,500.7ms
36ms 仅最新 27.4 8.6% 48.0 · 82.3ms 75.9ms

在预算范围内,这两种规则表现相同。一旦超出预算, 排队等待几乎能维持吞吐量,但延迟会无限累积(1 分钟后屏幕画面会延迟 4.5 秒)。“仅最新”策略则会在处理器空闲的瞬间只抓取最新的一帧,并丢弃积压的旧帧。虽然会丢弃 8.6% 的帧,但延迟得到了控制。在实时视频中,几秒钟前的帧结果毫无用处,因此选择丢弃是正确的。TT Score 的实时工作线程和浏览器也是这样做的(第 8 篇)。

4. 迟到的正确答案等于错误答案:Streaming Perception

Li、Wang 和 Ramanan 的论文《Towards Streaming Perception》(ECCV 2020)将这一理念转化为了一种评估方法。通常的检测准确率(AP)假设世界会等待模型。这篇论文中的 streaming AP 会将时间 t 的标准答案与“在 t 之前 完成计算 的最近一次输出”进行比较。由于延迟产生的输出与已经运动的世界进行对比,分数自然会下降。

检测器(自动驾驶视频 30fps,1920×1200) 单帧 AP
HTC(准确但缓慢),常规评估 700.5ms 38.0
同款模型,streaming 评估 700.5ms 6.2
RetinaNet(最快),0.2倍输入 31–36ms 5.5–6.0
Mask R-CNN,0.5倍输入,GPU 预处理 56.7ms 12.0
+ 调度调整(偶尔休息) 56.7ms 13.0
+ 卡尔曼预测,以 0.75 倍输入重新选择 92.7ms 17.8

(论文表 1·2,2017 年消费级高端 GPU 一张。)这里可以看出三点:

“调度调整”很有意思。如果预计下一帧很快就会到来,它就不会开始处理当前帧并选择等待。因为这总比为了抓着旧帧不放而错过新帧要好。这与第 3 节的“仅最新”理念如出一辙。

5. 我们的实测:寻找球的一帧的生命周期

我们在服务器端按阶段测量了 TT Score 的实时处理路径。我们将实际比赛画面的单帧(将 1920×1080 缩小为相机尺寸 1280×720)循环运行了 300 次。手机端所做的工作(缩放、编码)也在同一服务器 CPU 上进行了模拟。

阶段 运行位置 中位数 p90
1280×720 → 512×288 缩放 手机(用服务器 CPU 模拟) 0.27ms 0.30ms
JPEG 编码(质量 70) 手机(用服务器 CPU 模拟) 0.30ms 0.31ms
(传输:JPEG 中位数 12,252 字节) 互联网 未测量 未测量
JPEG 解码 服务器 CPU 0.31ms 0.32ms
BGR → RGB,0–1 归一化,减去均值与标准差 服务器 CPU 1.35ms 1.38ms
3 帧窗口堆叠 + 传输至 GPU CPU → GPU 1.76ms 1.86ms
球模型推理(FP32,生产模式) GPU 15.17ms 15.19ms
(同款推理使用 FP16) GPU 9.98ms 10.03ms
sigmoid + 将热力图传回 CPU GPU → CPU 0.18ms 0.20ms
寻找球的轮廓 服务器 CPU 0.07ms 0.07ms

在服务器端,处理一帧花费的时间约为 19ms(FP32),其中推理占了 80%。在剩下的部分中,耗时较长的不是解码,而是 归一化(1.35ms)和传输至 GPU(1.76ms) 。如果将 512×288×3 转换为 float32,单张图片大小为 1.77MB,如果是三张窗口帧则每次需要创建并传输 5.3MB。如果直接以 uint8 发送到 GPU并在 GPU 上进行归一化,传输量将减少到四分之一,且归一化也由 GPU 完成。目前尚未进行此项修改,其实际效果尚未测量。

该表格中未包含手机端的相机捕获与实际编码、互联网往返、Web 服务器转发以及屏幕渲染。这部分内容将在第 8 篇中结合实际浏览器的测试端到端数值一并总结。

6. 阅读数字的习惯

7. 局限性

8. 与我们项目的联系

Tt 的小贴士。 如果在球弹跳 4 秒后才大喊“界内!”,那无论多么准确,我都已经开始打下一个球了。迟到的正确答案就是错误答案!

参考文献

登录后即可点赞

评论

还没有评论。

登录后即可发表评论