一、并发调度概述:从单线程到多任务的进化之路
大家好,我是你们的老朋友。今天咱们聊聊并发调度。
说实话,我第一次接触并发调度这个概念时,也觉得挺抽象的。但后来在项目中踩过几次坑,才真正理解了它的价值。嗯,咱们慢慢来。
1.1 什么是并发调度?
并发调度,说白了就是「让多个任务看起来在同时执行」。你想想看,一个CPU核心同一时刻只能干一件事,但通过快速切换任务,就能让用户感觉所有任务都在跑。
我习惯用一个比喻来解释:就像餐厅里只有一个厨师,但他可以同时处理多个订单——切菜、炒菜、装盘,轮着来。这就是并发调度。
核心定义:并发调度是指系统根据某种策略,在多个就绪任务之间分配CPU时间片,使它们交替执行的过程。
在推理场景中,这个「厨师」就是GPU或CPU,「订单」就是一个个推理请求。调度器负责决定先处理哪个请求、什么时候切换、给每个请求分配多少计算资源。
1.2 为什么需要并发调度?
这个问题我问过很多新人。答案往往很直接:「因为要快啊。」
对,但不全对。我总结三个核心原因:
- 资源利用率最大化——GPU计算单元很贵,闲着就是浪费。并发调度能让它一直干活。
- 响应时间可控——用户发了个推理请求,不能等前面排队的都跑完才响应。调度策略可以优先处理短任务。
- 系统吞吐量提升——单位时间内处理更多请求,这是商业价值所在。
我在项目中遇到过这样一个场景:一个推理服务没有做并发调度,结果GPU利用率只有30%,但请求排队时间却长达5秒。加了调度后,利用率冲到85%,平均延迟反而降到了800毫秒。这就是调度的力量。
1.3 并发与并行的区别
这个问题面试常考,但很多人其实没搞透。我直接说人话:
| 概念 | 本质 | 比喻 |
|---|---|---|
| 并发 | 交替执行,逻辑上同时 | 一个人吃三碗面,轮着吃 |
| 并行 | 同时执行,物理上同时 | 三个人各吃一碗面 |
并发是「看起来同时」,并行是「真的同时」。单核CPU只能并发,多核CPU才能并行。
你想想看,推理场景里,一个GPU有几千个CUDA核心,这些核心可以并行计算。但多个推理请求之间,往往需要并发调度来协调。为什么?因为显存有限、带宽有限,不能所有请求同时往里塞。
我的经验:设计推理系统时,先搞清楚瓶颈在哪。如果是计算瓶颈,考虑并行;如果是IO或显存瓶颈,考虑并发调度。我曾经在一个项目中搞反了,结果优化了个寂寞。
1.4 调度系统在推理场景中的核心价值
推理场景和普通计算场景不太一样。推理请求有这几个特点:
- 请求大小不一(短文本vs长文档)
- 延迟敏感(用户等着呢)
- 资源消耗可预测(模型固定)
调度系统在推理场景中,核心价值体现在三个方面:
1.4.1 吞吐量与延迟的平衡
说白了,就是「既要马儿跑,又要马儿少吃草」。调度策略可以动态调整:高峰期优先保证吞吐量,低峰期优先降低延迟。
我习惯用「批处理窗口」来控制这个平衡。窗口大了吞吐量高但延迟也高,窗口小了延迟低但吞吐量上不去。怎么调?看业务需求。
1.4.2 资源隔离与公平性
多租户场景下,不能因为一个用户的请求量大,就把其他用户的请求饿死。调度系统可以按权重分配资源,保证公平。
我曾经遇到过一个客户,他们的推理服务被一个大模型请求占满了显存,小模型请求全被阻塞。后来加了基于优先级的调度策略,问题才解决。
1.4.3 动态负载均衡
推理请求的到达时间是不均匀的。调度系统可以根据当前负载,动态调整并发度,避免系统过载或空闲。
注意:不要以为并发调度是万能的。调度本身也有开销。如果任务切换太频繁,调度开销可能超过收益。我见过有人把时间片设成1微秒,结果CPU全在调度了,实际计算没干多少。
知识体系总览
下面这张图,是我梳理的本章知识结构。建议你保存下来,后面章节都会用到。
这张图把本章的核心内容串起来了。从定义出发,到为什么需要,再到并发与并行的区别,最后落到推理场景的价值。后面的章节,我们会逐一深入每个细节。
一个小建议:学并发调度,别死记硬背。找个你熟悉的推理框架(比如vLLM、TGI),看看它的调度器是怎么实现的。动手调一调参数,感受一下不同策略的效果。我当年就是这么入门的。
好了,这一章就到这里。记住一句话:并发调度不是目的,而是手段。它的终极目标,是让推理系统在有限的资源下,跑出最好的效果。
想要更多资料,联系可可