Accelerate 文件
FSDP 對比 DeepSpeed
並獲得增強的文件體驗
開始使用
FSDP 對比 DeepSpeed
Accelerate 透過整合 PyTorch FSDP 和 Microsoft DeepSpeed 這兩個功能強大的分散式訓練工具,提供了訓練框架的靈活性。本教程旨在比較兩者的異同,以便使用者能夠在這兩個框架之間無縫切換。
要在框架之間切換,我們建議使用 accelerate launch 命令,透過 --config_file 傳入正確的配置檔案,或者直接為 FSDP 和 DeepSpeed 傳入相應的引數。
DeepSpeed 的 Accelerate 配置示例請參見此處,FSDP 的配置示例請參見此處,或者在示例庫中的“啟動配置”部分查詢。
本教程僅適用於單節點、多 GPU 場景。
配置功能
模型張量被分成不同的 GPU 以便擴充套件模型大小;這在 FSDP 中稱為“分片”(*sharding*),在 DeepSpeed 中稱為“分割槽”(*partitioning*)。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 | truecpucpu | 全部或不解除安裝 |
| 模型載入 | FSDP DeepSpeed | --fsdp_cpu_ram_efficient_loading--zero3_init_flag | truetrue | 僅限 ZeRO 3 |
| 高效檢查點 | FSDP DeepSpeed | --fsdp_state_dict_type--zero3_save_16bit_model | SHARDED_STATE_DICTtrue | 僅限 ZeRO 3 |
| 權重預取 | FSDP DeepSpeed | --fsdp_forward_prefetch--fsdp_backward_prefetch無 | trueBACKWARD_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_stage,DeepSpeedPlugin.hf_ds_config 可用於傳遞 --deepspeed_config_file。
FSDP 也可以透過 FullyShardedDataParallelPlugin 配置,例如,FullyShardedDataParallelPlugin.sharding_strategy 等同於 --fsdp_sharding_strategy。
檢查點
請注意,FSDP 可以透過 --fsdp_state_dict_type 配置來儲存完整或分片檢查點。
對於 DeepSpeed Zero3,可以傳入 --zero3_save_16bit_model true,它方便地將模型整合到一個 rank 中並儲存;這相當於 FSDP 中的 fsdp_state_dict_type: FULL_STATE_DICT。
對於大型模型,將模型整合到一個 rank 中可能會非常慢。
為了加快檢查點儲存速度,對於 FSDP,請使用 fsdp_state_dict_type: SHARDED_STATE_DICT;對於 DeepSpeed Zero3,請使用 zero_to_fp32.py 指令碼來後轉換分片檢查點。
解除安裝
FSDP 只允許*全部或不解除安裝*(即,要麼解除安裝所有引數、梯度和最佳化器,要麼將它們全部保留在 GPU 中),但 DeepSpeed 可以不同地解除安裝引數和最佳化器。此外,DeepSpeed 還支援解除安裝到 NVME。
預取
FSDP 允許兩種預取配置:--fsdp_forward_prefetch 和 --fsdp_backward_prefetch,以犧牲額外記憶體為代價提高通訊/計算重疊,參見FSDP 文件。對於 DeepSpeed,預取會在需要時開啟,並且它會根據某些超引數(如 stage3_param_persistence_threshold、stage3_max_reuse_distance 等)開啟,這些超引數可以為 Zero3 配置;如果您未在 deepspeed 配置檔案中明確設定這些超引數,accelerate 可能會自動設定它們。
對於 FSDP,如果記憶體允許,請將 fsdp_backward_prefetch: BACKWARD_PRE 設定為提高吞吐量。
模型載入
FSDP 需要顯式設定 --fsdp_cpu_ram_efficient_loading true 來啟用高效模型載入,而 transformers 在使用 DeepSpeed Zero3 時會自動啟用類似功能。
對於 FSDP,當設定 --fsdp_cpu_ram_efficient_loading true 時,accelerate 會自動將 sync_module_states 設定為 true。對於 RAM 高效載入,權重將只加載到單個 rank 中,因此需要 sync_module_states 將權重廣播到其他 rank。
模型
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" 將自動選擇在 Accelerator 或 TrainingArguments(如果使用 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.Optimizer 以低精度 torch_dtype 執行,這在使用少量 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 |