PyTorch FSDP:把参数、梯度和优化器状态分片到多卡,训练放不下的模型
FSDP(Fully Sharded Data Parallel)把模型参数、梯度和优化器状态按数据并行组切分到各 GPU,前向/反向时按需 all-gather,计算完再释放。它适合单卡放不下、但又不想上张量并行的模型;和 DeepSpeed ZeRO-3 的目标类似,区别在实现、配置方式和生态集成。
FSDP 有两种常见形态:经典 FSDP wrapper 和 PyTorch 2.x 的 FSDP2(fully_shard)。FSDP2 使用 DTensor,支持更灵活的分片和 torch.compile,新项目优先评估 FSDP2。使用 FSDP 需要 torchrun 启动,不能直接用 python train.py 跑多卡。
# 8 卡启动
torchrun --standalone --nproc_per_node=8 train_fsdp.py
import torch
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
from torch.distributed.fsdp import MixedPrecision, ShardingStrategy
model = MyModel().cuda()
mp = MixedPrecision(param_dtype=torch.bfloat16,
reduce_dtype=torch.bfloat16,
buffer_dtype=torch.bfloat16)
model = FSDP(
model,
sharding_strategy=ShardingStrategy.FULL_SHARD,
mixed_precision=mp,
device_id=torch.cuda.current_device(),
use_orig_params=True,
)
# 按层 wrapping,避免一次性 all-gather 整个模型
from torch.distributed.fsdp.wrap import transformer_auto_wrap_policy
from torch.distributed.fsdp import FSDP
model = FSDP(
model,
auto_wrap_policy=transformer_auto_wrap_policy,
sharding_strategy=ShardingStrategy.FULL_SHARD,
)
FSDP2 的写法:
from torch.distributed.fsdp import fully_shard
for layer in model.layers:
fully_shard(layer)
fully_shard(model)
python 直接启动:FSDP 需要进程组和 LOCAL_RANK,多卡必须用 torchrun/torch.distributed.launch。no_sync 使用不当:梯度累积时用 no_sync 减少通信,但最后一个 micro-batch 必须同步;否则梯度缺失。FullStateDictConfig/LocalStateDictConfig 或分布式 checkpoint;直接 torch.save(model.state_dict()) 可能只保存部分。param_dtype、reduce_dtype、buffer_dtype 要一致规划;某些算子对 BF16 不支持。torch.compile 顺序错误:先 compile 还是先 fully_shard 随版本不同;按 PyTorch 版本文档调整,并用小模型验证。合上页面,先回答,再展开对照。
FULL_SHARD 和 SHARD_GRAD_OP 的主要区别是什么?torch.save(model.state_dict())?FULL_SHARD 在前后向后释放参数分片,显存最省但通信更多;SHARD_GRAD_OP 只分片梯度和优化器状态,参数常驻,通信较少、显存占用更高。
小程序版
微信扫码,随时查命令