Weak Scaling / Strong Scaling
结论
Weak scaling 和 strong scaling 是 HPC 里两种完全不同的扩容问题:
- Strong scaling:总问题规模固定,加机器,看单步时间能不能同比下降。
- Weak scaling:每台机器的问题规模固定,加机器则总问题规模一起变大,看单步时间能不能保持不变。
搬到 LLM 训练上,“问题规模”就是 global batch size,“每台机器的问题规模”就是每个 rank 的 microbatch token 数 $T$。于是两条路各撞一面墙:
- 固定 global batch 加卡(strong scaling)撞的是系统墙。$T$ 随卡数下降,掉到 $T_{crit}$ 以下之后 FSDP 通信无法被计算掩盖,GEMM 变小,MoE 每个 expert 分不到足够 token,pipeline 气泡占比上升。
- **固定每卡 token 数加卡(weak scaling)撞的是算法墙。**global batch 随卡数线性增大,超过 critical batch size 之后,固定 token 预算下 optimizer step 数不足,token efficiency 下降。
- **大规模训练几乎总是先 weak scale、再被迫 strong scale。**一旦 global batch 顶到当前阶段的 critical batch,继续加卡只能是 strong scaling,$T$ 下降不可避免,剩下能做的只有把 $T_{crit}$ 降下来。
一句话概括:weak scaling 的效率数字很容易做得好看,但它是拿算法预算换来的;真正难的是 strong scaling,而 strong scaling 的上限由 $T_{crit}$ 决定。
HPC 的原始定义
设总计算量为 $W$,处理器数为 $N$。
Strong Scaling 与 Amdahl 定律
$W$ 固定。若其中比例 $f$ 的工作无法并行:
$$ t(N)=f\,t(1)+\frac{(1-f)\,t(1)}{N}, \qquad S(N)=\frac{1}{f+\dfrac{1-f}{N}}. $$$N\to\infty$ 时 $S\to 1/f$。串行部分只占 5%,加速比上限就是 20 倍,跟买多少卡无关。
Weak Scaling 与 Gustafson 定律
每个处理器的工作量固定,$W\propto N$。此时
$$ S(N)=f+(1-f)N, $$加速比随 $N$ 线性增长。看起来漂亮,但它衡量的是“同样时间能算多大的问题”,不是“同一个问题能算多快”。
|
|
映射到 LLM 训练
沿用 Global Batch Size 的记号:
$$ B_{\mathrm{global}} =T_{\mathrm{micro/rank}}\times D_{\mathrm{DP}}\times A . $$这个等式里三个量,固定哪一个就决定了在做哪种 scaling:
| 固定量 | 加卡后的变化 | 主要风险 | |
|---|---|---|---|
| Strong scaling | $B_{\mathrm{global}}$ | $T_{\mathrm{micro/rank}}$ 下降 | 通信暴露、kernel 变小、气泡变大 |
| Weak scaling | $T_{\mathrm{micro/rank}}$ | $B_{\mathrm{global}}$ 上升 | 超过 critical batch,token efficiency 下降 |
需要注意的是,并行维度本身就带有 scaling 属性:
|
|
TP、CP、PP、EP 都属于“让更多卡共同处理同一批 token”,天然是 strong scaling 的手段;只有增大 $D_{\mathrm{DP}}$ 并保持 $T$ 才是 weak scaling。这也解释了一个常见现象:把 TP 从 4 开到 8,MFU 往往下降,因为它是在做 strong scaling,每卡的 GEMM 形状被切小了。
Strong Scaling 的实际衰减
把单步时间拆成随卡数下降的部分和不下降的部分:
$$ t_{\mathrm{step}}(N) \approx \underbrace{\frac{C}{N F_{\mathrm{eff}}}}_{\text{计算}} +\underbrace{t_{\mathrm{exposed}}(N)}_{\text{暴露通信 + 气泡 + optimizer}} . $$固定 $B_{\mathrm{global}}$ 时,$C$ 是常数,第一项按 $1/N$ 缩小;而 $t_{\mathrm{exposed}}$ 不但不缩小,还会因为每卡计算窗口变短而变大。
以 FSDP 计算通信 overlap 里的 dense 模型阈值 $T_{crit}\approx 3.7$k tokens/GPU 为例,假设 $B_{\mathrm{global}}=32$M tokens、$A=1$、纯 DP:
| GPU 数 | 每卡 token 数 | 计算 (ms) | 暴露部分 (ms) | Step time (ms) | 理想 step time (ms) | 并行效率 | 吞吐 (M tok/s) |
|---|---|---|---|---|---|---|---|
| 1,024 | 32k | 900 | 100 | 1,000 | 1,000 | 100% | 32 |
| 4,096 | 8k | 225 | 150 | 375 | 250 | 67% | 85 |
| 8,192 | 4k | 113 | 220 | 332 | 125 | 38% | 96 |
| 16,384 | 2k | 56 | 300 | 356 | 63 | 18% | 90 |
$T$ 掉到 $T_{crit}$ 附近时(8,192 卡),暴露时间已经超过计算时间;再加一倍卡(16,384 卡),吞吐反而从 96M 降到 90M。这就是 strong scaling 的典型形态:存在一个卡数拐点,越过之后加卡是负收益。
拐点位置基本由 $T_{crit}$ 决定。$B_{\mathrm{global}}$ 固定时,可用卡数上限约为
$$ N_{\max}\approx\frac{B_{\mathrm{global}}}{T_{crit}} . $$$B_{\mathrm{global}}=32$M、$T_{crit}=3.7$k 对应约 8.6k 卡,和上表的拐点一致。
Weak Scaling 的假效率
同样从 1,024 卡扩到 4,096 卡,但保持每卡 32k tokens:
| GPU 数 | 每卡 token 数 | Global batch | Step time (ms) | Weak scaling 效率 | 吞吐 (M tok/s) |
|---|---|---|---|---|---|
| 1,024 | 32k | 32M | 1,000 | 100% | 32 |
| 4,096 | 32k | 128M | 1,050 | 95% | 122 |
系统指标非常好:效率 95%,吞吐接近线性。问题在于 global batch 变成了 128M,远超目前公开旗舰模型的量级(见 Global Batch Size 的横向对比)。同样的 1T token 预算下:
$$ \frac{10^{12}}{32\times10^{6}}\approx 31\text{k steps} \;\longrightarrow\; \frac{10^{12}}{128\times10^{6}}\approx 7.8\text{k steps}. $$参数更新次数只剩四分之一,达到相同 loss 需要的 token 会更多。weak scaling 效率高不代表 time-to-quality 更好,只报告 tokens/s 或 MFU 时,这种退化完全看不出来。
这也是 MLPerf Training 用“训练到固定目标质量的时间”而不是吞吐作为指标的原因:一旦指标是 time-to-quality,靠放大 batch 换吞吐的做法就不再有收益。
和 Scaling Law 的区别
两个词长得像,讨论的完全是两件事:
| 自变量 | 因变量 | 关心什么 | |
|---|---|---|---|
| Scaling Law | 参数量、训练 token 数、算力预算 | validation loss | 给定算力怎么分配模型和数据 |
| Weak / Strong Scaling | 并行规模(GPU 数) | step time、吞吐 | 同一份工作能不能算得更快 |
两者唯一的交点是 critical batch size:它同时是 scaling law 侧的算法约束和 weak scaling 侧的扩容上限。
怎么把 Strong Scaling 的墙往后推
global batch 顶到 critical batch 之后,加卡只能 strong scale,$T$ 一定会降。能做的只有降低 $T_{crit}=\dfrac{F_{\mathrm{eff}}}{B_{\mathrm{eff}}}\cdot\dfrac{P}{P_a}$:
| 方向 | 做法 | 效果 |
|---|---|---|
| 提高 $B_{\mathrm{eff}}$ | 把 FSDP group 收进 NVLink 域、层次化 AllGather、IB 转 NVLink | 分母变大 |
| 降低 $P/P_a$ | 用 EP 搬 token 替代 FSDP 搬 expert 权重 | 稀疏 MoE 上收益最大 |
| 减少通信次数 | reshard_after_forward=False,或让参数跨多个 accumulation microbatch 保持 unshard |
用显存换通信 |
| 减少通信字节 | FP8 / BF16 参数通信,把 $s_w$ 减半 | 等价于 $B_{\mathrm{eff}}$ 翻倍 |
| 换气泡换通信 | 调整 PP schedule、增大 in-flight microbatch 数 | 降低 $t_{\mathrm{exposed}}$ 里的气泡项 |
注意最后两行是有代价的:它们都在拿峰值显存换通信,而 strong scaling 的一个副作用恰好是每卡激活显存随 $T$ 下降而变小,正好腾出空间。这两件事应该一起考虑,而不是分开调。
报告扩容结果时应该说清楚的事
一条“我们扩到 N 卡,效率 90%”的结论,不说明下面四点是没有信息量的:
- 固定的是 $B_{\mathrm{global}}$ 还是 $T_{\mathrm{micro/rank}}$,即到底在做哪种 scaling。
- baseline 卡数是多少,效率是相对谁算的。加卡区间从 1k 到 2k 和从 8k 到 16k 完全不是一回事。
- 并行配置有没有变。若同时改了 TP/PP/EP degree,那已经不是纯粹的 strong 或 weak scaling。
- 有没有 validation loss–token 曲线。只有吞吐和 MFU 时,weak scaling 的算法代价被完全隐藏了。
一句话总结:strong scaling 问的是“这一批 token 能不能算得更快”,weak scaling 问的是“同样时间能不能吞更多 token”。训练系统的真实约束是先用 critical batch size 定住 weak scaling 的上限,再用 $T_{crit}$ 定住 strong scaling 的拐点,两者共同决定一个模型最多值得用多少张卡。
Author Houmin Wei
Publish January 1, 0001
LastMod August 27, 2026
License 本作品采用 CC BY-NC-ND 4.0 许可协议进行许可,转载时请注明原文链接
如果你在浏览博客的过程中发现了任何问题,欢迎在对应文章下评论。如果你有其他事情想要咨询,可以通过邮件联系我。