理论基础
经典调度算法:从直觉到数学
经典调度算法是所有调度系统的基础。不管你用的是 K8S 默认调度器、Volcano 还是自研调度器,底层的排序逻辑一定逃不出这几个经典算法的思想。面试中,面试官期望你不只是知道算法名字,还能说清楚:为什么这个算法最优?最优的条件是什么?在什么条件下它会失败?
操作系统算法到 AI 集群调度的映射
FIFO、SJF、Round Robin、优先级、CFS 这些名字来自操作系统,但在 AI Infra 里会变成队列排序、准入控制、租户公平、抢占和节点放置策略。学习时建议把它们分成两层:排序层决定“谁先被考虑”,放置层决定“放到哪里”。
| OS 调度概念 | 核心含义 | 集群调度中的对应物 | AI Infra 注意点 |
|---|---|---|---|
| FIFO / FCFS | 按到达顺序执行 | 队列按提交时间排序 | 大 gang 任务可能造成 head-of-line blocking |
| SJF | 短任务优先 | 短实验、短 inference batch、短 pipeline stage 优先 | 需要运行时长预测,长任务要配 aging 防饥饿 |
| Round Robin | 时间片轮转 | 队列/租户轮转,按 ClusterQueue 轮转取任务 | GPU 任务不适合频繁时间片切换,但适合队列级轮转 |
| 优先级调度 | 高优先级先执行 | PriorityClass、Queue priority、抢占 | 低优任务要有 aging 或保障份额,否则会长期饥饿 |
| CFS | 按虚拟运行时间实现公平份额 | 按 dominant share、quota debt 或保障度做公平调度 | 多资源场景不能只按 GPU 数公平,要看 CPU/内存/GPU/NIC 的主导资源 |
基础调度策略详解
1. FIFO(First In First Out)
定义:先到的任务先调度。不看任务大小、不看优先级、不看紧急程度。
怎么理解:超市排队。先来先结账,不管你买 1 件还是 100 件。
优点:实现最简单,不需要任何预测信息(不需要知道任务运行多久),天然公平(按到达顺序)。
致命问题:Head-of-line blocking:如果队首是一个 10 小时的训练任务,后面 100 个 5 分钟的实验任务全部被阻塞。
面试中怎么答:FIFO 是所有调度器的默认起点。面试时不要说"FIFO 不好"——要说"FIFO 在什么场景下够用,什么场景下不够"。对于同质任务(运行时间差不多),FIFO 就够了。对于异质任务(短实验 + 长训练),FIFO 的 head-of-line blocking 就不可接受了。
2. SJF(Shortest Job First)
定义:运行时间最短的任务优先调度。不可抢占——一旦开始就必须跑完。
核心性质:SJF 最小化平均等待时间
直觉证明:假设队列里有任务 A(1h) 和 B(10h)。如果先 A 后 B:A 等 0h,B 等 1h,平均等待 = 0.5h。如果先 B 后 A:B 等 0h,A 等 10h,平均等待 = 5h。短任务排前面,它们的等待时间短(因为本身短),长任务无论排哪里都要等,放后面只增加一个"短任务的执行时间"。所以短任务优先永远不劣。
致命问题:饥饿:如果短任务源源不断到达,长任务可能永远排不上。
前提条件:必须知道任务的运行时间。在 GPU 集群里,用户声明、历史统计或在线预测可以提供这个信息。
面试中怎么答:面试官问"为什么 SJF 最优",你应该:(1) 说"它最小化平均等待时间";(2) 用简单的数字例子说明;(3) 补"但它会导致饥饿,需要 aging 或配额保障来缓解"。
3. SRTF(Shortest Remaining Time First)
定义:SJF 的抢占版本。按剩余时间排序,新来的短作业可以打断正在执行的长作业。
和 SJF 的本质区别:SJF 按总执行时间排序,任务一旦开始就不可中断。SRTF 按剩余时间排序,每当新任务到达时重新排序,可以抢占。
什么时候比 SJF 更好:当任务到达时间不确定时。例如多 agent 工作流中,不断有新 stage 到达。SRTF 可以让新来的短 stage 立即执行,避免被正在执行的长 stage 阻塞。
额外代价:(1) 需要抢占机制;(2) 需要更精确的剩余时间预测;(3) 抢占本身的成本(训练任务可能需要回滚到 checkpoint)。
怎么理解:SJF 像"餐厅只接受预约,上桌了就不赶人走"。SRTF 像"急诊室分诊——新来了更急的病人,正在处理的可以先放一放"。
4. EDF(Earliest Deadline First)
定义:截止时间最近的任务优先调度。可抢占。
适用场景:有明确 deadline 的任务。如实时系统、数据 Pipeline("明早 8 点前必须跑完")、模型发布倒计时。
最优性:在任务可抢占且 deadline 可知的前提下,EDF 是最优的——如果 EDF 都调不了,没有任何算法能调。
局限:(1) 需要知道 deadline;(2) 系统过载时,所有接近 deadline 的任务会"集体崩溃";(3) GPU 训练任务通常没有明确的 deadline,所以 EDF 在 GPU 集群中用得少。
怎么理解:EDF 像"赶飞机"——谁离登机时间最近谁先走安检。
5. Round Robin
定义:每个任务分配一个时间片,时间片用完就换下一个任务。循环往复。
优点:绝对公平——每个任务获得相等的 CPU 时间。
局限:(1) 上下文切换开销大——GPU 训练任务切换代价极高(模型加载 + NCCL 重建),不适合频繁切换;(2) 时间片大小难选——太小浪费切换时间,太大又退化成 FIFO。
GPU 集群里几乎不用:因为 GPU 任务不能"切一小段就换"。但"按队列轮转调度"的思想(如 Kueue 的 ClusterQueue 轮转)是 Round Robin 的变体。
6. 优先级调度
定义:按静态或动态优先级排序调度。优先级可以基于业务重要性、紧急程度、资源效率等。
静态 vs 动态优先级:静态优先级在提交时确定,运行中不变。动态优先级可以变化——例如 aging(等待越久优先级越高)、或者基于 QAD(保障度低的队列优先级提升)。
问题:低优先级任务可能饥饿。需要 aging 或配额保障来缓解。
算法对比与选择
| 算法 | 可抢占 | 需要预测 | 最优性 | 饥饿风险 | GPU 集群适用性 |
|---|---|---|---|---|---|
| FIFO | 否 | 否 | 同质任务最优 | 无 | 默认基线 |
| SJF | 否 | 是(运行时间) | 最小化平均等待 | 长任务饥饿 | 短实验优先场景 |
| SRTF | 是 | 是(剩余时间) | 最小化平均等待 | 长任务饥饿 | 多 agent 工作流 |
| EDF | 是 | 是(deadline) | 实时最优 | 过载崩溃 | Pipeline 场景 |
| Round Robin | 是 | 否 | 公平最优 | 无 | 几乎不用 |
| 优先级 | 可选 | 否 | 取决于优先级设定 | 低优先级饥饿 | 最常用 |
实际系统的组合策略
真实调度器不会只用一个算法,而是组合使用:
面试中,你要说清楚"每个决策点用了哪个算法的什么思想",而不是笼统地说"用了 SJF"。
Bin Packing vs Spread
这是放置策略的经典对比,面试中经常出现。
Bin Packing
定义:尽量把任务塞到已有节点,减少碎片。它来自装箱问题:给定一批物品和若干箱子,希望用尽可能少的箱子装下所有物品。在调度里,物品是 Pod/Job 的资源需求,箱子是 Node 或资源池。
类比:装箱——先把一个箱子装满,再开新的。
GPU 集群为什么常用:GPU 是昂贵资源,碎片化(节点 A 剩 1 GPU,节点 B 也剩 1 GPU,但需要 2 GPU 的任务放不进去)是最大浪费。Bin Packing 尽量让某些节点跑满,留出完整的空闲节点给大 gang。
风险:(1) 单节点故障影响更多任务(爆炸半径大);(2) 热点——某些节点过于拥挤。
Bin Packing 在调度器里怎么实现
| 层次 | 做法 | 直觉 | 风险控制 |
|---|---|---|---|
| Filter | 过滤放不下 CPU/内存/GPU/端口/拓扑约束的节点 | 先保证可行 | 不要为了装箱破坏硬约束 |
| Score | 给“放入后剩余资源更少、更紧凑”的节点更高分 | 优先填满已有节点 | 加入温度、故障域、拓扑质量权重 |
| Reserve | 暂存被选节点上的资源占用 | 避免并发调度重复占用 | 失败时必须 Unreserve |
| 全局队列 | 把小任务回填到碎片,把大任务留完整资源窗口 | 减少碎片累积 | 配合 backfill 和 aging 避免大任务/小任务互相伤害 |
Spread
定义:尽量把任务分散到不同节点。
类比:分散投资——不把鸡蛋放在一个篮子里。
适用场景:在线推理服务——需要高可用,节点挂了不能影响所有副本。
风险:碎片化——每个节点都剩一点 GPU,但凑不出大块。
选择建议
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 离线训练 | Bin Packing | 减少碎片,大 gang 更容易放得下 |
| 在线推理 | Spread | 高可用,单节点故障影响小 |
| 混合部署 | 推理 Spread + 训练 Bin Packing | 不同任务类型用不同策略 |
| 多租户实验平台 | Bin Packing + 故障域约束 | 减少碎片但避免单点故障 |
经典算法面试问答
三种思路:
- 预测驱动排序:SRTF/SJF 让短任务先执行,减少被长任务阻塞的概率。这解决的是"队首长任务阻塞后面短任务"的问题。
- 抢占:长任务阻塞时强制让位给高优先级任务。这解决的是"正在执行的任务不能被打断"的问题。
- 多队列:不同类型任务分开排队,互不干扰。这解决的是"不同类型任务对延迟要求不同"的问题。
实际系统中常常同时使用多种:SRTF 排序 + 抢占 + 分队列。例如 K8S 调度器有多个 Queue(ActiveQ、BackoffQ、UnschedulableQ),在 ActiveQ 内部按优先级排序,高优先级任务可以触发 preemption。
SJF 最小化平均等待时间。把短任务排前面,它们的等待时间短(因为本身短,不会让后面等太久)。长任务无论排哪里都要等前面的任务,放后面只增加一个"短任务的执行时间",放前面却让所有后面的人都多等它的长时间。所以短任务优先永远不劣。
如果短任务源源不断到达,长任务可能永远排不上。一个训练 20 小时的大任务,如果前面总有 5 分钟的实验任务插队,它可能等一天都启动不了。
(1) Aging:等待时间越长优先级越高。等了 N 小时的长任务优先级会超过刚到的短任务。(2) 配额保障:每个租户至少获得一定比例的调度机会。(3) 词典序排序:先看保障度(是否满足配额),再看运行时间。保障度不足的任务优先,同保障度内按 SJF 排序。
(1) 进度浪费:被抢占作业已完成的计算全部丢失(除非有 checkpoint)。一个训练了 20 小时、3 小时没 checkpoint 的任务被抢占,回滚到 17 小时前的状态。(2) 重启开销:重新排队、加载模型/数据、重建 NCCL 通信组——可能需要 5-30 分钟。(3) 系统开销:保存状态、清理资源、通知相关组件。
(1) Checkpoint 机制:定期保存进度,减少进度损失。代价是 I/O 开销。(2) 代价基抢占:选择沉没成本最小的牺牲者——checkpoint 新鲜、运行时间短的任务优先被抢占。(3) 在自然间隔抢占:在 stage 边界、epoch 结束时抢占,进度损失为零。需要训练框架配合。(4) 优雅终止:通知任务"请 checkpoint 后退出",给 5 分钟优雅期。(5) 弹性训练:缩减 world size 而非杀掉整个任务,释放部分 GPU 但训练继续。
GPU 集群的资源是多维的——CPU、内存、GPU、网络带宽。三个核心挑战:
- 碎片化:某些维度剩余很多,但另一个维度不够,整个节点不可用。例如一个节点剩 7 GPU 但内存用完了,那 7 GPU 也是浪费的。
- 耦合性:GPU 任务通常也需要大量 CPU 做数据预处理。一个任务分配了 8 GPU 但 CPU 不够,数据加载跟不上,GPU 在等数据。
- 异构性:不同 GPU 型号性能差异大。1 张 H100 ≈ 4 张 V100,但调度器可能只看到"1 张 GPU"。
DRF 从理论上解决公平性,但实际中还需要拓扑感知(NVLink 拓扑)、亲和性约束(CPU-GPU NUMA)和异构资源表达(GPU flavor)。
更好的调度决策需要更多信息(拓扑、负载预测、历史数据)和更多计算(更复杂的打分函数),但用户不想等太久——任务提交后应该尽快开始。
(1) 两阶段调度:Filter 快速排除明显不行的(几十毫秒),Score 只在少量候选中精选(几百毫秒)。大部分节点在 Filter 阶段就被淘汰了。(2) 缓存:Informer 本地缓存节点和 Pod 信息,避免每次调度都查 API Server。(3) 近似算法:不需要最优解,"足够好"就行。例如只对 top-K 候选节点做详细打分。(4) 异步:Bind 阶段异步执行,不阻塞下一个 Pod 的调度周期。调度器和 binder 是并行工作的。
K8S scheduler 的一个 scheduling cycle 约 10-100ms。它用 Informer cache + 两阶段 Filter/Score + 异步 Bind 来保证延迟可接受。
不要说"我选 XX 算法",而要说"我根据场景选择":
- 先定场景:推理/训练/实验平台?不同场景对延迟、吞吐、公平性的要求不同。
- 再看约束:是否有 gang 需求?是否有 deadline?是否需要预测运行时间?
- 然后选排序策略:同质任务用 FIFO,异质任务用优先级 + SJF,有 deadline 用 EDF。
- 最后说组合:实际系统是组合使用的——排序用 SJF/DRF,准入用 Gang/Quota,放置用 Bin Packing + 拓扑打分,抢占用代价感知。
"调度算法的选择不是非此即彼,而是根据场景在经典算法的基础上组合和调整。关键是说清楚每个决策点用了什么思想、为什么这样选。"
为什么调度要先定目标函数
很多人学调度会直接跳到算法——"怎么排序、怎么打分、怎么抢占"。但调度本质上是一个多目标优化问题:你在优化某个指标的同时,必然在牺牲另一个指标。如果不确定优化什么,算法就无从谈起。
举个例子:同样的集群,如果你优化平均 JCT,短作业优先(SJF)是最好的;但如果你优化公平性,SJF 会让长作业饥饿。两个目标都合理,但策略完全不同。
所以学调度的第一步,不是学算法,而是搞清楚每个指标衡量什么、谁在用它、它和别的指标怎么冲突。
核心指标详解
1. Waiting Time(等待时间)
定义:从任务提交到任务开始执行的时间。注意是"开始执行",不是"执行完毕"。
为什么重要:它衡量的是用户感知的响应速度。一个实验提交后等了 2 小时才开始跑,体验就很差。对于交互式任务、开发调试和在线推理,等待时间是最直接的体验指标。
面试中怎么用:当面试官问"你的调度器如何改善用户体验",如果你的系统侧重排队策略,waiting time 就是你最该展示的指标。但要注意,降低等待时间不等于降低 JCT——一个任务可能等 1 分钟就启动了,但跑了 10 小时。
怎么理解:想象你在超市排队。Waiting time 就是你从拿号到开始结账的时间。前面人少就快,前面有个人买了一整车东西就慢。SJF 相当于"买得少的人先结账"。
2. JCT(Job Completion Time)
定义:从任务提交到任务完成的总时间 = waiting time + execution time。
为什么重要:对于离线训练、批处理和 HPC 任务,用户最关心的是"我什么时候能拿到结果",而不是"什么时候开始跑"。JCT 是 AI 训练调度论文里最常用的指标。
面试中怎么用:面试官问"你的调度策略对训练任务有什么好处",你应该从 JCT 切入,但要分解成 waiting time 和 execution time 分别说明。例如拓扑感知调度不改变等待时间,但通过减少通信开销来降低 execution time,从而降低 JCT。
怎么理解:JCT = 排队时间 + 跑的时间。改善排队靠排序和准入策略,改善跑的时间靠拓扑放置和资源分配。
3. Makespan
定义:一批任务中,最后一个完成的时间。衡量的是"整批活什么时候干完"。
为什么重要:在批处理场景下,运维更关心"这批任务什么时候全部跑完"而不是单个任务体验。例如一个数据 Pipeline 要在明早 8 点前跑完,makespan 就是关键指标。
面试中怎么用:问"你怎么衡量一个批调度系统的效率"时,makespan 是答案之一,但要补一句——它和公平性冲突,因为最优 makespan 可能意味着某些任务被无限推迟。
怎么理解:Makespan 是站在管理员视角,JCT 是站在用户视角。两个视角对"好调度"的定义不同。
4. Throughput(吞吐量)
定义:单位时间内完成的任务数,或单位时间内处理的 token/images 数。
为什么重要:集群运营商和平台团队最关心吞吐,因为它直接对应资源产出效率。同样 100 张 GPU,如果调度策略能让每天完成的训练任务数从 50 增加到 80,相当于节省了 37.5% 的硬件成本。
面试中怎么用:不要把吞吐和利用率混淆——吞吐是产出,利用率是资源使用率。高利用率不一定意味着高吞吐(可能在跑低效任务),但低利用率通常意味着吞吐也不高。
怎么理解:吞吐 = 集群的"产出速度"。利用率 = 集群的"忙碌程度"。忙碌不等于高效。
5. Utilization(资源利用率)
定义:已使用资源 / 总资源。常见的有 GPU 利用率、CPU 利用率、内存利用率、网络带宽利用率。
为什么重要:GPU 利用率是 AI Infra 里最常被关注的指标。一个 8 卡 A100 节点的 GPU 利用率如果只有 30%,意味着 70% 的算力在闲置,而一张 A100 售价超过 1 万美元。
常见误区:高利用率 ≠ 好调度。如果一个调度器把所有任务都塞到少数节点上,利用率确实高,但可能牺牲了拓扑质量、公平性或故障隔离。利用率是一个"不该太低,但也不是越高越好"的指标。
面试中怎么用:当面试官问"怎么提高 GPU 利用率",你应该先问"什么类型的任务"。在线推理可以通过 continuous batching 提高;离线训练可以通过 bin packing 减少碎片;GPU sharing 可以让小任务合用一张卡。但每种方法都有代价——bin packing 可能增加故障爆炸半径,GPU sharing 可能有性能干扰。
6. Fairness(公平性)
定义:不同用户或团队之间资源分配的均衡程度。常用指标包括 dominant share 的基尼系数、max-min fairness 偏差、SLO violation 率等。
为什么重要:多租户 GPU 集群里,如果只用 throughput 做目标,调度器会偏向"资源效率高"的大团队,小团队的任务可能永远排不上。公平性保证每个团队都能获得合理份额。
面试中怎么用:公平性通常和利用率冲突。面试时要说明"怎么定义公平"比"要不要公平"更重要。是按 GPU 数量公平,还是按 dominant share 公平,还是按配额保障度公平?不同的定义会导致不同的策略。
怎么理解:公平不是均分。团队 A 有 100 个 researcher,团队 B 有 5 个 researcher,均分 50/50 对 B 来说过于慷慨。按人头、按配额、按保障度是三种不同的公平定义。
7. SLO Violation Rate(服务等级违约率)
定义:不满足服务等级目标(如延迟 P99 < 200ms、任务 24h 内完成)的请求或任务比例。
为什么重要:在线推理场景下,SLO 是最核心的约束。GPU 调度不能只追求利用率,而要保证推理服务的 tail latency 满足 SLO。
面试中怎么用:如果面试官问"在线推理和离线训练怎么混部",SLO violation rate 就是衡量混部是否成功的指标。推理的 SLO 是硬约束,训练可以弹性让步。
8. Preemption Cost(抢占代价)
定义:抢占一个正在运行的任务所造成的进度损失、重启成本和系统开销。
为什么重要:传统调度论文里抢占就是"杀掉低优先级,运行高优先级",但在 AI 训练里,一个训练任务被抢占后可能要回滚到数小时前的 checkpoint,重新加载模型和数据,重建 NCCL 通信组。这些代价远大于一个在线服务 Pod 被驱逐后重启。
面试中怎么用:如果你研究的是训练任务调度,抢占代价是你必须要考虑的维度。面试时应该说明"代价基抢占"怎么选择牺牲者——不是简单看优先级,而是看 checkpoint 新鲜度、运行时长、释放资源量和重启成本。
不同场景的指标优先级
面试中最常问的问题之一就是"这个指标在你的场景里排第几"。没有统一答案,但可以按场景给出典型排序:
在线推理场景
- SLO / Tail Latency——推理服务的核心承诺
- Throughput——单位时间处理的 token/请求数
- GPU Utilization——但不应牺牲 SLO
- Fairness——多模型之间
推理场景不太关心 JCT 和抢占——推理请求是毫秒级,没有 checkpoint 概念。
离线训练场景
- JCT——用户最关心什么时候出结果
- GPU Utilization——训练成本高,碎片化是浪费
- Fairness——多团队共享时避免饥饿
- Preemption Cost——训练抢占代价大
训练场景不太关心单个请求延迟和 SLO。
实验平台场景
- Waiting Time——实验反馈速度决定研发效率
- Fairness——多个 researcher 共享集群
- Utilization——但不应过度影响反馈速度
实验平台的特点是短作业多、交互性强、用户等待容忍度低。
大模型预训练场景
- Stability——训练一旦开始,尽量不中断
- Topology Quality——通信效率直接影响训练速度
- Fault Tolerance——硬件故障必须快速恢复
- Utilization——但稳定性更重要
大模型预训练的特点是时间长(数周到数月)、GPU 多(数百到数千)、中断代价极高。这个场景下,频繁抢占、gang 不满足、拓扑差都是不可接受的。
指标之间的典型冲突
理解冲突比理解指标本身更重要。面试中如果能说清楚冲突和权衡,比单纯罗列指标更有区分度。
公平性 vs 利用率
严格配额可以保证公平,但可能导致某些队列空闲时其他队列不能用。例如团队 A 的 32 张 GPU 配额只用了 10 张,团队 B 的任务在排队,但配额不允许 B 借用 A 的空闲 GPU。解决方式是弹性借用——允许借用,但在保障租户需要时能回收。
短作业优先 vs 长作业饥饿
SJF/SRTF 能降低平均 JCT,但长作业可能永远排不上。解决方式是 aging(等待越久优先级越高)或配额保障(每个租户至少获得一定比例的调度机会)。
拓扑最优 vs 调度延迟
等待同机柜或同 NVLink 资源可以提升训练性能,但会增加排队时间。如果所有任务都要求"最优拓扑",大部分时间 GPU 在等完美组合而不是干活。解决方式是设定可接受的拓扑质量阈值,超过阈值就不等了。
抢占效率 vs 进度损失
抢占可以快速释放资源给高优先级任务,但训练任务的 checkpoint 可能是 1 小时前的,被抢占意味着 1 小时的计算白费。解决方式是代价基抢占——优先抢占 checkpoint 新鲜、运行时间短的任务。
装箱 vs 故障域隔离
Bin packing 降低碎片,但把任务集中到少数节点会增加单节点故障的影响范围。解决方式是按故障域分级——在线服务尽量分散,训练任务可以集中但需要快速恢复机制。
公平性、吞吐量、延迟、资源利用率的 trade-off
调度系统不可能同时把所有指标都推到最优。面试里最重要的不是说“我都优化”,而是说明你的场景下哪个指标是硬约束、哪个是优化目标、哪个可以让步。
| 优化目标 | 常用策略 | 通常牺牲什么 | 适用场景 | 风险 |
|---|---|---|---|---|
| 公平性 | quota、DRF、CFS-like share、aging | 短期利用率和整体吞吐 | 多租户平台、共享 GPU 集群 | 严格隔离会让空闲配额不能被借用 |
| 吞吐量 | SJF、batching、bin packing、提高并发 | 单个任务延迟和长任务公平 | 离线批处理、低优训练队列 | 短任务偏置导致长任务饥饿 |
| 低延迟 | 优先级、预留资源、抢占、spread | 资源利用率和吞吐 | 在线推理、交互式 notebook、紧急任务 | 预留过多会造成 GPU 闲置 |
| 高资源利用率 | backfill、bin packing、GPU sharing、超卖 | SLO、故障隔离、公平性 | 成本敏感平台、离线混部 | “忙但没产出”,或互相干扰 |
在线调度 vs 离线调度
在线和离线不是“线上服务”和“离线任务”的简单同义词,而是算法是否提前知道完整输入的区别。在线调度只能看到已经到达的任务,必须边到达边决策;离线调度提前知道全部任务、资源和运行时间,可以做全局优化。
| 维度 | 在线调度 Online Scheduling | 离线调度 Offline Scheduling |
|---|---|---|
| 信息可见性 | 只知道当前和历史任务,不知道未来 | 提前知道完整任务集合和约束 |
| 决策方式 | 每个任务到达时立即或短时间内决策 | 可以全局搜索、排序、规划 |
| 典型系统 | K8s scheduler、在线推理调度、交互式实验平台 | 批处理排程、生产计划、trace replay 仿真 |
| 评价重点 | 竞争比、延迟、鲁棒性、实时响应 | 全局最优性、makespan、平均 JCT |
| 工程难点 | 未来不确定、任务时长预测不准、不能频繁反悔 | 求解复杂度高,假设可能不符合真实在线环境 |
AI 集群大多数实际调度是在线调度,但会吸收离线思想:用历史 trace 训练预测器,用未来资源释放估计做 backfill,用离线仿真评估策略。
回答结构
当面试官问"你怎么衡量调度系统的好坏",用这个框架回答:
- 先定场景——推理、训练、实验平台、大模型预训练?不同场景的指标优先级不同。
- 再说核心指标——选 2-3 个最重要的,说清楚定义和为什么重要。
- 然后说冲突——这些指标之间的矛盾是什么,你怎么权衡。
- 最后说实验——你用什么 trace、什么 baseline、什么 workload 证明了你的策略改善了哪些指标。
JCT = waiting time + execution time。Waiting time 只衡量排队,JCT 衡量从提交到完成的全部时间。
降低 waiting time 靠排队策略(排序、准入、抢占)。降低 execution time 靠放置策略(拓扑、资源分配、GPU sharing)。降低 JCT 需要两者配合。
拓扑感知调度可能不改变 waiting time(甚至可能增加,因为等更好拓扑),但通过减少通信开销降低了 execution time,最终 JCT 反而更低。
高利用率可能意味着:(1) 确实调度合理,资源被高效使用;(2) 任务都挤在少数节点,牺牲了拓扑和故障隔离;(3) GPU 在做无效计算,例如 NCCL 等待、数据加载瓶颈或 MPS 干扰。
看利用率的同时看吞吐、JCT 和 SLO。如果利用率高但吞吐低,说明 GPU 在"忙但没产出"。如果利用率高但 JCT 也在增加,说明调度可能在做过度装箱。
离线训练论文通常报告 JCT(平均和中位数)、waiting time、GPU 利用率。多租户论文加上公平性(dominant share 偏差或配额保障度)。在线推理加上 SLO violation rate 和 tail latency。
每次去掉一个机制,看哪个指标退化了。例如去掉拓扑感知,JCT 可能增加但 waiting time 不变;去掉公平性,小团队的 waiting time 可能急剧增加;去掉抢占,高优先级任务的 waiting time 增加。
和默认 scheduler 比,和 Volcano/Kueue 比,和同领域论文比。如果只和自己去掉了某些机制的版本比,说服力有限。
(1) 优化了什么:明确说指标名,例如"优化了 P90 JCT,降低了 25%"。(2) 牺牲了什么:例如"在极端负载下,短作业的 waiting time 略有增加,因为我们优先调度 gang 任务"。(3) 为什么可接受:例如"增加的 waiting time 在 5 分钟以内,但 gang 任务的 JCT 改善了 30%,整体集群利用率提高了 15%"。
面试官不期望你优化所有指标,但期望你说清楚权衡。能说清楚"牺牲了什么、为什么可接受"比"什么都优化了"更有说服力。
Makespan 是"最后一个任务什么时候完成",平均 JCT 是"所有任务的平均完成时间"。Makespan 是管理员视角,平均 JCT 是用户视角。
优化平均 JCT 通常会让短任务先跑(SJF),但这可能推迟长任务的完成时间,从而增加 makespan。反过来,如果优化 makespan,可能需要所有任务并行跑,但这会增加资源竞争和通信开销,单个任务的 JCT 不一定改善。
批处理和数据 Pipeline 关心 makespan;交互式训练和实验平台关心平均 JCT;多租户平台还要看公平性。