Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第 9 讲 · 闭卷回忆卡

用法:遮住答案,在空白纸上写;写完再展开对照。每张卡末尾标记号:✓ 能完整写出 / △ 有关键词但缺条件 / × 完全想不起,只重做 △ 与 ×。共 33 张卡(定义 9 / 结论 8 / 公式 8 / 陷阱 8),一轮约 36 分钟。 凡涉及数字的卡片,评分时必须连带写出确认口径(精度 + 优化器 + 是否含主权重 + 卡数),否则按 △ 计。

A. 定义卡

A1. 写出「模型状态」与「激活」的定义,并各给一种只对它有效的省显存手段。

解答

模型状态 = 参数 + 梯度 + 优化器状态 + 主权重,∝N\propto N、与批大小无关、训练全程常驻(处方:ZeRO/FSDP 分片、8-bit 优化器、CPU offload、降精度)(定义 9.1.1);激活 = 前向中间张量,∝BmicroTL\propto B_{\text{micro}}T L、用完即释放(处方:梯度累积 / 减小 micro-batch、激活重计算、序列并行)。两者手段不可互换——分片对激活无效。(✓ / △ / ×)

A2. 「三堵墙」各是什么?给出每堵墙的判据、症状与首选处方。

解答

显存墙:Mstate+Mact+Mcomm>McapM_{\text{state}}+M_{\text{act}}+M_{\text{comm}}\gt M_{\text{cap}},症状 OOM / 被迫缩批 → 分片、切层、省(定义 9.1.2);算力墙:单步时间远大于 C/FC/F 且 GPU 利用率高 → 提吞吐(FP8、更大批);通信墙:tcomm≈tcomputet_{\text{comm}}\approx t_{\text{compute}},症状是利用率忽高忽低、扩展效率随卡数下降 → 重叠、换拓扑、降并行度。三者联动:为了绕开显存墙而切分,立刻制造通信墙。(✓ / △ / ×)

A3. 写出加速比与扩展效率的定义,并说明为什么验收不能用总吞吐。

解答

S=t1/tkS=t_1/t_k,E=S/kE=S/k(tkt_k 是同样全局批下 kk 卡的耗时);E=0.5E=0.5 意味着「一半的卡在等通信或空转」(定义 9.1.3)。卡数翻倍而每卡吞吐减半时,总吞吐没变、成本翻倍——所以看 EE 且必须同全局批比较。(✓ / △ / ×)

A4. 写出数据并行(DP / DDP)的三步流程,并说出它的两条主要代价。

解答

① 每卡用自己的数据分片前向 + 反向得局部梯度 gi\boldsymbol g_i;② All-Reduce 求跨卡平均 gˉ=1k∑igi\bar{\boldsymbol g}=\frac1k\sum_i\boldsymbol g_i;③ 每卡用同一个 gˉ\bar{\boldsymbol g} 更新自己那份参数(故各副本每步末完全一致,数学上等价于批 kBkB 的单卡训练)(定义 9.2.1)。两条代价:显存冗余(每卡一份 16N16N,共浪费 (k−1)×16N(k-1)\times16N)与每步同步(≈2S\approx2S,且与批无关)。(✓ / △ / ×)

A5. 写出梯度累积与等效批大小的定义,并说明它「省什么、不省什么」。

解答

把大 batch 拆成 KK 个 micro-batch 依次前向/反向并累加梯度,攒满 KK 个再更新一次;Bglobal=K×Bmicro×kB_{\text{global}}=K\times B_{\text{micro}}\times k,为保持梯度尺度需把每个 micro-batch 的损失乘 1/K1/K(定义 9.2.2)。省激活(任意时刻只有一份 micro-batch 的激活);不省模型状态;不增通信(整批只同步一次,通信占比反而降约 KK 倍)。代价是单步墙钟变长、算子变小 → 算力利用率下降。(✓ / △ / ×)

A6. ZeRO 三个阶段各分片什么?每卡模型状态是多少?通信怎么变?

解答

按粒度递进(定义 9.2.3):ZeRO-1 分优化器状态与主权重 → 4N+12N/k4N+12N/k,通信不变(仍 All-Reduce);ZeRO-2 再分梯度 → 2N+2N/k+12N/k2N+2N/k+12N/k,因每卡只需自己那 1/k1/k 份 → 用 reduce-scatter 替代 All-Reduce,通信约减半;ZeRO-3 再分参数 → 16N/k16N/k,额外每层 all-gather 参数 → 通信升至约 1.5 倍。8 卡 7B:112→38.5→26.25→14112\to38.5\to26.25\to14 GB。(✓ / △ / ×)

A7. FSDP 的核心循环是什么?它与 ZeRO-3 是什么关系?

解答

按需聚齐、用完即散:参数 / 梯度 / 优化器状态都以分片常在(16N/k16N/k);前向进入第 ll 层前 all-gather 该层参数 → 算 → 立即释放;反向再 all-gather → 算梯度 → reduce-scatter(每卡只留 1/k1/k);现代实现会预取下一层参数把 all-gather 藏进计算(定义 9.2.4)。FSDP = ZeRO-3 语义在 PyTorch 原生实现里的落地(FSDP2 改为逐参数 DTensor 分片,2024 年起,无对应论文)。(✓ / △ / ×)

A8. 写出五个集合通信原语的每卡发送量(kk 较大时)与它们在训练里的用途。

解答

Broadcast ≈S\approx S(初始化 / 同步超参);Reduce ≈S\approx S(中心化聚合);All-Reduce ≈2S\approx2S(DDP 梯度同步);Reduce-Scatter ≈S\approx S(ZeRO-2/3 与 FSDP 的梯度归约);All-Gather ≈S\approx S(FSDP 聚合参数、序列并行重排);All-to-All ≈S(k−1)/k\approx S(k-1)/k(专家并行、Ulysses 换头);P2P =S=S(流水线段边界)。两条恒等式:All-Reduce ≈ Reduce-Scatter + All-Gather(定义 9.6.1)。(✓ / △ / ×)

A9. 5D 并行是哪五个轴?各切什么、通信特征如何、常用取值多少?

解答

DP(切数据,每步一次大 All-Reduce,最外层尽量大);TP(切层内权重与激活,每层若干次 All-Reduce、延迟敏感,≤\le 单机 GPU 数,常 4 或 8);PP(切层,段间 P2P、量小,2–16 且 M≥M\ge 若干倍 PP);EP(MoE 专家,All-to-All);CP/SP(序列维激活与 KV,环状或 all-to-all)(定义 9.6.2)。配平四原则:最密集的通信放最快链路、最少的放最外层、乘积等于总卡数、每轴守住整除约束。(✓ / △ / ×)

B. 结论卡

B1. 为什么梯度 All-Reduce 的通信量与批大小无关?这条结论有什么实际用途?

解答

通信对象是梯度张量,其形状只由模型结构决定;批大小决定的是「算出这个梯度花了多少矩阵乘」,因此批影响计算 / 通信比而非通信量(结论 9.2.1)。用途:加卡会让通信量略微增大(2S(k−1)/k→2S2S(k-1)/k\to2S)而计算按卡数摊薄 → 「卡越多、每卡计算越少、通信占比越高」;从而推出「小卡数 × 大批 × 长序列」的偏好,以及「每卡 token 太少时通信占比失控」。(✓ / △ / ×)

B2. 为什么 ZeRO-2 的通信量比基线减半,而 ZeRO-3 反而增加?

解答

基线要让每张卡都拿到完整的平均梯度,所以必须「归约 + 广播」两遍(≈2S\approx2S);ZeRO-2 中每卡只需要自己那 1/k1/k 份梯度,于是用只做归约的 reduce-scatter(≈S\approx S)替代 All-Reduce。ZeRO-3 额外需要每层参数的 all-gather(前向 + 反向各一次),这是全新的通信,净效果约 1.5×2S1.5\times2S。(✓ / △ / ×)

B3. 什么时候「分片反而更慢」?给出四条判据。

解答

① kk 很小(2–4 卡):省下的显存有限,却引入归约路径与每层 all-gather 的固定延迟;② 模型本来放得下(16N<Mcap16N\lt M_{\text{cap}}):平白多出通信,小模型上通信占比极高;③ 跨机且消息小:每层参数分片后碎成很多小消息,受延迟支配(看 profiler 里通信内核次数是否暴涨);④ 序列短、批小:计算量本来就小,通信无法被摊薄(方法 9.2.2)。(✓ / △ / ×)

B4. 为什么张量并行里「列切」与「行切」必须成对出现?

解答

列切免通信但把分片留在输出;行切把分片留在输入,必须求和才能拼回完整。若两层都列切:第二层需要完整输入却拿到分片 → 必须先 all-gather,通信不省;若两层都行切:每层后都要归约 → 通信翻倍。因此「列切 → 逐元素激活 → 行切」是唯一能做到每块一次归约的组合(前向 1 次、反向对称 1 次,与 kk 无关)(结论 9.3.1)。(✓ / △ / ×)

B5. 为什么张量并行通常必须限制在单机(NVLink)之内?给出两条理由。

解答

① 频次:TP 每层 2 个通信点,32 层就是 64 次/步,而 DP 每步只有 1 次 → 延迟而非带宽成为瓶颈,必须低延迟链路;② 消息大小:TP 的消息是单层输出(数十 MB),小消息对带宽利用率差、对往返延迟更敏感,跨机固定开销会吃掉收益(例 9.3.1)。按「对链路要求由高到低」排序是 TP > DP > PP。(✓ / △ / ×)

B6. 1F1B 调度改变了什么、没改变什么?

解答

不改变气泡公式(气泡总量在朴素口径下不变)。改变的是:GPipe 要把全部 MM 个 micro-batch 的激活留到各自反向开始(峰值 ∝M\propto M);1F1B 在预热后交替执行一前一后,反向一完成就释放激活,同时驻留约 PP 份;前反向交错还让通信更容易与计算重叠(9.4.4)。所以它改善的是「同样的卡数能塞下多大的 micro-batch / 多少个 micro-batch」。(✓ / △ / ×)

B7. 为什么「开混合精度就能省一半静态显存」是错的?

解答

混合精度把参数与梯度从 4N+4N4N+4N 压到 2N+2N2N+2N,但低精度参数上做小步更新会被舍入吃掉,必须另存 fp32 主权重 4N4N → 正好抵消,静态账仍是 16N16N(例 9.5.1)。它真正的红利是算力吞吐(16 位张量核心)与激活 / 临时张量(bf16 存储减半)。要动静态账必须动优化器状态:8-bit 优化器 16N→10N16N\to10N。(✓ / △ / ×)

B8. 为什么说万卡规模下「故障是常态」而不是意外?写出推导思路与量级。

解答

λsys≈\lambda_{\text{sys}}\approx 各组件故障率之和 ≈Gλ\approx G\lambda,任一失效即中断,故 MTBF ≈1/(Gλ)\approx1/(G\lambda)——随组件数线性缩短。取 λ≈3×10−6\lambda\approx3\times10^{-6}/小时:8 卡 ≈4.2×104\approx4.2\times10^4 小时;512 卡 ≈650\approx650 小时;8192 卡 ≈41\approx41 小时;16384 卡 ≈20\approx20 小时。而训练时长不变(数周到数月)→ 「每天都坏」是统计必然,容错因此是与吞吐并列的设计目标(9.6.4)。(✓ / △ / ×)

C. 公式卡

C1. 写出混合精度 Adam 的 16N16N 逐项账,并给出三种口径的组成差异。

解答

参数 2N2N + 梯度 2N2N + mm 4N4N + vv 4N4N + 主权重 4N4N = 16N\mathbf{16N} 字节(方法 9.1.1)。口径对照:纯 fp32 Adam =4N+4N+8N=16N=4N+4N+8N=16N(无独立主权重);混合精度 Adam =2N+2N+8N+4N=16N=2N+2N+8N+4N=16N;混合精度 + 8-bit 优化器 =2N+2N+2N+4N=10N=2N+2N+2N+4N=10N。7B:14+14+28+28+28=11214+14+28+28+28=112 GB;8-bit 时 7070 GB(省 37.5%)。(✓ / △ / ×)

C2. 写出环状 All-Reduce 的每卡通信量,并算出 7B、bf16、k=8k=8 时的流量与 IB / NVLink 时间。

解答

V=2×k−1kS→2SV=2\times\frac{k-1}{k}S\to2S(kk 大时):第一阶段 reduce-scatter 走 k−1k-1 步、每步 S/kS/k;第二阶段 all-gather 同样 S(k−1)/kS(k-1)/k;SS 是被归约张量的字节数(结论 9.2.1)。代入 S=2N=14S=2N=14 GB:V=2×78×14=24.5V=2\times\frac78\times14=24.5 GB/卡 → IB(50 GB/s)≈0.49\approx0.49 s、NVLink(300 GB/s)≈0.08\approx0.08 s(乐观下界)。ZeRO-2 用 reduce-scatter:12.2512.25 GB → 0.250.25 s。(✓ / △ / ×)

C3. 写出气泡占比公式,并算出 P=8,M=16P=8,M=16 与 M=64M=64;气泡 ≤10% 需要多大的 MM?

解答

bubble=P−1M+P−1\text{bubble}=\dfrac{P-1}{M+P-1}(结论 9.4.1)。P=8,M=16P=8,M=16:7/23=30.4%7/23=30.4\%(利用率 69.6%);M=64M=64:7/71=9.9%7/71=9.9\%。10% 条件 7M+7≤0.1⇒M≥63≈9P\frac{7}{M+7}\le0.1\Rightarrow M\ge63\approx9P。极限:M→∞M\to\infty 气泡→0;M≪PM\ll P 气泡→P−1P≈1\frac{P-1}{P}\approx1。(✓ / △ / ×)

C4. 写出「列切 → 逐元素激活 → 行切」一个块的通信点数量与每次消息大小(h=4096h=4096、B=4B=4、T=2048T=2048、bf16)。

解答

每块前向 1 次 All-Reduce、反向对称 1 次,与 kk 无关。消息是行并行层的输出,形状 B×T×hB\times T\times h:S=4×2048×4096×2=6.7×107S=4\times2048\times4096\times2=6.7\times10^7 B ≈67\approx67 MB;每卡每次 V=2×k−1kSV=2\times\frac{k-1}{k}S(k=8k=8 时 ≈117\approx117 MB)。每层前向 2 个通信点(注意力输出投影 + FFN 的 W2W_2)→ ≈234\approx234 MB;32 层每步 ≈22\approx22 GB/卡(例 9.3.1)。(✓ / △ / ×)

C5. 写出等效批大小的公式(含流水线的 MM),并说明「配置前为什么要核对框架的记账方式」。

解答

Bglobal=K×M×Bmicro×kB_{\text{global}}=K\times M\times B_{\text{micro}}\times k(方法 9.4.2):KK 梯度累积步数、MM 流水线 micro-batch 数、kk 数据并行度。注意:流水线的 MM 是对已分到本卡的小批再切分,一般不改变本卡样本总数;只有把「PP 段各过一遍」算作 PMPM 个样本的记账方式(GPipe 论文口径)才会多出 PP 因子——配错会让学习率缩放算错(正文标「需核实」)。(✓ / △ / ×)

C6. 写出 ZeRO 三级「每卡模型状态」的公式与 8 卡 7B 的数值。

解答

ZeRO-1:4N+12N/k4N+12N/k → 28+10.5=38.528+10.5=38.5 GB;ZeRO-2:2N+2N/k+12N/k2N+2N/k+12N/k → 14+1.75+10.5=26.2514+1.75+10.5=26.25 GB;ZeRO-3:16N/k16N/k → 1414 GB(例 9.2.3)。其中 12N12N 是优化器相关(m,vm,v 各 4N4N + 主权重 4N4N)。配通信读法:不变 / 减半 / 约 1.5 倍。(✓ / △ / ×)

C7. 写出三种重算口径下「每 token 每层」的激活字节数,并说明它们为什么必须标「需核实」。

解答

不重算 ≈34\approx34 字节、选择性重算 ≈18\approx18 字节、全层重算 ≈2\approx2 字节(只留层输入 B×T×hB\times T\times h、2 字节/元素)(9.5.3)。三个系数高度依赖「哪些中间张量被计入」(是否重算注意力、是否实体化 softmax 矩阵、是否启用 FlashAttention),且正文的乘积与单位口径处已标「需核实」——报价必须用你自己的实现实测。(✓ / △ / ×)

C8. 写出 MTBF 与 checkpoint 最优间隔的表达式,并说明公式之外的硬约束。

解答

MTBF ≈1Gλ\approx\dfrac{1}{G\lambda};每小时额外时间 E(T)=4fT+55.8TE(T)=4fT+\dfrac{55.8}{T}(ff 次/小时,4=0.5×84=0.5\times8 分钟,55.8=60×0.9355.8=60\times0.93)→ T⋆=13.95fT^\star=\sqrt{\dfrac{13.95}{f}},f=0.5f=0.5 时 ≈5.3\approx5.3 小时(例 9.6.3)。硬约束:恢复时间必须远小于间隔、单次故障不至于丢掉太多算力;故障呈批次性时先修机器。(✓ / △ / ×)

D. 陷阱卡(每题给一个错误说法,请指出错在哪)

D1. 「开了混合精度,静态显存直接省一半。」

解答

错。省下的 4N4N 被新增的 fp32 主权重吃回去,静态仍是 16N16N(例 9.5.1)。它省的是激活与临时张量,红利在吞吐。要省静态账必须动优化器状态(8-bit 优化器 16N→10N16N\to10N)或分片。(✓ / △ / ×)

D2. 「批越大,梯度通信量越大,所以大批训练更难跨机。」

解答

错。通信量 V≈2SV\approx2S 由模型字节数决定,与批大小无关;批越大,同样的通信摊到更多计算上,通信占比更低。真正让通信占比失控的是「每卡 token 数太少」(9.2.2)。(✓ / △ / ×)

D3. 「ZeRO 阶段越高,训练越快——显存省了还能开更大的批。」

解答

错。ZeRO-1 通信不变、ZeRO-2 减半、ZeRO-3 上升到约 1.5 倍;kk 小或模型本来放得下时 ZeRO-3 反而更慢。判据:能放下就用 DP + ZeRO-1/2,放不下才上 ZeRO-3 / FSDP2(方法 9.2.2)。(✓ / △ / ×)

D4. 「张量并行度翻倍,每卡通信量就减半。」

解答

错。V=2S(k−1)/kV=2S(k-1)/k 中的 SS 是完整输出的大小,与 kk 无关,所以每卡通信量几乎不变(只缓慢趋近 2S2S);变的是「消息更小、次数更多」,延迟受限时有害。第二条约束:能靠更大批解决,就别加 TP 度(例 9.3.1 及其后陷阱框)。(✓ / △ / ×)

D5. 「1F1B 能消除气泡。」

解答

错。1F1B 改的是调度顺序与峰值显存:气泡总量在朴素口径下不变;它把峰值激活从 ∝M\propto M 降到 ∝P\propto P,并让前向通信与反向计算更容易重叠。消气泡要靠增大 MM、交错调度或 zero-bubble(方法 9.4.1)。(✓ / △ / ×)

D6. 「只要定期存 checkpoint 就不怕故障,恢复时把权重读回来就行。」

解答

错。checkpoint 只解决「丢多少进度」,不解决一致性:恢复后若数据顺序被打乱、优化器步数与学习率调度位置对不上、随机状态未还原,等于悄悄换了实验条件。必须一并恢复:分片布局、优化器步数、已消费样本数、随机状态、调度器位置(9.6.4 误解 1、6)。(✓ / △ / ×)

D7. 「QLoRA 把 7B 放进 24 GB 卡,所以 4-bit 主干的显存就是 0.5N0.5N。」

解答

错(不完整)。0.50.5 字节/参数是 NF4 单重量化的理想值,双重量化与分块缩放会引入少量额外开销(常按 0.55–0.6 字节估计,需实测);此外还有激活、KV cache、适配器、以及训练时把主干按层反量化出的临时副本(现代实现按层反量化以抑制峰值)(例 9.5.4 的两个易错点)。(✓ / △ / ×)

D8. 「推理量化(GPTQ / AWQ)也能省训练显存。」

解答

错。它们的目标是部署:把权重压到 4 bit 供推理。训练时的瓶颈是 m,vm,v 与主权重(12N12N)以及激活,都不在它们的解决范围内(定义 9.5.5、9.5.5 误解 8)。(✓ / △ / ×)

导出到 Anki / CSV

  1. 打开 Anki → 新建卡组「DL-第 9 讲」(可按四组再建子卡组:定义 / 结论 / 公式 / 陷阱);
  2. 用「问题 → 答案」逐条录入;也可在纯文本里用 Tab 分隔「正面 / 反面」后导入(正面写卡片编号与问题,反面写折叠里的答案正文,保留出处链接如 [定义 9.2.3](sec92.md#def-9.2.3));
  3. 复习节点:当天 / 隔天 / 第 3 天 / 第 7 天(与 summary.md 的复习路线 对齐);
  4. 每轮只重做标 △ 与 × 的卡;连续两轮仍 × 的条目,写进勘误与补注第四节的待核实条目单独跟踪;
  5. 公式卡建议手写(不敲键盘):16N16N、2S(k−1)/k2S(k-1)/k、P−1M+P−1\frac{P-1}{M+P-1}、4N+12N/k4N+12N/k 这四条各写三遍,面试时几乎都是从这里出题。