跳到主要内容

高性能推理服务

本节定位

如果上一节讲的是:

  • 模型能不能在本地跑

这一节讲的就是更现实的一层:

模型能不能在线上稳定扛住请求。

这也是很多项目从 demo 走向生产时,第一次真正撞墙的地方。

学习目标

  • 理解吞吐、延迟、批处理、队列这些推理服务关键词
  • 理解为什么“能跑”不等于“能服务”
  • 看懂一个最小批处理推理服务思路
  • 建立对推理服务优化问题的第一层直觉

一、为什么本地推理和推理服务是两回事?

1.1 本地推理关心的是“出不出结果”

例如:

  • 一条 prompt 能不能答
  • 一张图能不能生成

1.2 推理服务关心的是“同一时间能扛多少请求”

一旦上线,你要面对的是:

  • 多个请求同时到来
  • 流量波峰
  • 资源限制
  • 超时

所以推理服务的核心问题变成:

怎样在资源有限的情况下平衡速度和吞吐。


二、先分清两个最重要的词

2.1 Latency

一次请求要等多久。

2.2 Throughput

单位时间能处理多少请求。

这两个指标往往互相拉扯。

例如:

  • batch 变大,吞吐可能更高
  • 但单请求等待时间可能也会更长

所以推理服务不是“单项越高越好”,而是平衡问题。


三、为什么批处理(batching)会特别重要?

3.1 一个直觉理解

如果 8 个请求几乎同时进来,你可以:

  • 一个个单独跑

也可以:

  • 合成一个 batch 一起跑

后者通常能更高效利用硬件。

3.2 一个最小示意

requests = [12, 8, 15]
batch_size = 8

for r in requests:
num_batches = (r + batch_size - 1) // batch_size
print("needs", num_batches, "batches")

3.3 这段代码在教什么?

它在教你:

推理服务不是按“一个请求”思考,而更像按“队列和批次”思考。


四、为什么队列是高性能服务的基础部件?

4.1 因为请求不会整齐地来

真实流量往往是:

  • 有波峰
  • 有波谷
  • 有突发

如果没有队列,系统很容易:

  • 突然爆掉
  • 请求直接丢失

4.2 一个最小队列示例

from collections import deque

queue = deque(["req1", "req2", "req3", "req4", "req5"])
batch_size = 2

while queue:
batch = []
for _ in range(min(batch_size, len(queue))):
batch.append(queue.popleft())
print("run batch:", batch)

这个例子很简单,但已经说明:

  • 请求先排队
  • 再按批次执行

这就是很多推理服务最基本的行为模式。


五、并发和批处理不是一回事

这是很多初学者最容易混的地方。

5.1 并发

多个请求在系统里同时推进。

5.2 批处理

多个请求在模型层合成一个 batch 一起算。

所以可以记成:

  • 并发是调度层问题
  • 批处理是模型执行层问题

这两个常常一起出现,但并不等价。


六、一个最小推理服务主循环

from collections import deque

queue = deque(["q1", "q2", "q3", "q4"])
batch_size = 2

def run_model(batch):
return [f"answer_for_{item}" for item in batch]

while queue:
batch = []
for _ in range(min(batch_size, len(queue))):
batch.append(queue.popleft())

results = run_model(batch)

for item, result in zip(batch, results):
print(item, "->", result)

6.2 这段代码为什么重要?

因为它已经包含了一个高性能推理服务最关键的骨架:

  • 入队
  • 合批
  • 推理
  • 回传结果

这条链才是“服务”的本体。


七、为什么高性能推理服务永远在做平衡?

你通常会在这些维度之间取舍:

  • batch 大一点,吞吐更高
  • batch 小一点,响应更快
  • 常驻模型更快,但更占资源
  • 更多实例更稳,但更贵

这意味着:

推理服务的优化不是绝对值优化,而是业务约束下的平衡优化。


八、真实服务里最值得盯的指标

至少通常要看:

  • 平均延迟
  • P95 / P99 延迟
  • 队列长度
  • batch 利用率
  • 错误率
  • GPU / CPU 利用率

这些指标会告诉你:

  • 当前瓶颈是在请求侧
  • 还是在 batch 组织侧
  • 还是在模型执行侧

九、最常见的误区

9.1 只看单次推理 benchmark

线上服务真正重要的是整体流量下的表现。

9.2 一上来把 batch 调很大

吞吐也许变高了,但延迟可能被拖垮。

9.3 只会跑模型,不会看队列和资源利用

这会让你很难真正理解系统瓶颈在哪里。


十、小结

这一节最重要的不是记住某个推理服务名词,而是理解:

高性能推理服务的核心,是把模型调用从“单次执行”变成“能在真实流量里平衡吞吐、延迟和资源使用的系统”。

这也是它和“本地跑通模型”本质上完全不同的地方。


练习

  1. 用自己的话解释:为什么 batching 和 concurrency 不是一回事?
  2. 想一想:如果你的产品要求很低延迟,你会倾向大 batch 还是小 batch?
  3. 设计一份最小推理服务监控指标清单。
  4. 为什么说推理服务真正难的是“平衡”,而不是单项做到极致?