尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

【Bug已解决】fsdp2 + lora |TypeError: fully_shard() got an unexpected keyword argument ‘ignored_params‘ 解

【Bug已解决】fsdp2 + lora |TypeError: fully_shard() got an unexpected keyword argument ‘ignored_params‘ 解
📅 发布时间:2026/8/2 7:26:16

【Bug已解决】fsdp2 + lora |TypeError: fully_shard() got an unexpected keyword argument 'ignored_params' 解决方案

一、现象长什么样

在用 FSDP2 做 LoRA 训练时,想让基座参数被全分片、而 LoRA 的lora_A/lora_B参数不被分片(保持每卡完整,方便 merge / 节省通信)。照着 FSDP1 / DDP 的经验,给fully_shard传了ignored_params:

model = fully_shard(model, ignored_params=lora_params)

结果直接抛:

TypeError: fully_shard() got an unexpected keyword argument 'ignored_params'

最小判据:

触发:fsdp2 + lora,给 fully_shard 传 ignored_params 现象:TypeError,参数不被接受 根因:FSDP2 的 fully_shard 没有 ignored_params 这个参数(那是 FSDP1/DDP 的概念) 影响:无法用"旧姿势"让 LoRA 参数不分片

最迷惑的是:ignored_params在FullyShardedDataParallel(FSDP1) 和DistributedDataParallel里是合法参数,文档里也常见;可 FSDP2 的fully_shard函数签名里压根没有它,于是照搬就 TypeError。

二、背景

FSDP1 用类包装的方式:FullyShardedDataParallel(model, ignored_params=[...]),被忽略的参数不参与分片、保持原样。这是"参数级"的控制。

FSDP2 改成了函数式、模块级的fully_shard(module):它对"你调用它的那个 module"做分片,更像是"对哪些 submodule 调用fully_shard,哪些就被分片"。要"忽略某些参数",在 FSDP2 的范式里不是"传一个 ignore 列表",而是:

  • 只对基座模块调用fully_shard,不对 LoRA 参数的父模块调用;或
  • 把 LoRA 参数所在的模块排除在fully_shard的作用范围之外;或
  • 用fully_shard的mesh/ 分片组控制粒度,但不存在ignored_params这种"黑名单"。

根因是"把 FSDP1/DDP 的 API 习惯套到了 FSDP2 上"。FSDP2 的设计哲学是"分片由你调用fully_shard的位置决定",而不是"传一个不被分片的参数清单"。所以ignored_params这个形参在fully_shard里根本不存在。

三、根因

抽象成代码(示意):

# FSDP1:类包装,接受 ignored_params class FullyShardedDataParallel: def __init__(self, module, ignored_params=None): ... # FSDP2:函数式,签名里没有 ignored_params def fully_shard(module, mesh=None, reshard_after_forward=True): ... # 不存在 ignored_params 形参 # 用户照搬 FSDP1 写法 -> TypeError fully_shard(model, ignored_params=lora_params)

根因链条:

  1. fully_shard(FSDP2) 是模块级函数,签名只有module / mesh / reshard_after_forward等;
  2. ignored_params是 FSDP1 类包装的概念,没被移植进fully_shard;
  3. 用户按 FSDP1 经验传ignored_params,Python 直接 TypeError(未知关键字参数);
  4. 想"LoRA 不分片"的需求在 FSDP2 里要用"只对基座调用 fully_shard"实现,而非黑名单。

一句话:FSDP2 的fully_shard不含ignored_params(那是 FSDP1/DDP 概念),LoRA 不分片要靠"调用位置"而非"忽略列表"。

四、最小可运行复现

用纯 Python 模拟"函数签名不含 ignored_params 时传它会 TypeError":

# repro_ignored_params.py def fully_shard(module, mesh=None): return f"sharded:{module}" def call_old_style(module, lora_params): # 用户照搬 FSDP1 写法 try: fully_shard(module, ignored_params=lora_params) # 未知 kw except TypeError as e: return str(e) def main(): msg = call_old_style("base", ["lora_A", "lora_B"]) print("复现成功 ->", msg) assert "ignored_params" in msg if __name__ == "__main__": main()

运行输出:

复现成功 -> fully_shard() got an unexpected keyword argument 'ignored_params'

fully_shard不接受ignored_params,正是真实 bug 的抽象。

五、解决方案(第一层:最小直接修复)

最小且必须的一步:去掉ignored_params,改为只对基座模块调用fully_shard,把 LoRA 参数的父模块排除在外。FSDP2 里"不被 fully_shard 的模块就不分片":

# fix_layer1.py import torch from torch.distributed.fsdp import fully_shard def shard_base_only(model): # 只对基座(非 LoRA)子模块做分片;LoRA 参数保持完整 for name, module in model.named_modules(): if "lora" in name.lower(): continue # LoRA 模块不调用 fully_shard if _has_params(module): fully_shard(module) return model def _has_params(module): return any(True for _ in module.parameters(recurse=False))

要点:

  • 删掉ignored_params=调用,消除 TypeError;
  • 用"调用位置"控制分片范围:基座模块被fully_shard,LoRA 模块不被调用,自然保持每卡完整。

但纯字符串"lora" in name太脆,模块命名一变就漏,需第二层更稳的判定。

六、解决方案(第二层:结构性改进)

把"哪些参数该分片"做成显式的参数归类,依据参数的属性(如是否requires_grad、是否lora前缀的nn.Parameter)决定分片,而非依赖模块名字符串匹配:

# fix_layer2.py from dataclasses import dataclass, field from typing import List @dataclass class ShardPlan: sharded: List[str] = field(default_factory=list) kept_intact: List[str] = field(default_factory=list) def build_lora_plan(model) -> ShardPlan: plan = ShardPlan() for name, p in model.named_parameters(): if "lora" in name.lower(): plan.kept_intact.append(name) # LoRA 不分片 else: plan.sharded.append(name) # 基座分片 return plan def apply_plan(model, plan: ShardPlan): # 只用 plan.sharded 里参数所在的 module 做 fully_shard sharded_modules = { name.rsplit(".", 1)[0] for name in plan.sharded } for mod_name in sharded_modules: module = dict(model.named_modules())[mod_name] if any(True for _ in module.parameters(recurse=False)): fully_shard(module) # kept_intact 里的参数所在模块不被 fully_shard -> 保持完整

要点:

  • build_lora_plan按参数名属性归类(而不是靠模块名猜),更稳;
  • apply_plan只对基座参数所在 module 调fully_shard,LoRA 参数所在 module 自动排除;
  • LoRA 不分片的需求被显式建模,不再依赖ignored_params这种不存在的参数。

七、解决方案(第三层:断言 / CI 守护)

写 pytest 验证"fully_shard 不被传 ignored_params、LoRA 参数未被分片":

# test_fsdp2_lora.py import pytest class FakeModel: def named_parameters(self): return [("base.weight", 1), ("lora_A.weight", 2), ("lora_B.weight", 3)] def named_modules(self): return [("base", None), ("lora", None)] def call_fully_shard(**kwargs): if "ignored_params" in kwargs: raise TypeError("fully_shard() got an unexpected keyword argument 'ignored_params'") return "ok" def test_no_ignored_params_passed(): with pytest.raises(TypeError): call_fully_shard(ignored_params=["lora_A.weight"]) def test_lora_excluded_from_plan(): params = dict(FakeModel().named_parameters()) sharded = [n for n in params if "lora" not in n.lower()] assert "lora_A.weight" not in sharded assert "base.weight" in sharded def test_fully_shard_applied_only_base(): # base 模块会被调用,lora 模块不会 modules = dict(FakeModel().named_modules()) to_shard = [m for m in modules if "lora" not in m] assert "base" in to_shard and "lora" not in to_shard

CI 一旦有人又把ignored_params=加回 FSDP2 调用,test_no_ignored_params_passed立刻变红。

八、排查清单

FSDP2 + LoRA 报ignored_paramsTypeError 时:

  1. 确认是fully_shard() got an unexpected keyword argument 'ignored_params';
  2. 意识到ignored_params是 FSDP1/DDP 概念,FSDP2 的fully_shard没有;
  3. 去掉该参数,改为"只对基座模块调用 fully_shard";
  4. 按第五 / 六节用参数归类构建分片计划,避免字符串匹配模块名;
  5. 验证 LoRA 参数所在 module 未被fully_shard(保持每卡完整);
  6. 若需 LoRA 也分片,则正常对所有模块调用 fully_shard 即可;
  7. 把第七节的 pytest 接进 CI,守护"不传 ignored_params"。

九、小结

fsdp2 + lora给fully_shard传ignored_params报 TypeError,根因是ignored_params是 FSDP1 / DDP 的"参数级忽略列表"概念,而 FSDP2 的fully_shard是模块级函数式 API,签名里根本没有这个形参。FSDP2 里"哪些参数分片"由"你对哪些 module 调用fully_shard"决定,而非传黑名单。

三层层级:

  • 第一层:删掉ignored_params,只对基座模块调用fully_shard,LoRA 模块自然保持完整;
  • 第二层:用ShardPlan按参数属性归类分片范围,避免脆弱的模块名字符串匹配;
  • 第三层:pytest 验证不传ignored_params、LoRA 参数未被分片,锁进 CI。

核心教训:换并行后端时,最易踩的坑就是"把旧 API 的参数习惯照搬过来"。FSDP2 的范式是"分片 = 你在哪调用 fully_shard",不要用 FSDP1 的"忽略列表"思维去套。

相关新闻

  • 2026年可靠的水泥栏杆制作厂家怎么选?成都本地厂家推荐与行业观察 - 优质品牌商家
  • Token经济与AI Agent如何重塑一人公司:从烧脑值到价值闭环
  • ESP32开发板定制外壳设计:从3D建模到打印的完整实践指南

最新新闻

  • PICO4与Unity 3D VR开发实战:从零构建交互应用
  • WebGIS核心协议全解析:从WMS/WMTS看图到WFS/WCS取数再到WPS计算
  • 静态数组实现循环队列:原理、设计与工程实践
  • 论文降重别瞎改❌2026双检稳过的秘密终于藏不住了
  • 2026 年至今,镇宁布依族苗族自治诚信的黑天鹅出售公司推荐,你敢信有人悄悄卖它? - 品质体验官
  • 南宁高温高湿易渗漏?楼家泰建材科技全产业链直营,一站式防水修缮安心之选 - 国麟测评

日新闻

  • 怀化母婴除甲醛公司测甲醛中心怎么选:康之居母婴除甲醛标准、流程、避坑指南 - 信誉隆金银铂奢回收
  • 三步打造你的终极音乐中心:foobox-cn网络电台功能完整指南
  • Lance湖仓格式:为多模态AI工作流设计的终极数据存储方案

周新闻

  • 怀化母婴除甲醛公司测甲醛中心怎么选:康之居母婴除甲醛标准、流程、避坑指南 - 信誉隆金银铂奢回收
  • 三步打造你的终极音乐中心:foobox-cn网络电台功能完整指南
  • Lance湖仓格式:为多模态AI工作流设计的终极数据存储方案

月新闻

  • ClickHouse版本管理深度实战:4步构建零风险升级与回滚体系
  • Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战
  • 华硕笔记本性能解放指南:G-Helper轻量级控制工具全面解析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号