一、单机多卡调度策略:时间片轮转、优先级调度、Gang Scheduling
各位同学,今天我们来聊聊单机多卡场景下的调度策略。说实话,这块内容我当年刚接触时也觉得挺枯燥的,直到我在一个训练任务里踩了坑——8张卡,跑一个模型,结果有的卡忙死,有的卡闲死。嗯,从那以后我才真正重视起调度策略来。
单机多卡,说白了就是一台机器上插了多块GPU。你想想看,这些卡怎么分配任务?谁先跑?谁后跑?跑多久?这就是调度策略要解决的问题。我个人习惯把调度策略分成三类:时间片轮转、优先级调度、还有Gang Scheduling。咱们一个一个来看。
核心观点:调度策略的选择直接影响GPU利用率和训练效率。选错了,再好的硬件也白搭。
1.1 时间片轮转(Round-Robin)
时间片轮转,这个名字听起来挺唬人,其实原理很简单。就像学校食堂打饭,每个人轮流来,每人打一勺,打完一轮再从头开始。GPU调度也是这个道理——每个任务分到一个时间片,时间到了就换下一个任务。
我在项目中遇到过这样一个场景:4张卡,跑8个推理任务。如果用时间片轮转,每张卡上轮流跑2个任务,每个任务跑100ms就切换。这样做的好处是什么?公平!每个任务都能得到差不多的GPU时间,谁也别想独占。
但这里有个坑——上下文切换开销。我曾经在一个推理服务里用时间片轮转,结果发现切换太频繁了,GPU光忙着保存和恢复上下文了,真正干活的时间反而少了。后来我把时间片从50ms调到了200ms,吞吐量直接提升了30%。
经验之谈:时间片大小怎么设?我个人建议:推理任务用100-200ms,训练任务用500ms-1s。当然,具体还得看你的任务特点。
时间片轮转的优缺点很明显:
- 优点:实现简单,公平性好,每个任务都能得到响应
- 缺点:没有优先级概念,重要任务也得排队;上下文切换有开销
1.2 优先级调度(Priority Scheduling)
优先级调度就更好理解了——谁重要谁先上。就像医院急诊,危重病人优先处理。在GPU调度里,我们可以给每个任务设置一个优先级,调度器会优先把GPU资源分配给优先级高的任务。
我记得有一次做线上推理服务,用户请求分两种:VIP用户的实时请求和普通用户的批量请求。VIP请求必须秒级响应,普通请求可以等几秒。这时候优先级调度就派上用场了——VIP请求优先级设为10,普通请求设为5。调度器一看,有VIP请求来了,立马把GPU让给它。
但优先级调度有个经典问题——优先级反转。什么意思呢?就是低优先级任务占着资源不放,高优先级任务干等着。我曾经就遇到过:一个低优先级的预处理任务占着GPU显存,高优先级的推理任务死活拿不到资源,结果VIP用户等了5秒才得到响应。后来我加了优先级继承机制,才解决了这个问题。
避坑指南:我曾经在优先级调度里忘了处理优先级反转,结果线上出了事故。记住:高优先级任务等待低优先级任务释放资源时,低优先级任务应该临时继承高优先级。
优先级调度的关键参数:
| 参数 | 说明 | 建议值 |
|---|---|---|
| 优先级范围 | 任务优先级数值范围 | 0-100(数值越大优先级越高) |
| 优先级继承 | 是否启用优先级继承机制 | 建议开启 |
| 抢占粒度 | 高优先级任务能否抢占正在运行的低优先级任务 | 建议允许抢占 |
1.3 Gang Scheduling(组调度)
Gang Scheduling,中文叫组调度,这个稍微复杂一点。它的核心思想是:要么一起跑,要么都不跑。什么意思呢?就是一组相关的任务必须同时被调度到不同的GPU上运行,要么就全部等待。
你想想看,在分布式训练里,一个模型被切分到多张卡上,每张卡跑模型的一部分。如果只有部分卡在跑,其他卡闲着,那跑起来的卡也得等着——因为数据依赖啊!这就是Gang Scheduling要解决的问题。
我在做大规模语言模型训练时,就遇到过这个问题。模型被切分到8张卡上,结果调度器只分配了6张卡,剩下2张卡还在等资源。那6张卡跑了一会儿就得停下来等同步,GPU利用率直接掉到40%。后来改用Gang Scheduling,8张卡要么一起跑,要么一起等,利用率提升到了85%以上。
关键点:Gang Scheduling特别适合数据并行和模型并行的训练场景。说白了,就是那些需要多卡协同工作的任务。
Gang Scheduling的实现要点:
- 组定义:哪些任务属于同一个组?通常是一个训练任务的所有子任务
- 资源预留:调度器必须同时为组内所有任务分配资源,不能部分分配
- 同步机制:组内任务之间需要同步点,确保进度一致
三种调度策略的对比:
| 策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 时间片轮转 | 推理服务、多任务共享GPU | 公平、实现简单 | 无优先级、切换开销 |
| 优先级调度 | 有QoS要求的推理服务 | 重要任务优先 | 优先级反转问题 |
| Gang Scheduling | 分布式训练、多卡协同 | 避免资源碎片、提高利用率 | 实现复杂、资源预留可能导致等待 |
最后,我给大家画了一张图,把三种调度策略的核心逻辑展示出来。这张图我画了好几次才满意,希望能帮你们理解。
好了,三种调度策略就讲到这里。说实话,没有哪种策略是万能的。我个人的做法是:根据场景选策略,根据数据调参数。推理服务用时间片轮转加优先级,训练任务用Gang Scheduling。当然,实际项目中往往需要组合使用,这个我们后面章节再细聊。
最后一个小建议:刚开始做多卡调度时,别想着一步到位。先用时间片轮转跑起来,观察GPU利用率,再逐步优化。我曾经就是太着急,一上来就搞Gang Scheduling,结果调试了三天才跑通。
想要更多资料,联系可可