Skip to content

[FSDP] optim FSDP save/load - #79724

Open
Xing-lil wants to merge 13 commits into
PaddlePaddle:developfrom
Xing-lil:optim_fsdp_save_load
Open

[FSDP] optim FSDP save/load#79724
Xing-lil wants to merge 13 commits into
PaddlePaddle:developfrom
Xing-lil:optim_fsdp_save_load

Conversation

@Xing-lil

@Xing-lil Xing-lil commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

PR Category

Performance Optimization

PR Types

Others

Description

save/load 方案:
FSDP 将参数拼接为融合 buffer 并按 rank 切分,单卡不持有完整参数。save 时各 rank 直接落盘本地分片,不再 all_gather 参数,记录该分片所属参数及其区间,由 flex_checkpoint 在 load 时重组。
以上为 FC 格式;HF 格式需完整参数,显式 raise 并走离线转换(暂无转换脚本)。
验证:
在 Qwen3-30B-A3B N1C8 上已验证接续对齐。

是否引起精度变化


sharded_state = {}
for vname, tensor in state_dict.items():
base_name, tag = _split_optimizer_state_name(vname)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 optimizer_sharded_state_dict 会把无法匹配 _moment1/_moment2/_velocity/_beta*_pow_acc 的状态直接跳过。FullyShardFusion 的训练路径没有限制优化器类型,而 Adamax(moment/inf_norm)、RMSProp(mean_square/mean_grad)和 Nadam(momentum_decay_pow/mu_product 等)的累积状态都会在保存时丢失,加载后相当于从零开始,改变续训结果。请复用各优化器的状态映射,或在接口上明确拒绝未支持的优化器并覆盖测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新提交通过动态收集优化器的 *_acc*_str,但 Adadelta 的 _avg_squared_grad_acc_str_avg_squared_update_acc_str 值本身以 _ 开头;经 .lstrip("_") 后,实际变量名 fuse_params_0__avg_squared_grad_0 会被解析为 base fuse_params_0_,与 fused buffer owner 不一致,仍会触发 NotImplementedError(另一个累积项同样受影响)。因此该 P1 仍未解决,需修正前缀处理并补充 Adadelta(含 master weight)保存/加载测试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adadelta 的前导下划线问题已修复,但当前解析仍未覆盖 Optimizer 的公开 name 参数:_add_accumulator 会把 self._name + "_" 插入变量名(例如 fuse_params_0_opt_moment1_0),而 _split_optimizer_state_name 只按 _<tag>_ 截断,得到 base fuse_params_0_opt,随后在 base_name != owner 处抛出 NotImplementedError。因此合法的 AdamW(..., name="opt") 等 FSDP 续训仍无法保存;建议按 owner 后的完整后缀解析或显式覆盖/拒绝命名优化器,并补充该配置测试。

opt.step()
opt.clear_grad()

opt_sharded_state_dict = fsdp_context.optimizer_sharded_state_dict(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 这里的新增用例只比较 ShardedWeight 的元数据,没有调用 dist.save_state_dict/dist.load_state_dict,也没有把加载后的状态注入新 optimizer 后继续执行一步。因此实际 checkpoint 的文件去重、跨 rank 重组、参数/累积值和 master weight 恢复都未被验证,核心 save/load 回归仍可能通过 CI。请增加 2 卡真实保存/加载 round-trip,并比较恢复后参数及下一步训练结果。

@Paddle-Bot Paddle-Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Paddle-Bot Review Board (review完成)

序号 位置 优先级 规则来源 状态
1 优化器状态映射 P1 仓库规则:正确性与兼容性
2 检查点往返测试 P1 仓库规则:测试质量与验证
3 混合权重衰减策略 P1 仓库规则:正确性与兼容性
4 Adadelta 混合精度执行 P1 仓库规则:功能正确性与兼容性
Powered by Nyanpasu with gpt-5.6-sol 默认推理级别, please check the suggestions carefully.

@codecov-commenter

codecov-commenter commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.81287% with 14 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (develop@df1fbe1). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...thon/paddle/distributed/fsdp/fully_shard_fusion.py 91.71% 14 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             develop   #79724   +/-   ##
==========================================
  Coverage           ?   91.81%           
==========================================
  Files              ?        2           
  Lines              ?      171           
  Branches           ?        0           
==========================================
  Hits               ?      157           
  Misses             ?       14           
  Partials           ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Paddle-Bot

Paddle-Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Failed CI看板

流水线名称 问题标签 修复建议 日志片段
CI-Windows / Windows-GPU / Build and test CI 代理网络 502 【与当前改动无关】GitHub 仓库克隆阶段即失败,直接重跑该 job。 报错代码
CI-Windows / Windows-Inference / Build and test CI 代理网络 502 【与当前改动无关】未进入编译和测试,重跑该 job。 报错代码
Bot Approval Required / Require review-bot approval 审批门禁未通过 【与当前改动无关】等待指定机器人或审批账号对当前 SHA 99cfd06... 完成 APPROVED 后重跑门禁。 报错代码
CI / Linux-DCU / Build CI 网络连接超时 【与当前改动无关】在拉取 upstream 分支阶段即失败,重跑该 job。 报错代码
CI-H / Build Fleet whl PaddleFleet 克隆失败 【与当前改动无关】git clone PaddleFleet.git 因代理返回 502 失败,重跑 CI-H;无需修改本 PR 代码。 报错代码
日志分析报告

失败的测试 case:

1. Windows-GPU / Build and test
   步骤:初始化 Windows GPU 构建环境后拉取 Paddle 仓库。
   关键错误:fatal: unable to access 'https://github.com/PaddlePaddle/Paddle.git/': Received HTTP code 502 from proxy after CONNECT
   未执行编译或测试。

2. Windows-Inference / Build and test
   步骤:初始化 Windows 推理构建环境后拉取 Paddle 仓库。
   关键错误:fatal: unable to access 'https://github.com/PaddlePaddle/Paddle.git/': Received HTTP code 502 from proxy after CONNECT
   未执行编译或测试。

3. Require review-bot approval
   步骤:检查当前 head SHA 上指定机器人和审批账号的最新决定性 review。
   关键错误:当前 PR 尚未获得 risemeup1111、Paddle-Bot、sneaxiy 或 From00 的 APPROVED。
   这是审批门禁失败,不是测试失败。

4. Linux-DCU / Build
   步骤:拉取 upstream develop 或目标分支。
   关键错误:fatal: unable to access 'https://github.com/PaddlePaddle/Paddle.git/': Failed to connect to github.com port 443: Connection timed out
   未进入构建阶段。

5. Build Fleet whl
   步骤:启动构建容器并克隆 PaddleFleet 仓库。
   关键错误:fatal: unable to access 'https://github.com/PaddlePaddle/PaddleFleet.git/': CONNECT tunnel failed, response 502
   未进入 wheel 构建或 PR 代码测试阶段。

根本原因分析:

5 个失败 job 中,4 个是外部网络或代理故障:Windows 两个 job 和 Linux-DCU 在访问 Paddle.git 时分别收到 502 和连接超时,CI-H 在克隆 PaddleFleet.git 时收到代理 502。它们都发生在构建、测试以及本 PR 的 FSDP 代码执行之前,因此与 PR diff 无直接因果关系。

Require review-bot approval 仅因当前 SHA 没有满足审批门禁的 APPROVED review 失败。日志没有显示任何代码测试错误,也不能据此推断 PR 代码存在问题。

PR diff 主要修改 FSDP checkpoint、优化器状态和相关测试;快照中没有任何涉及这些改动的编译错误、Python 异常、断言失败、CUDA 错误或测试输出。因此当前证据支持 CI 基础设施/审批状态问题,不支持将失败归因于 PR 代码。

修复建议:

  1. 【与当前改动无关】Windows-GPU / Build and test:修复或等待 GitHub 代理网络恢复后重跑该 job。
  2. 【与当前改动无关】Windows-Inference / Build and test:重跑该 job,确认仓库克隆成功后再判断构建结果。
  3. 【与当前改动无关】Require review-bot approval:让指定机器人或审批账号针对当前 head 完成 APPROVED,然后重跑审批门禁。
  4. 【与当前改动无关】Linux-DCU / Build:重跑该 job,确认 upstream 拉取成功后再分析后续构建日志。
  5. 【与当前改动无关】CI-H / Build Fleet whl:重跑 CI-H;若持续失败,应排查访问 PaddleFleet 的代理或网络连通性。

Powered by Nyanpasu with gpt-5.6-luna 默认推理级别, please check the suggestions carefully.

"without weight decay; mark the exempt ones with "
"`param.no_weight_decay = True` before fully_shard()."
)
buffer_decay[buffer_name] = any(answers) and not group.no_decay

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 这里把 fused buffer 内所有参数的 decay 回调结果用 any(answers) 合并成一个布尔值;当常见的 weight decay 参数和 bias/no-decay 参数位于同一 buffer 时,整个 buffer(包括 bias)都会被施加 weight decay。当前 warning 不能阻止错误更新。请按 decay 策略拆分 buffer、按参数切片应用 decay,或显式拒绝混合组,并增加混合 weight/bias 的回归测试。

{
"test_type": "optimizer",
"layer_type": "FullyShard",
"optimizer_type": "Adadelta",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 新增的 Adadelta 两卡配置会让 test_sharded_state_dict 在真正执行 opt.step() 时失败:上一版 head 47abbded 的 Coverage 日志已稳定复现 Adadelta._append_optimize_opInvalidArgumentError: ... float16 ... float32,而当前 head 仅追加了另一个 AdamW 配置,Adadelta 路径仍未修复。请为 Adadelta 提供有效的 FSDP/混合精度 dtype 处理(或移除/改为受支持的测试配置),并确保该两卡用例可完成训练与 checkpoint 往返。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 head 本地复跑两卡用例:pytest -k TestParallelLayersWith2Devices → 1 passed / 218s,20 个配置全过;单跑 Adadelta 配置 exit 0,save/load 往返断言都执行。

Adadelta 那条没设 amp_level,走默认 O1,MixPrecisionLayer 不 cast 权重(只挂 main_grad hook),param 和 grad 都是 fp32,adadelta_ 无 dtype 冲突。float16 参数只出现在新增的 amp_level=O2 配置,而那条是支持 multi_precision 的 AdamW —— 47abbde 日志里的 float16/float32 应属该配置,误归到 Adadelta 了。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确认,你的定位正确。我复核到测试基类会复用并修改 os.environ47abbded 的 O2 配置未显式指定 optimizer_type,因此继承了上一条 Adadelta,实际失败组合是 O2 + Adadelta,而不是默认 O1 的 Adadelta 配置。当前 head 显式设置 AdamW 后已消除该环境串扰;此前归因有误,这条 P1 撤回并标记为已解决。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants