Skip to content

FSDP 与 DeepSpeed

Accelerate 通过集成两个极其强大的分布式训练工具——Pytorch FSDPMicrosoft DeepSpeed,提供了训练框架的灵活性。本教程的目的是对比这两种工具的相似之处和潜在差异,以帮助用户在这两个框架之间无缝切换。

配置功能

模型张量被拆分到不同的 GPU 上,以尝试扩展模型规模;这在 FSDP 中称为 分片,在 DeepSpeed 中称为 分区。FSDP 分片和 DeepSpeed ZeRO(分区)阶段分别通过 --fsdp_sharding_strategy--zero_stage 进行配置。特别是,FSDP 的 FULL_SHARD 对应于 DeepSpeed ZeRO 阶段 3;请参阅此 FSDP 分片和 DeepSpeed ZeRO 设置之间的详细映射。下表总结并分组了类似的设置:

GroupFrameworkConfigurationExampleRestrictions (if any)
sharding / partitioningFSDP
DeepSpeed
--fsdp_sharding_strategy
--zero_stage
1 (FULL_SHARD)
3
offloadFSDP
DeepSpeed
--fsdp_offload_params
--offload_param_device
--offload_optimizer_device
true
cpu
cpu
all or nothing

model loadingFSDP
DeepSpeed
--fsdp_cpu_ram_efficient_loading
--zero3_init_flag
true
true

only ZeRO 3
efficient checkpointingFSDP
DeepSpeed
--fsdp_state_dict_type
--zero3_save_16bit_model
SHARDED_STATE_DICT
true

only ZeRO 3
weights prefetchingFSDP

DeepSpeed
--fsdp_forward_prefetch
--fsdp_backward_prefetch
None
true
BACKWARD_PRE


modelFSDP

DeepSpeed
--fsdp_auto_wrap_policy
--fsdp_transformer_layer_cls_to_wrap
None
TRANSFORMER_BASED_WRAP
<Layer Class>

Usually not needed
Transparent to user.
parameters summoningFSDP
DeepSpeed
--fsdp_use_orig_params
None
truerequired for torch.compile
Transparent to user
parameters syncingFSDP
DeepSpeed
--fsdp_sync_module_states
None
true
trainingFSDP
DeepSpeed
None
--gradient_accumulation_steps
--gradient_clipping

auto
auto
Transparent to user

有关上述内容的详细描述,请参阅 Accelerate 启动文档

检查点

请注意,FSDP 可以通过 --fsdp_state_dict_type 配置为保存完整或分片的检查点。

卸载

FSDP 仅允许 全有或全无 的卸载(即,要么卸载参数、梯度和优化器,要么将它们全部保留在 GPU 中),而 DeepSpeed 可以分别卸载参数和优化器。此外,DeepSpeed 还支持 卸载到 NVME

预取

FSDP 允许两种预取配置 --fsdp_forward_prefetch--fsdp_backward_prefetch,以提高通信/计算的重叠,但会增加额外的内存开销,详见 FSDP 文档。 对于 DeepSpeed,预取会在需要时自动开启,并且根据某些超参数(如 stage3_param_persistence_thresholdstage3_max_reuse_distance 等)来决定是否开启,这些超参数可以在 Zero3 中配置accelerate 可能会自动设置这些超参数,如果你没有在 DeepSpeed 配置文件中显式设置它们。

模型加载

虽然 FSDP 需要显式地使用 --fsdp_cpu_ram_efficient_loading true 来激活高效的模型加载,但 transformers 在使用 DeepSpeed Zero3 时会自动激活类似的功能。

模型

FSDP 需要一个显式的 --fsdp_auto_wrap_policy 参数,以便算法决定如何调度 all-gather 和 reduce-scatter 操作。但对于 DeepSpeed,这是对用户透明的。

参数调用

如果使用 torch.compile,FSDP 需要显式地设置 --fsdp_use_orig_params 标志,详情请参阅 PyTorch 文档。对于 DeepSpeed,这一过程对用户是透明的。

训练

Deepspeed 需要显式指定 --gradient_accumulation_steps--gradient_clipping 标志。对于 FSDP,这是对用户透明的。

关于数据精度处理的差异

为了讨论 FSDP 和 Deepspeed 在数据精度处理上的差异,首先概述这些框架中模型参数的处理方式是有帮助的。在模型/优化器参数被分发到多个 GPU 之前,参数准备涉及将它们首先"展平"为一维的torch.Tensor。FSDP 和 Deepspeed 在这些"展平"参数的 dtype 存储方式上有所不同,这会影响到torch.Optimizer 如何分配它们的 dtype。下表概述了两个框架的处理过程;"本地"列表示在每个 GPU 级别发生的处理过程,因此任何由于类型提升而产生的内存开销应理解为由使用的 GPU 数量分摊。

ProcessLocalFrameworkDetails
Loading, i.e., [AutoModel.from_pretrained(..., torch_dtype=torch_dtype)]
Preparation, i.e., creation of "flat params"FSDP
DeepSpeed
created in torch_dtype.
disregards torch_dtype, created in float32.
Optimizer initializationFSDP
DeepSpeed
creates parameters in torch_dtype
creates parameters in float32
Training Step, i.e, forward, backward, reductionFSDP
DeepSpeed
follows MixedPrecision
follows deepspeed_config_file mixed precision settings.
Optimizer (Pre-Step)FSDP
DeepSpeed
upcasting (if any) to torch_dtype
upcasted to float32
Optimizer (Actual Step)FSDP
DeepSpeed
occurs in torch_dtype
occurs in float32.

为了澄清上表,考虑以下具体示例;为了简洁,将优化器的预步骤和实际步骤合并在一起。使用 FSDP 时,可以以以下两种模式运行,但 DeepSpeed 只能以其中一种模式运行。

FrameworkModel Loading (torch_dtype)Mixed PrecisionPreparation (Local)TrainingOptimizer (Local)
FSDPbf16default (none)bf16bf16bf16
FSDPbf16bf16fp32bf16fp32
DeepSpeedbf16bf16fp32bf16fp32