Chapter 12

Checkpoint:Megatron ↔ HuggingFace 互转

📌 源码引用基于 tools/checkpoint/ 、 megatron/core/dist_checkpointing/ · commit 432d76b2b8bf 。

12.1 Megatron checkpoint 长什么样

Megatron 的 checkpoint 不是单一文件,而是按并行布局切分的目录树。一个 TP=4 × PP=2 训练的 checkpoint 目录大致:

iter_0001000/
├── mp_rank_00_000/                  # TP=0, PP=0
│   └── model_optim_rng.pt
├── mp_rank_01_000/                  # TP=1, PP=0
│   └── model_optim_rng.pt
├── mp_rank_02_000/                  # TP=2, PP=0
│   └── model_optim_rng.pt
├── mp_rank_03_000/                  # TP=3, PP=0
│   └── model_optim_rng.pt
├── mp_rank_00_001/                  # TP=0, PP=1
│   └── model_optim_rng.pt
├── ... 共 4 × 2 = 8 个目录
└── latest_checkpointed_iteration.txt

每个 model_optim_rng.pt 含:

12.2 三种 checkpoint 格式

--ckpt-format说明
torch 经典格式(上面那种 mp_rank_XX_YYY 目录)
torch_dist(推荐)新版 distributed checkpoint,能在不同并行配置间互转
zarr Zarr 格式,便于云存储

torch_dist 的好处是"训练用 TP=8 PP=16,恢复用 TP=4 PP=8"完全没问题。Megatron 0.10+ 默认推荐这个。

12.3 互转的两个方向

flowchart LR HF["HuggingFace 格式
(pytorch_model-XX.bin / safetensors)"] Mcore["Megatron-Core checkpoint
(切分目录树)"] Mlm["Megatron-LM legacy checkpoint
(更旧)"] HF -->|tools/checkpoint/convert.py loader_llava/mixtral_hf...| Mcore Mcore -->|tools/checkpoint/convert.py + saver_| HF Mlm -->|tools/checkpoint/loader_legacy| Mcore Mcore -->|可选 TP/PP 改切| Mcore

核心工具是 tools/checkpoint/convert.py,它接受一对 loader(读什么格式)+ saver(写什么格式)

12.4 HF → Megatron(用 HF 模型起步训练)

常见诉求:拿 HuggingFace 上的 Llama-3-70B 当起点做继续预训练。

python tools/checkpoint/convert.py \
    --model-type GPT \
    --loader llama_mistral \
    --saver core \
    --load-dir /path/to/hf/Meta-Llama-3-70B \
    --save-dir /path/to/megatron/llama3_70b_tp8_pp4 \
    --target-tensor-parallel-size 8 \
    --target-pipeline-parallel-size 4 \
    --tokenizer-model /path/to/tokenizer.model \
    --model-size llama3-70B \
    --bf16

关键参数:

参数说明
--loader 选输入格式:llama_mistral / mixtral_hf / llava / megatron / core / legacy
--saver 选输出格式:core / megatron / llama_mistral / mixtral_hf
--load-dir 源 checkpoint 目录
--save-dir 目标目录
--target-tensor-parallel-size目标 TP 度
--target-pipeline-parallel-size目标 PP 度
--model-size 用于推断 architecture 配置(llama3-8B / llama3-70B / mistral-7B 等)

12.5 Megatron → HF(训练完导出给生态用)

python tools/checkpoint/convert.py \
    --model-type GPT \
    --loader core \
    --saver llama_mistral \
    --load-dir /path/to/megatron/output/iter_0010000 \
    --save-dir /path/to/hf/my_llama3_70b_continued \
    --target-tensor-parallel-size 1 \
    --target-pipeline-parallel-size 1 \
    --tokenizer-model /path/to/tokenizer.model

注意:

12.6 改变并行布局(Megatron → Megatron)

训练时用 TP=8 PP=16(128 卡),后续用 8 卡微调,需要 TP=4 PP=2:

python tools/checkpoint/convert.py \
    --model-type GPT \
    --loader core \
    --saver core \
    --load-dir /old/megatron/ckpt \
    --save-dir /new/megatron/ckpt \
    --target-tensor-parallel-size 4 \
    --target-pipeline-parallel-size 2

新格式 torch_dist 训练时直接换并行配置就行,不需要离线转换:

# 训练时
--ckpt-format torch_dist

# 恢复时换并行配置直接 --load 即可

12.7 dist_checkpointing:新版机制详解

megatron/core/dist_checkpointing/ 下的代码实现了"布局无关"的 checkpoint。原理:

  1. 保存时按"逻辑张量"组织(每个参数有一个全局 key),每张卡只存自己持有的切片;
  2. 所有 rank 协同写入同一 checkpoint 目录;
  3. 恢复时按当前进程的 TP/PP/DP 重新切分加载——和保存时不一致也没问题。

这种"分片但可重组"的设计让checkpoint 不再绑定具体并行布局

12.8 异步保存(H100 神器)

--ckpt-format torch_dist \
--async-save

原理:把"序列化 + 落盘" 放到后台线程,训练继续进行。能省下大型 checkpoint 的同步时间(70B 模型一次 save 同步会卡 30-60 秒)。

12.9 loader / saver 列表(按模型)

loader支持模型
core Megatron-Core 自家格式(默认)
legacy Megatron-LM 老格式
llama_mistral Llama-2/3/4 + Mistral / Yi 系
mixtral_hf Mixtral MoE
llava LLaVA 多模态

没列出的模型(如 Qwen3、DeepSeek-V3)通常用 NVIDIA-NeMo/Megatron-Bridge,那是 NV 官方做的更通用工具。

12.10 Megatron-Bridge:推荐的统一互转工具

仓库 README 顶部就推荐:

Megatron Bridge provides bidirectional Hugging Face ↔ Megatron checkpoint conversion with production-ready recipes.

用法:

pip install megatron-bridge

# HF → Megatron
python -m megatron_bridge.tools.convert_hf_to_megatron \
    --hf_model meta-llama/Llama-3-70B \
    --output ckpt/llama3_70b_mcore \
    --tp 8 --pp 4 \
    --dtype bf16

# Megatron → HF
python -m megatron_bridge.tools.convert_megatron_to_hf \
    --megatron_ckpt ckpt/llama3_70b_mcore/iter_0010000 \
    --output hf/my_llama3_70b \
    --hf_model_id meta-llama/Llama-3-70B          # 用原模型的 config 模板

Bridge 比 tools/checkpoint/convert.py 的优势:

12.11 转完之后的验证

检查 HF 格式模型转换正确性:

# 1. config.json 存在
ls path/to/hf/model/config.json

# 2. 能正常加载 + 输出和原模型相近
python -c "
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
tok = AutoTokenizer.from_pretrained('path/to/hf/model')
model = AutoModelForCausalLM.from_pretrained('path/to/hf/model', torch_dtype=torch.bfloat16).cuda()
inputs = tok('Hello world', return_tensors='pt').to('cuda')
print(model.generate(**inputs, max_new_tokens=20))
"

# 3. 数值差异检查(与原 HF 模型对比)
python tools/checkpoint/checkpoint_inspector.py \
    --check-dir path/to/megatron/ckpt

12.12 常见坑

现象原因修复
转换后的模型生成乱码 position_embedding / RoPE base 设错 检查 --rotary-base 与原模型一致
SwiGLU 参数对不上 HF 与 Megatron 的 SwiGLU gate / value 顺序不同loader 自带处理;自己写 loader 时注意 W1/W3 顺序
GQA 的 num_query_groups 设错 从原 HF config 读 num_key_value_heads
embedding tied 错误 HF tied 但 Megatron untied --untie-embeddings-and-output-weights
转完模型大一倍 多出 optimizer state 转换时不带 optim:--no-load-optim
tokenizer 不工作 没 copy tokenizer 文件 手动 copy tokenizer.model / tokenizer.json
fp8 训练的模型转回 HF 后跑不了 HF 不直接支持 fp8 scaling factor 导出时用 bf16

12.13 Async dist-checkpointing(2025-Q2 新)

megatron/core/dist_checkpointing/strategies/ 下两个新文件:

文件用途
async_utils.py asyncio 任务管理 + 完成回调
filesystem_async.py 非阻塞磁盘写(aio + 后台线程)
fully_parallel.py 所有 rank 同时写(共享 FS 上常用)
torch.py 用 torch native dist-ckpt(pytorch>=2.3)
nvrx.py NVIDIA NVRx 后端
two_stage.py "先暂存到本地 SSD 再异步上传"

启用方式:--ckpt-format torch_dist --async-save。训练循环在 save_step 立即返回,不阻塞 forward/backward;后台线程完成后再回调释放 buffer。1B+ 模型每 100 步保存一次也基本无感。

12.14 torch_dist 格式的优势

能力说明
布局无关 TP=4 PP=2 训的 ckpt 可以用 TP=2 PP=4 续训
并行 I/O 所有 rank 同时写,吞吐随 rank 数线性扩展
异步 --async-save 完全不阻塞
HF 互转 Megatron-Bridge 直接读 torch_dist 格式
压缩 / 切片 策略可插拔(见 12.13 table)

2026 新工程建议直接用 torch_dist,旧的 zarr / per-rank pickle 都进入维护状态。

12.15 这章你需要带走什么