延迟的构成:传输延迟、处理延迟、排队延迟、调度延迟

聊到 Batch 大小,咱们得先搞清楚一个核心问题:延迟到底从哪来的?

很多人一上来就调 Batch size,调了半天效果不好,其实是因为根本没弄明白延迟的构成。我见过不少团队,把网络延迟当成了处理延迟去优化,结果白忙活一场。

延迟这东西,说白了就四个部分:传输延迟、处理延迟、排队延迟、调度延迟。咱们一个一个拆开看。

1. 传输延迟:数据在路上花的时间

传输延迟,就是数据从 A 点跑到 B 点的时间。你想想看,数据在网线、光纤、无线信号里跑,总得花时间吧?

这个时间取决于两个因素:距离和带宽。

  • 距离:光速虽然快,但物理距离摆在那。北京到纽约,来回怎么也得 130 毫秒。这个你改不了。
  • 带宽:带宽越大,单位时间能塞的数据越多。但注意,带宽只影响「吞吐量」,不影响「单次传输的延迟」。

关键点:传输延迟是物理限制,你没法通过调 Batch size 来优化它。但你可以通过数据本地化来减少它——把计算放到数据所在的地方。

我在项目中遇到过一件事:有个团队把训练数据放在美国,计算节点放在欧洲,结果每次拉数据都要等 200 多毫秒。后来把数据迁移到本地,延迟直接降到 2 毫秒。嗯,有时候问题就这么简单。

2. 处理延迟:真正干活的时间

处理延迟,就是 CPU 或 GPU 真正在计算的那段时间。这个跟 Batch size 关系最大。

举个例子:

# 小 Batch:处理延迟低,但吞吐量也低
batch_size = 1
# 处理时间:2ms

# 大 Batch:处理延迟高,但吞吐量高
batch_size = 64
# 处理时间:20ms

为什么会这样?因为硬件有并行能力。GPU 一次处理 64 个样本,跟处理 1 个样本相比,时间并不是线性增长的。说白了,大 Batch 能更好地利用硬件资源。

但这里有个坑:处理延迟不是无限降低的。当 Batch 大到一定程度,硬件资源饱和了,再增大 Batch 只会增加延迟,吞吐量却不再提升。

我的习惯:先跑一个小实验,看看你的硬件在哪个 Batch size 下达到「拐点」。这个拐点就是处理延迟和吞吐量的最佳平衡点。

3. 排队延迟:等着被服务的时间

排队延迟,就是数据到了,但没被立即处理,得排队等着。

你想想看,一个系统同时处理多个请求,总得有个先来后到吧?排队延迟就是数据在队列里等待的时间。

排队延迟跟两个因素有关:

  • 队列长度:队列越长,等待时间越久
  • 服务速率:处理得越快,队列清空得越快

Batch size 会影响排队延迟吗?当然会。大 Batch 意味着每个请求的处理时间更长,后面的请求就得等更久。这就是为什么有时候你调大 Batch,单个请求的延迟反而飙升。

我曾经踩过的坑:在一个实时推理系统里,我把 Batch size 从 1 调到了 32,想着提高吞吐量。结果呢?单个请求的延迟从 5ms 涨到了 120ms。因为排队延迟爆炸了。后来我用了动态 Batch 策略,才把问题解决。

4. 调度延迟:系统在「安排」上花的时间

调度延迟,是操作系统或框架在分配资源、切换上下文时花的时间。这个最容易被忽略。

举个例子:

# 调度延迟的典型场景
- 线程切换:每次切换约 10-100μs
- GPU kernel 启动:每次约 5-50μs
- 数据拷贝:从 CPU 到 GPU,每次约 100μs-1ms

Batch size 越小,调度次数越多。你想想看,如果 Batch size = 1,每处理一个样本就要调度一次,调度延迟占比就很高。如果 Batch size = 64,调度次数减少到 1/64,调度延迟自然就摊薄了。

但这里有个度。调度延迟虽然被摊薄了,但处理延迟却增加了。所以还是那个问题:找到平衡点。

一张图看懂延迟构成

下面这张图,是我自己总结的延迟构成框架。你看完应该能明白,调 Batch size 到底在调什么。

延迟构成四要素 传输延迟 数据在路上跑的时间 距离 + 带宽 Batch 影响:低 处理延迟 真正干活的时间 计算量 + 硬件能力 Batch 影响:高 排队延迟 等着被服务的时间 队列长度 + 服务速率 Batch 影响:中 调度延迟 系统安排的时间 线程切换 + 启动开销 Batch 影响:中 Batch 大小对延迟的影响总结 • 小 Batch:处理延迟低,但调度延迟占比高,吞吐量低 • 大 Batch:处理延迟高,但调度延迟被摊薄,吞吐量高 • 关键:找到「拐点」——硬件饱和前的最佳 Batch size • 注意:排队延迟会随 Batch 增大而增加,实时系统要小心

四种延迟的关系

这四种延迟不是孤立的,它们互相影响。我举个例子你就明白了:

假设你有一个推理服务,Batch size 从 1 调到 64:

  • 传输延迟:不变,因为数据量没变
  • 处理延迟:从 2ms 涨到 15ms,因为要处理更多数据
  • 排队延迟:从 1ms 涨到 50ms,因为每个请求占用的时间变长了
  • 调度延迟:从 0.5ms 降到 0.01ms,因为调度次数减少了

你看,总延迟从 3.5ms 涨到了 65ms。虽然吞吐量上去了,但单个请求的延迟却恶化了。这就是为什么我说:Batch 大小是一把双刃剑。

我的建议:在做 Batch 调优之前,先搞清楚你的系统是延迟敏感型还是吞吐量敏感型。

  • 延迟敏感型(如在线推理):用小 Batch,甚至 Batch=1
  • 吞吐量敏感型(如离线训练):用大 Batch,尽量压满硬件

小结

延迟的四个构成部分,说白了就是:

  1. 传输延迟:数据在路上跑的时间,跟 Batch 关系不大
  2. 处理延迟:真正干活的时间,Batch 越大,处理延迟越高
  3. 排队延迟:等着被服务的时间,Batch 越大,排队越久
  4. 调度延迟:系统安排的时间,Batch 越大,调度开销越小

理解了这些,你就能明白:调 Batch size 不是在调一个参数,而是在平衡四种延迟。没有完美的 Batch size,只有最适合你场景的 Batch size。

嗯,下一节咱们聊聊怎么测量这些延迟,以及如何用工具找到那个「黄金 Batch size」。

可可精品资料库