ValueError: When using FSDP2, a model and optimizer must be passed together to `Accelerator.prepare()`

这个报错通常出现在未训练过的 Trainer 上直接调用 evaluate() 或 predict() ,且使用 FSDP2 的场景:评估流程只准备模型、不准备优化器,而 FSDP2 要求模型和优化器一起传给 Accelerator.prepare() 。优先排查是否在 FSDP2 下走了“仅模型”

快速结论:这个报错通常出现在未训练过的 Trainer 上直接调用 evaluate() 或 predict(),且使用 FSDP2 的场景:评估流程只准备模型、不准备优化器,而 FSDP2 要求模型和优化器一起传给 Accelerator.prepare()。优先排查是否在 FSDP2 下走了“仅模型”的 prepare 分支。

适用环境:Issue 中确认的环境为 transformers 5.17.0.dev0(main 41f519e741)、accelerate 1.14.0、torch 2.13.0+cu130、Python 3.13.13,单卡 1x H100 80GB,通过 accelerate launch 使用 --use_fsdp --fsdp_version 2、--num_processes 1 即可复现;未涉及上下文并行。

最快修复方案:暂无确认的一步修复方案。该 Issue 由维护者关闭并表示内部处理,讨论中并未验证任何补丁或命令级修复。可优先尝试的方向是让新 Trainer 的评估路径不要以“仅模型”方式准备 FSDP2,但具体实现尚未确认。

注意事项:讨论指出,直接把新 FSDP2 评估改走 prepare_model(..., evaluation_mode=True) 虽可绕过模型+优化器校验,但该模式不做 FSDP 包装,且 FSDP 会关闭默认设备放置;若再显式搬移模型,可能让每个 rank 都持有完整模型,从而失去分片,因此不能视为等价修复。

问题场景

用户在 Transformers Trainer 中使用 FSDP2(accelerate launch 的 --use_fsdp --fsdp_version 2),对一个尚未训练过的新 Trainer 直接调用 trainer.evaluate(Tokens())(或同理的 predict)。复现脚本使用 Qwen3Config 构造的小型 AutoModelForCausalLM(sdpa 注意力)和自定义 Dataset。单进程、单卡环境即可触发,不需要上下文并行。

报错原文

ValueError: When using FSDP2, a model and optimizer must be passed together to `Accelerator.prepare()`
as the optimizer needs to have its parameters modified after the model is converted.

原因分析

未训练过的 Trainer 调用评估时,evaluation_loop 会自行准备模型;在 Trainer 的该分支中,非 FSDP 情况会走 prepare_model(model, evaluation_mode=True),但 FSDP2 分支没有做同样的处理。accelerate 1.14.0 在 FSDP2 下不允许只传模型调用 Accelerator.prepare(),因为优化器参数需要在模型转换后再修改,于是抛出上述 ValueError。这是“仅模型 prepare”与 FSDP2 约束冲突导致的可能原因。另需注意,讨论中提出 evaluation_mode=True 本身也不进行 FSDP 包装,所以它不是完整的 FSDP2 评估方案。

环境排查

  • 确认 transformers 版本:Issue 复现于 5.17.0.dev0(main 41f519e741),其他版本行为需自行验证。
  • 确认 accelerate 版本:Issue 为 1.14.0,报错来源即该版本 Accelerator.prepare() 的 FSDP2 校验。
  • 确认 torch 版本:Issue 为 2.13.0+cu130。
  • 确认 Python 版本:Issue 为 3.13.13。
  • 确认显卡与进程数:Issue 为 1x H100 80GB,--num_processes 1。
  • 确认启动参数:是否使用 --use_fsdp --fsdp_version 2,以及 --fsdp_auto_wrap_policy TRANSFORMER_BASED_WRAP。
  • 确认调用顺序:是否在未调用过 train() 的新 Trainer 上直接调用 evaluate() / predict()。

解决步骤

  1. 先确认这是 FSDP2 专属问题:用同样的脚本分别在普通 DDP 与 FSDP2 下运行,若只有 FSDP2 报该 ValueError,则与 Issue 场景一致。
  2. 梳理评估路径:检查 Trainer 评估流程中在未训练情况下自行 prepare 模型的分支,确认 FSDP2 下是否以“仅模型”形式调用了 Accelerator.prepare()。
  3. 评估可选的处理方向(尚无已验证结论):一是让该路径在 FSDP2 下也满足“模型+优化器一起准备”的约束;二是如讨论所设想,在 Accelerate 侧提供不要求优化器的推理专用 FSDP2 准备路径;三是仅让评估能跑通,但需接受可能失去分片或占用更多显存。
  4. 若只是临时绕开报错,可先在有优化器的训练流程后再评估,或改用已训练/已 prepare 的 Trainer;但这是绕过路径,并非 Issue 中验证过的修复。
  5. 如果自行修改代码,请补充 FSDP 分布式回归测试(讨论建议包括端到端双进程用例),并确认单卡与多卡行为一致。

验证方法

在 FSDP2 启动参数下对全新 Trainer 调用 evaluate() 和 predict(),确认不再抛出上述 ValueError,且评估结果正常输出;同时检查模型是否仍按 FSDP2 分片(而非每个 rank 复制完整模型)、显存占用是否合理。若涉及多进程,还需在双进程及以上环境中验证分片与结果一致性。

参考来源

huggingface/transformers #48841

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 30923

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注