返回关卡地图
预判 0 / 3 闯关题:0 / 3 XP 0 / 300

Level 28 | 零基础导学关卡

Pipeline 并行微批次

Pipeline Parallelism MicroBatch

先通过图解和小例子理解原理,再做预测与练习;不懂的地方可以反复尝试,最后把理解写进官方 Notebook。

本课官方 Notebook ↗
28_Pipeline_Parallelism_MicroBatch.ipynb 并行通信Pipeline ParallelismMicroBatch
Mission 1 概念练习

先画时间轴:stage 越靠后,同一 micro-batch 越晚到达

🎯 先猜一猜

p=3、m=4,在时间 t=4 查看 stage=2。

此时 micro_idx=t-stage 是多少,是否应记录?

先猜一个答案,再对照下面的讲解。可以随时修改选择,猜错会得到解释。

先补的知识

  • p 表示 Pipeline stage 数量,m 表示 micro-batch 数量;编号都从 0 开始。
  • timeline 是 Python 列表;timeline[t] 又是一个列表,保存该时间步活跃的 (stage, micro_idx) 元组。
  • micro-batch 每经过一个 stage 就晚一个时间步,因此在时间 t、阶段 stage 上,对应编号是 micro_idx = t - stage。
  • 只有 0 <= micro_idx < m 时该任务真实存在;负编号表示还没到达,编号达到 m 表示所有 micro-batch 已经过完。

图解原理

把 micro-batch 想成依次进入流水线的小批任务。第 0 个任务在 t=0 进入 stage 0,t=1 到 stage 1;与此同时第 1 个任务进入 stage 0。于是活跃项沿着“时间向右、stage 向下”的对角线移动。

入口每个时间步可有一个新 micro-batch 进入 stage 0 传播同一 micro-batch 每过一步进入下一个 stage 边界只记录 0 <= micro_idx < m 结束最后一个 micro-batch 离开最后一个 stage
时间 tp=3、m=4 时的 active 列表活跃槽位数
0[(0,0)]1
1[(0,1),(1,0)]2
2[(0,2),(1,1),(2,0)]3
3[(0,3),(1,2),(2,1)]3
4[(1,3),(2,2)]2
5[(2,3)]1

为什么有 m + p - 1 步

4 个 micro-batch 依次进入需要 4 步;最后一个进入后,还要再穿过剩余 p-1=2 个 stage,所以总共 6 步。

一条公式决定格子内容

已知tstage 计算micro_idx = t - stage 保留条件0 <= micro_idx < m
timeline 不是 Tensor,没有 shape/dtype/device;它的结构契约是“长度为总时间步数的 list,每个元素是若干二元 tuple”。

语法热身:用两道工序和五个订单练对角线调度

stations, orders = 2, 5
steps = stations + orders - 1
schedule = []

for tick in range(steps):
    working = []
    for station in range(stations):
        order_id = tick - station
        if 0 <= order_id < orders:
            working.append((station, order_id))
    schedule.append(working)

例子中的变量 -> Notebook TODO 变量/操作

  • stations -> porders -> m
  • steps -> Notebook 的总时间步数,来自 stage 数与 micro-batch 数。
  • tick/station/order_id -> t/stage/micro_idx
  • schedule/working -> timeline/active:都是嵌套 Python list,不涉及 Tensor dtype 或 device。

巩固一下

p=3、m=4 时,timeline 应包含多少个时间步?

学完这一段,试着做

用一个小动作确认自己理解了;最后再进入官方题目。

Mission 2 概念练习

再数槽位:空闲比例 = 1 - 活跃槽位 / 全部槽位

🎯 先猜一猜

p=3、m=4 的时间轴每步活跃数是 1、2、3、3、2、1。

全部槽位 total_slots 应如何计算?

先猜一个答案,再对照下面的讲解。可以随时修改选择,猜错会得到解释。

先补的知识

  • 一个槽位表示“某个时间步里的某个 stage”;每步有 p 个槽位。
  • len(step) 是该时间步的活跃 stage 数,把所有 step 的长度相加就是 active_slots。
  • timeline 一共有 m+p-1 步,所以 total_slots = len(timeline) * p。
  • bubble 是空闲占比。先求活跃占比 active_slots/total_slots,再用 1 减去它。

图解原理

时间轴已经告诉我们每一刻有几台 stage 在工作。现在只做一次考勤:所有可能的“时间 × stage”格子是总槽位,有任务的格子是活跃槽位,剩下的格子就是气泡。

1timeline = build_pipeline_timeline(p, m)先使用 TODO 1 的真实调度结果
2active_slots = sum(len(step) ...)每个二元组代表一个活跃槽位
3total_slots = len(timeline) * p每一步最多 p 个 stage 同时工作
4bubble = 1 - active / total返回 0 到 1 之间的 Python 浮点比例

继续 p=3、m=4 的例子

每步活跃数1 + 2 + 3 + 3 + 2 + 1 = 12 全部槽位6 个时间步 × 3 个 stage = 18 气泡比例1 - 12/18 = 1/3

和闭式公式对上

每个 m 个 micro-batch 都经过 p 个 stage,所以 active_slots=m×p。

代入总槽位 p×(m+p-1),约掉 p 后得到 (p-1)/(m+p-1)。

p=8、m=32语义
len(timeline)3932+8-1 个时间步
active_slots25632×8 次 stage 计算
total_slots31239×8 个可用格子
bubble7/39 ≈ 0.1795落在测试要求的 0.15 到 0.25 之间
分母不是 active_slots,也不是单独的 m;它必须覆盖完整时间轴上的全部 stage 槽位。

语法热身:用教室考勤表练活跃格与空闲格统计

attendance = [
    [('A', 0)],
    [('A', 1), ('B', 0)],
    [('B', 1)],
]
rooms = 2
present = sum(len(period) for period in attendance)
capacity = len(attendance) * rooms
idle_ratio = 1.0 - present / capacity
assert idle_ratio == 1.0 / 3.0

例子中的变量 -> Notebook TODO 变量/操作

  • attendance -> timeline:每个内层列表记录当前时刻的活跃项。
  • rooms -> p:每个时间步最多可用的并行槽位数。
  • present -> active_slots,通过各步 len 求和。
  • capacity/idle_ratio -> total_slots/bubble;返回普通 float,不涉及 Tensor device。

巩固一下

p=8、m=32 时,基于时间轴得到的精确 bubble ratio 是哪一个?

学完这一段,试着做

用一个小动作确认自己理解了;最后再进入官方题目。

Mission 3 概念练习

最后用测试反推:micro-batch 越多,固定灌排成本越薄

🎯 先猜一猜

保持 p=8 不变,把 m 从 32 增大到 64。

简化模型中的 bubble ratio 会怎样变化?

先猜一个答案,再对照下面的讲解。可以随时修改选择,猜错会得到解释。

先补的知识

  • 气泡来自开头灌满 p 个 stage 和结尾排空的固定开销,公式分子 p-1 不随 m 增长。
  • m 增大时,分母 m+p-1 增大,所以气泡占比下降;这不代表现实系统可以无限增加 m。
  • 可见测试为了兼容精确公式与大 m 近似公式,只要求 0.15 &lt; ratio &lt; 0.25。
  • 当前模拟忽略通信、前后向差异、显存和真实 1F1B 细节;TODO 的目标是读懂简化时间轴,而不是实现完整分布式调度器。

图解原理

p-1 个灌排空档像固定成本。只处理很少 micro-batch 时,这部分占比很大;让更多 micro-batch 连续穿过流水线,固定空档被更多有效计算摊薄。测试选择 m=32、p=8,就是在检查这个趋势是否落到合理数值。

m 很小

p=8、m=1 时,气泡是 7/8。只有一个 micro-batch 沿对角线移动,大部分 stage 槽位都在等待。

测试规模

p=8、m=32 时,精确值是 7/39,约 0.1795,能通过 0.15 到 0.25 的严格区间。

m 继续增大

p 固定时,分母继续增长,气泡趋近 0;但现实里还要考虑 micro-batch 太小带来的算力利用率和通信问题。

非 None
函数确实返回结果
大于 0.15
没有把气泡低估到不合理
小于 0.25
没有把空闲比例算得过高
精确参考
7/39 ≈ 0.1795

两个边界自检

p=1没有跨 stage 灌排,bubble 应为 0 m=1只有一条对角线,bubble 应为 (p-1)/p

调试顺序

先打印每个 timeline step,再核对 active_slots,最后才看 ratio。这样能区分是调度构造错,还是统计公式错。

测试区间较宽不等于任意公式都可以。基于 TODO 1 的时间轴逐格统计,才能让代码结构、精确公式和调度直觉三者一致。

语法热身:用固定准备时间观察任务数增加后的空闲占比

setup_steps = 3
for jobs in [1, 4, 16]:
    idle = setup_steps / (jobs + setup_steps)
    print(jobs, idle)

# jobs 增加时,固定 setup_steps 被更多有效工作摊薄
assert 3 / (16 + 3) < 3 / (4 + 3)

例子中的变量 -> Notebook TODO 变量/操作

  • setup_steps -> p - 1:流水线灌满与排空带来的固定项。
  • jobs -> m:连续送入的 micro-batch 数量。
  • idle -> bubble:用于理解趋势,Notebook 仍要求从 timeline 统计得到它。
  • 这些都是 Python 数值,没有 Tensor shape/dtype/device;最终测试只比较 ratio 的数值区间。

巩固一下

compute_bubble_ratio(p=8, m=32) 返回 0.1795 左右时,可见测试结果是什么?

学完这一段,试着做

用一个小动作确认自己理解了;最后再进入官方题目。

把理解变成自己的代码

准备好,去官方题目试一试

在本页用小例子建立直觉,再去官方 Notebook 完成实现。先运行你自己的测试,遇到困难时再查看官方提示与参考答案。

前往本课官方 Notebook ↗

这节课会遇到的代码对象

build_pipeline_timeline · compute_bubble_ratio

先找题目里的输入、输出与 TODO,再把本课的手算过程对应进去;以官方题目中的函数说明和测试为准。

练习来源:Datawhale 官方仓库 · 518cc45。这里的入口直接打开官方版本,不读取或分享你的本地 Notebook。

完成 3 道闯关题后,本关即算完成;作业 checklist 用来辅助你回 notebook 练习。
进度只保存在当前浏览器 localStorage,分享 HTML 不会带走你的记录。
上一关:L27 下一关:L29