卡数、显存与并行方式#

在交互实验室的「布局」步骤中逐个点击图示。先确认各阶段能放下且学习正确,再优化每秒有效样本数。

从多少张卡起步?#

实验室按每节点 8 GPU,参考 H100/H200 级别、高速互联服务器的仓库配方。这些是配方起步值,不是实测最小值,也不保证这一档所有硬件均能直接运行。模型配方默认回复上限为 131,072 tokens(128K),GLM-5.3 为 262,144(256K),均启用 CP,每轮 8 个 prompt、各采样 8 次;prompt 长度仍计入显存。MoE 和 Qwen 默认启用 CPU Adam 与重计算。

模型

训练卡数

TP / PP / CP / EP

每个推理引擎卡数

来源

GLM-4.7-Flash

8

2 / 1 / 4 / 8

8

Flash

GLM-4.7

64

8 / 4 / 2 / 16

32

355B

GLM-5.3

256

4 / 8 / 8 / 32

64

744B

Qwen3.8-27B

32

4 / 2 / 4 / 1

2

匹配的架构

Flash 使用 TP2 / CP4 / EP8 和单流水线阶段,将 128K 序列分散到更多卡上。导出的配方启用 --log-probs-chunk-size 1024,降低 log-prob 与 SC 计算的临时显存。Qwen3.8 复用匹配架构配置,此次文档修改尚未对新 checkpoint 做 GPU 验证。第一次建议用 9B 或 Flash 理解循环,再对目标模型做短实验,测量峰值显存后分配长任务资源。

同卡训推分配一个池;训推分离需训练卡数加 rollout 卡数。PD 将 rollout 池分为完整 prefill/decode 引擎;外部推理资源不计入训练 Ray 集群。只增加卡数而不调整模型并行,可能只是增加副本,并不减少每卡模型显存。

显存账本#

以一种混合精度 Adam 为例,\(P\) 个参数的 BF16 权重占 \(2P\) 字节、FP32 梯度 \(4P\)、FP32 master weights \(4P\)、两份 FP32 moments \(8P\):

\[M_{\rm states}=(2+4+4+8)P=18P\ \text{bytes}.\]

实际 precision-aware 优化器的状态精度可能不同。激活、buffers、临时转换、分配器预留、reference policy 副本、KV cache 还要另算。30B 的 BF16 权重约 60 GB,两份 FP32 moments 约 240 GB,尚未分片。MoE 存储要看总参数量,不能只看激活参数量。

        flowchart TB
    T[训练显存] --> W[权重 + 梯度]
    T --> O[优化器状态]
    T --> A[保存的激活]
    T --> B[Buffers + 临时分配]
    O --> C[CPU Adam:主机存储和计算]
    A --> R[重计算:少保存,再算一次]
    S[推理显存] --> SW[权重]
    S --> KV[KV cache + workspace]
    

理想的阶段 offload 使同卡显存需求接近 \(\max(M_{\rm train},M_{\rm rollout})\),还需考虑常驻 buffers 与切换开销。分离布局则分别满足两个池的容量约束。

TP:拆一个层#

按矩阵列拆分:

\[W=[W_0\;W_1],\qquad Y=XW=[XW_0\;XW_1].\]

各卡计算一片;后续按输入行拆分的层计算 \(Z=Y_0V_0+Y_1V_1\),需要归约各卡的部分输出。这解释了显存节省和频繁通信的来源,TP 应优先放在高速互联内。Sequence parallelism 还拆分部分激活操作,不能替代 CP。见 Megatron 论文和并行指南。

PP:拆模型层#

        flowchart LR
    A[前面的层] -->|激活| B[中间的层]
    B -->|激活| C[后面的层]
    C -->|梯度| B
    B -->|梯度| A
    

每个 stage 只保存自己的层。假设 \(p\) 个等耗时阶段、\(m\) 个 microbatch、每阶段耗时 \(\tau\),简单 forward 流水线耗时 \((m+p-1)\tau\)。利用率为 \(m/(m+p-1)\),填充与排空的 bubble 比例为 \((p-1)/(m+p-1)\)。实际训练还受 backward 调度、通信与分层不均衡影响。增加 microbatch 数能摊薄 bubble,但每个 microbatch 仍要放得下。见 Megatron 论文。

EP:拆 MoE 专家#

对选中的专家集合 \(K(x)\):

\[y(x)=\sum_{e\in K(x)}g_e(x)E_e(x).\]

不同 GPU 保存不同专家。All-to-all dispatch 把 token 送到专家所在卡,combine 返回加权输出。权重均匀分片不代表 token 流量均匀,专家负载倾斜可能成为瓶颈。见 GShard。

Dense 层常用卡数关系为 \(N=TP\cdot PP\cdot CP\cdot DP\)。专家层有另一套含 expert TP、expert DP 的分组,不能在 dense 关系上再乘 EP。本实验室使用 expert TP=1,检查卡数能被 \(TP\cdot PP\cdot CP\) 和 \(EP\cdot PP\) 整除;模型维度与 Megatron 还会带来其他约束。

CP:拆 token#

CP 按 token 位置分配 queries;attention 仍需远端 keys/values,因此引入通信。它减少本地序列激活,不会自动拆模型权重。

单条 8-token 序列、CP2

Rank 0

Rank 1

默认 zigzag

0、1、6、7

2、3、4、5

slime allgather CP

0、1、2、3

4、5、6、7

Zigzag 将每条补齐后的序列切为 \(2c\) 块,rank \(r\) 得到第 \(r\) 与 \(2c-r-1\) 块。前后配对平衡 causal attention:8 个位置连续切分时两卡分别处理 10、26 个 query-key 对,图中的 zigzag 各处理 18 对。这是配对数,不是 sparse kernel 真实耗时。

slime 的 --allgather-cp 打包序列,将补齐后的整体 token 流连续切分。DSA backend 收集所需远端 attention/index 数据,loss 处理再恢复样本归属。它不同于 zigzag 逐序列切分;不兼容的 backend 上误开 flag 会打乱 token 顺序。

        flowchart LR
    A[Rank 0 本地 queries] --> C[对所需 keys 做 attention]
    B[Rank 1 keys / values] -->|backend 通信| C
    C --> D[Rank 0 本地输出]
    

Zigzag 描述布局,不等同于某一个固定 ring 算法;通信由 attention backend 决定。Allgather 可能产生较大聚合张量,所以 CP 不会将每类内存等比例缩小。

CP > 1 时,slime 当前只允许 DeepseekV32ForCausalLM 和 GlmMoeDsaForCausalLM 使用 allgather CP。实验室的 GLM-5.3 通过模型配置启用它,其他配方保持支持的布局。图示按钮不修改运行 flag。见参数校验、打包、CP 索引和 Megatron 指南。

ZeRO 与 distributed optimizer#

数据并行副本处理不同样本。ZeRO 依次分片优化器状态(stage 1)、梯度(stage 2)、参数(stage 3)。沿用每参数 18 字节示例,\(D\) 个副本上的理想持久状态开销为:

\[M_0=18P,\quad M_1=6P+12P/D,\quad M_2=2P+16P/D,\quad M_3=18P/D.\]

推导即先将 master weights 和 moments 除以 \(D\),再依次将梯度、BF16 权重除以 \(D\);未计临时通信 buffers。\(P\) 可以是本地模型并行分片,\(D\) 是对应副本数;专家参数分组可能不同。见 ZeRO。

slime 默认启用 Megatron use_distributed_optimizer,分片优化器状态与更新计算,再聚合更新后的参数。这不等于完整 ZeRO-3 参数分片,也不表示使用 DeepSpeed runtime。见后端默认参数。

CPU Adam 与重计算#

Adam 保存 moments 并做偏差修正:

\[m_t=\beta_1m_{t-1}+(1-\beta_1)g_t,\quad v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2,\]
\[\hat m_t=m_t/(1-\beta_1^t),\quad\hat v_t=v_t/(1-\beta_2^t),\quad\theta_{t+1}=\theta_t-\eta\hat m_t/(\sqrt{\hat v_t}+\epsilon).\]

CPU Adam 在主机保存优化器状态并执行更新。开关导出 --optimizer-cpu-offload、--overlap-cpu-optimizer-d2h-h2d 和 --use-precision-aware-optimizer。分片决定哪个 rank 负责状态;offload 决定该 rank 在哪里保存和更新状态。主机内存、CPU 算力和 PCIe 带宽接过一部分显存负担,激活与 KV cache 不受影响。背景见 Adam、ZeRO-Offload,slime 使用 Megatron 实现。

独立的重计算开关保存边界,在 backward 时重做部分 forward,以 FLOPs 换激活显存,见激活 checkpointing。训练 OOM 先判断状态还是激活占主导,再选 offload、更多模型并行或更小的 token microbatch。推理 OOM 则检查权重、KV 精度、并发、回复长度和引擎卡数。通过 profiling逐项测量。