Feat/checkpoint resharding - #196
JYMiracle305 wants to merge 3 commits into
Conversation
5153a9e to
a3f6181
Compare
57ab888 to
7689011
Compare
e0540b5 to
c85e813
Compare
c85e813 to
7028203
Compare
5514a0b to
cf3cce5
Compare
7028203 to
8e4012b
Compare
8e4012b to
83a73ee
Compare
59a9674 to
9d99035
Compare
83a73ee to
57bc905
Compare
9d99035 to
862a378
Compare
862a378 to
f6f4715
Compare
57bc905 to
9928ff2
Compare
f6f4715 to
9d30401
Compare
845f617 to
8ba9890
Compare
9d30401 to
6799ce4
Compare
d64951e to
770fc02
Compare
6799ce4 to
9d406c9
Compare
9d406c9 to
86aefcd
Compare
770fc02 to
8a3ddc2
Compare
86aefcd to
48ca7e4
Compare
8a3ddc2 to
340c458
Compare
340c458 to
32b6d48
Compare
32b6d48 to
fb9fc5f
Compare
8323452 to
b66c25c
Compare
b66c25c to
82a301e
Compare
fb9fc5f to
31e9655
Compare
31e9655 to
40e28ec
Compare
7f25f0a to
3328359
Compare
4f610e7 to
df1c7e3
Compare
| nn::parallel::function::AllReduce(token, nn::parallel::function::ReduceOpType::kSum, nullptr, true)->Synchronize(); | ||
| } | ||
|
|
||
| void WaitForWriterManifests(const std::filesystem::path &staging_root, int tp_size, int pp_size, |
There was a problem hiding this comment.
这里在一直轮询所有 metadata.json,但进程同步语义不应该绑定到文件是否出现上。我看已经有SynchronizeCheckpointRanks 函数了,应该可以通过改造复用来实现更可靠的判断。
| obj_pos = obj_end + 1; | ||
| } | ||
|
|
||
| LOG(INFO) << "[CKPT] Loaded metadata.json: " << meta.tensors.size() << " tensors, iteration=" << meta.iteration; |
There was a problem hiding this comment.
这里如果继续用轮询检测 metadata file 的话可能有刷屏风险。
| } | ||
| } | ||
|
|
||
| Checkpoint::Load(resume_dir, *args.model, args.optimizer.get(), args.state, args.lr_scheduler.get()); |
There was a problem hiding this comment.
Checkpoint::Save 和 Checkpoint::Load 没有地方使用了,相应函数和测试都可以删掉。
| class SavePlanner { | ||
| public: |
There was a problem hiding this comment.
只有一个 static 方法,不需要套一个 class 吧。
| WriteItem item; | ||
| item.key = key; | ||
| item.filename = is_optimizer ? "optimizer.ckpt" : "model.ckpt"; | ||
| item.offset = offset; |
There was a problem hiding this comment.
这个字段不需要吧,真正用的是 storage.data_offset
| } | ||
| } | ||
| if (!filtered_sd.empty()) { | ||
| model_file_index = SaveStateDict(checkpoint_dir / "model.ckpt", filtered_sd); |
There was a problem hiding this comment.
建议把 model.ckpt、optimizer.ckpt、metadata.json 等字符串都提出为常量,不要在各个地方硬编码。
| for (auto &[name, parameter] : parameters) { | ||
| name = RemapLayerKey(name, local_layers, global_layers); | ||
| if (!sharded_state.tensors.contains(name)) { | ||
| continue; |
There was a problem hiding this comment.
这里应该 CHECK 或 LOG(WARNING),tensors 不在 ShardedStateDict 里是不正常的。
| #include <unordered_set> | ||
| #include <vector> | ||
|
|
||
| #include "infini_train/include/checkpoint/shard_spec.h" |
There was a problem hiding this comment.
nn 是基础设施,checkpoint 是上层功能,nn 层不应该依赖 checkpoint 层。PyTorch 里也是 DCP 依赖 nn.Module,不是反过来。建议把 shard 描述类型下沉到基础层(infini_train/include/shard_spec.h,namespace infini_train),或让 nn 层只暴露一个不含 checkpoint 语义的轻量结构。
|
|
||
| #include "infini_train/include/nn/functional.h" | ||
| #include "infini_train/include/nn/init.h" | ||
| #include "infini_train/include/nn/lora/lora_parallel_linear.h" |
There was a problem hiding this comment.
Transformer 层不应该 include lora 层,这里引用是为了拿 kParamLoraBName ,应该在 LoRAColumnParallelLinear::ShardedStateDict 里完成。
| emitted_items.push_back(&item); | ||
| } | ||
| } | ||
| int dp_rank = 0, tp_rank = 0, pp_rank = 0; |
There was a problem hiding this comment.
我们现在都是硬编码dp_rank = 0,但 Megatron / PyTorch 是 replica_id 挂在 ShardedTensor 上,由数据自己决定谁写,这里可以加个TODO。
|
|
||
| checkpoint::ShardedStateDict global_state; | ||
| for (auto &[local_key, tensor] : local_state.tensors) { | ||
| const auto global_key = RemapLayerKey(local_key, local_layers, global_layers); |
There was a problem hiding this comment.
这里能不能构造时就把 global layer_number 传进来,而不是 Remap 一遍
背景
现有 distributed checkpoint 与保存时的 TP/PP 拓扑绑定,恢复训练时要求使用相同的并行配置。本 PR 引入基于全局张量坐标的 checkpoint resharding,使 checkpoint 可以在不同 TP/PP 配置之间恢复。
设计文档:Checkpoint Resharding 设计
主要修改
ShardedTensor/ShardedStateDict,描述张量的全局形状、本地分片、全局偏移和切分方式。SavePlanner,统一规划模型参数和 Adam optimizer state 的本地写入布局,并生成可用于 reshard 的全局 metadata。LoadPlanner,根据源 checkpoint 与当前目标拓扑的分片坐标计算重叠区间。IndexedRegionLoadStrategy,按 metadata 中的文件和 offset 直接读取所需区域,在加载阶段完成重组,无需预先生成中间 checkpoint。m/v共用参数分片信息,训练状态和 LR scheduler 状态随 checkpoint 一并恢复。dp_rank=0的 TP/PP ranks 写入 shard,并在所有 rank metadata 就绪后原子发布全局 metadata。当前限制
segments表达。DistributedOptimizer/ ZeRO optimizer state 的保存和恢复。测试