加速文档

FSDP 与 DeepSpeed

Hugging Face's logo
加入 Hugging Face 社区

并获得增强型文档体验

开始使用

FSDP 与 DeepSpeed

Accelerate 提供了训练框架的灵活性,通过集成两个用于分布式训练的强大工具,即 Pytorch FSDPMicrosoft DeepSpeed。本教程旨在阐明两者之间的异同,并帮助用户在这两个框架之间无缝切换。

要在这两个框架之间切换,我们建议您启动代码 accelerate launch 并传入正确的配置文件(使用 --config_file),或者直接为 FSDP 和 DeepSpeed 传入相应的参数。

可在以下链接找到 Accelerate 配置示例:DeepSpeedFSDP,或在 “启动配置”下的示例库 中。

本教程仅适用于单节点、多GPU场景。

配置功能

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

分组 框架 配置 示例 限制(如有)
分片/分区 FSDP
DeepSpeed
--fsdp_sharding_strategy
--zero_stage
1 (FULL_SHARD)
3
卸载 FSDP
DeepSpeed
--fsdp_offload_params
--offload_param_device
--offload_optimizer_device
true
cpu
cpu
全部或无

模型加载 FSDP
DeepSpeed
--fsdp_cpu_ram_efficient_loading
--zero3_init_flag
true
true

仅 ZeRO 3
高效检查点 FSDP
DeepSpeed
--fsdp_state_dict_type
--zero3_save_16bit_model
SHARDED_STATE_DICT
true

仅 ZeRO 3
权重预取 FSDP

DeepSpeed
--fsdp_forward_prefetch
--fsdp_backward_prefetch
true
BACKWARD_PRE


模型 FSDP

DeepSpeed
--fsdp_auto_wrap_policy
--fsdp_transformer_layer_cls_to_wrap
TRANSFORMER_BASED_WRAP
<层类>

通常不需要
对用户透明。
参数调用 FSDP
DeepSpeed
--fsdp_use_orig_params
true torch.compile 需要
对用户透明
参数同步 FSDP
DeepSpeed
--fsdp_sync_module_states
true
训练 FSDP
DeepSpeed

--gradient_accumulation_steps
--gradient_clipping

自动
自动
对用户透明

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

要访问其他 DeepSpeed 配置(例如混合精度设置),您需要传入 --deepspeed_config_file,请参阅 文档

DeepSpeed 也可以通过 DeepSpeedPlugin 进行配置,例如,DeepSpeedPlugin.zero_stage 等效于 --zero_stageDeepSpeedPlugin.hf_ds_config 可用于传递 --deepeed_config_file.

FSDP 也可以通过 FullyShardedDataParallelPlugin 进行配置,例如,FullyShardedDataParallelPlugin.sharding_strategy 等效于 --fsdp_sharding_strategy

检查点

请注意,虽然可以通过 --fsdp_state_dict_type 配置 FSDP 以保存完整/分片检查点。

对于 DeepSpeed Zero3,可以传递 --zero3_save_16bit_model true,这可以方便地将模型合并到单个秩并保存;这相当于 FSDP 的 fsdp_state_dict_type: FULL_STATE_DICT

对于大型模型,将模型合并到单个秩可能非常缓慢。

为了更快地进行检查点保存,对于 FSDP,请使用 fsdp_state_dict_type: SHARDED_STATE_DICT,对于 DeepSpeed Zero3,请 使用 zero_to_fp32.py 脚本将分片检查点后转换为 FP32

卸载

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

预取

FSDP 允许两种预取配置 --fsdp_forward_prefetch--fsdp_backward_prefetch 以提高通信/计算的重叠,但会增加额外的内存消耗,请参阅 FSDP 文档。对于 DeepSpeed,预取将在需要时启用,并且根据某些超参数(如 stage3_param_persistence_thresholdstage3_max_reuse_distance 等)启用,这些超参数可以为 Zero3 配置;如果您未在 deepspeed 配置文件中显式设置这些超参数,则 accelerate 可能会自动设置它们。

如果内存允许,为了提高吞吐量,请为 FSDP 设置 fsdp_backward_prefetch: BACKWARD_PRE

模型加载

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

对于 FSDP,只要设置 --fsdp_cpu_ram_efficient_loading trueaccelerate 就会自动将 sync_module_states 设置为 true。为了进行内存高效加载,权重将仅加载到单个秩中,因此需要 sync_module_states 将权重广播到其他秩。

模型

FSDP 需要显式 --fsdp_auto_wrap_policy 才能让算法决定如何安排 all-gather 和 reduce-scatter 操作。但对于 DeepSpeed,这对于用户是透明的。

对于 FSDP,只需设置 fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP。使用最新的 transformers 版本,我们尽最大努力为 HF transformers 模型找出合适的 fsdp_transformer_layer_cls_to_wrap。但是,如果您遇到与此相关的错误,请指定它。

参数调用

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

对于 FSDP,当使用 torch.compile 时,请设置 fsdp_use_orig_params: True

训练

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

当使用 DeepSpeed 时,设置 gradient_accumulation_steps: "auto"gradient_clipping: "auto" 以自动获取在 AcceleratorTrainingArguments(如果使用 transformers)中设置的值。

关于数据精度处理的差异

为了讨论 FSDP 和 Deepspeed 中如何处理数据精度,首先概述一下这两个框架中如何处理模型参数是有益的。在将模型/优化器参数分布到 GPU 之前,会涉及参数准备,首先将它们“展平”为一维 torch.Tensor。FSDP/Deepspeed 的实现在这方面有所不同,即这些“展平”的参数存储的 dtype,并且在 torch.Optimizer 如何分配其 dtype 方面存在影响。下表概述了这两个框架的过程;“本地”列表示在每个 GPU 层面发生的进程,因此任何由于向上转换导致的内存开销都应理解为被使用的 GPU 数量均摊。

根据经验,对于使用自动混合精度的稳定训练,所有可训练参数都必须是 torch.float32

进程 本地 框架 详情
加载,即 AutoModel.from_pretrained(..., torch_dtype=torch_dtype)
准备,即创建“扁平参数” FSDP
DeepSpeed
torch_dtype 中创建。
忽略 torch_dtype,在 float32 中创建。
优化器初始化 FSDP
DeepSpeed
torch_dtype 中创建参数
float32 中创建参数
训练步骤,即前向、反向、约减 FSDP
DeepSpeed
遵循 MixedPrecision
遵循 deepspeed_config_file 混合精度设置。
优化器(预步骤) FSDP
DeepSpeed
向上转换(如果有)到 torch_dtype
向上转换到 float32
优化器(实际步骤) FSDP
DeepSpeed
torch_dtype 中发生
float32 中发生。

因此,当使用少量 GPU 的 DeepSpeed 时,请注意由于在准备期间进行向上转换而可能产生的大量内存开销。

使用 FSDP 时,在没有混合精度的情况下,可以以低精度 torch_dtype 操作 torch.Optimizer,这在使用少量 GPU 时可能会有所帮助。

使用混合精度时,FSDP 和 DeepSpeed 将在模型准备步骤中进行向上转换(参见上表)。但请注意,FSDP 随后将以向上转换的精度保存检查点;如果指定了 --zero3_save_16bit_model,Deepspeed 仍然可以保存低精度检查点。

为了阐明上表,请考虑以下具体示例;为简洁起见,将优化器预步骤和实际步骤组合在一起。使用 FSDP,可以以下面所示的两种模式操作,但 DeepSpeed 只能以一种模式操作。

框架 模型加载 (torch_dtype) 混合精度 准备 (本地) 训练 优化器 (本地)
FSDP bf16 默认(无) bf16 bf16 bf16
FSDP bf16 bf16 fp32 bf16 fp32
DeepSpeed bf16 bf16 fp32 bf16 fp32
< > 在 GitHub 上更新