Transformers 多卡训练统一配置:基于 Accelerate 的 FSDP、DeepSpeed 与 DDP 接入指南
本文基于 Transformers 仓库的 Accelerate 官方文档 展开,讲解 Accelerate 如何作为 Trainer 的统一分布式训练后端,并给出两条完整的配置路径:其一,通过 accelerate config 生成的 YAML 配置文件直接驱动训练;其二,通过 TrainingArguments 中的 fsdp_config、deepspeed、ddp_* 等参数在代码内配置。文中结合 Trainer 源码 与 TrainingArguments 源码 剖析配置的实际生效位置,读完你可以掌握从 1 卡 DDP 到 8 卡 FSDP 的完整训练环境搭建方案。
Accelerate 在 Trainer 中扮演什么角色
Accelerate 为 FSDP、DeepSpeed 等分布式训练后端提供统一接口。它会自动检测运行环境(GPU 数量、分布式后端、混合精度设置等),并据此完成训练配置——无论你是在单卡上跑 DDP,还是在 8 卡上跑 FSDP。
具体来说,Accelerate 会完成三件核心工作:
- 用合适的分布式包装器(wrapper)包装模型;
- 将模型移动到正确的设备(device)上;
- 创建与之兼容的优化器(optimizer)。
训练过程中,Accelerate 使用自身的 backward() 方法处理混合精度下的梯度缩放(gradient scaling)。Trainer 本身并不直接触碰这些分布式细节,而是调用相应的 Accelerate API,把所有分布式机制的委托交给 Accelerate。
从源码结构看,这一“委托”关系在 src/transformers/trainer.py 的 Trainer.create_accelerator_and_postprocess() 方法中得到印证:该方法读取 TrainingArguments 中的 Accelerate 相关设置,构造 Accelerator 实例,并在创建后执行 FSDP / DeepSpeed 的后置配置与冲突校验。原文档指出:“Trainer calls the appropriate Accelerate APIs and delegates all distributed mechanics to Accelerate”,即 TrainingArguments 是用户侧的入口,Accelerate 是实际执行者。
TrainingArguments 支持两种配置方式:Accelerate 配置文件或 TrainingArguments 参数,下文分别介绍。
方式一:使用 Accelerate 配置文件(适合脚本化启动)
运行 accelerate config 命令,按提示回答关于硬件与训练设置的问题,它会在你的缓存目录中生成 default_config.yaml 文件。原文档给出的是一个 FSDP 场景的示例,完整配置如下:
compute_environment: LOCAL_MACHINE
distributed_type: FSDP
fsdp_config:
fsdp_version: 2
fsdp_reshard_after_forward: true
fsdp_cpu_offload: false
fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
fsdp_cpu_ram_efficient_loading: true
fsdp_activation_checkpointing: false
fsdp_state_dict_type: SHARDED_STATE_DICT
fsdp_transformer_layer_cls_to_wrap: LlamaDecoderLayer
mixed_precision: bf16
num_machines: 1
num_processes: 4
各字段的含义(结合 TrainingArguments 中 FSDP 参数文档 对照):
distributed_type: FSDP:声明使用 FSDP 作为分布式类型,num_processes: 4表示 4 个进程(通常对应 4 卡);fsdp_version: 2:使用 FSDP2;fsdp_reshard_after_forward:前向之后重新分片参数(true省显存,false则在前反向之间保持参数已收集状态,省去 re-all-gather 但峰值显存更高);fsdp_cpu_offload:是否将参数/梯度卸载到 CPU 以节省显存;fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP:按 Transformer 层自动包装,配合fsdp_transformer_layer_cls_to_wrap: LlamaDecoderLayer指定要包装的层类名(区分大小写);fsdp_cpu_ram_efficient_loading: true:只在第一个进程加载预训练权重,其余进程以空权重启动并接收广播;fsdp_state_dict_type: SHARDED_STATE_DICT:按 rank 分片保存检查点(每个 rank 一个文件),对大模型更快;mixed_precision: bf16:bfloat16 混合精度;fsdp_activation_checkpointing:FSDP 侧的激活重计算,注意它与TrainingArguments的gradient_checkpointing不能同时为True(源码中会直接抛出ValueError,见 trainer.py)。
配置完成后,用 accelerate launch 启动基于 Trainer 的脚本:
accelerate launch train.py
Accelerate 会读取该配置文件来完成训练环境的搭建。此时 TrainingArguments.fsdp_config 和 TrainingArguments.deepspeed 参数是多余的,因为 Accelerate 配置文件已经覆盖了相同的设置。
用 accelerator_config 补充无专用参数的选项
TrainingArguments.accelerator_config 接受那些没有专门顶层参数的设置。例如,将 non_blocking=True 与 dataloader_pin_memory 一起设置,可以让数据传输与计算重叠,提高 GPU 吞吐:
from transformers import TrainingArguments
TrainingArguments(
...,
dataloader_pin_memory=True,
accelerator_config={
"non_blocking": True,
},
)
源码印证了这一建议的必要性:在 Trainer.create_accelerator_and_postprocess() 中,如果开启了 non_blocking 却没有开启 dataloader_pin_memory,Trainer 会主动打印告警——“non_blocking is enabled but dataloader_pin_memory is not. For the best performance, it's recommended to enable both.” 两个开关需配合使用才能发挥异步数据搬运的收益。
accelerator_config 支持的完整键值(来自 TrainingArguments 参数文档):
| 选项 | 默认值 | 说明 |
|---|---|---|
split_batches |
False |
是否将批跨设备切分。True 时所有设备上的实际批大小相同(总数需能被进程数整除);False 时每设备各自获得指定批大小 |
dispatch_batches |
IterableDataset 为 True,否则 False |
True 时仅主进程迭代 dataloader 并向各设备分发批次 |
even_batches |
True |
从数据集头部复制样本,保证所有 worker 批大小一致 |
use_seedable_sampler |
True |
使用完全可播种的随机采样器以保证可复现性 |
use_configured_state |
False |
复用已初始化的 AcceleratorState/PartialState 而非新建,可能与超参调优冲突 |
accelerator_config 本身支持三种传入形式:JSON 配置文件路径(如 "accelerator_config.json")、字典、或 AcceleratorConfig 实例(定义于 src/transformers/trainer_pt_utils.py)。规范化逻辑见 training_args.py:None 时使用默认 AcceleratorConfig(),字典通过 AcceleratorConfig(**dict) 实例化,字符串路径调用 AcceleratorConfig.from_json_file() 加载;直接传未实例化的类会被明确拒绝。
方式二:通过 TrainingArguments 配置后端(适合纯 Python 脚本)
如果不想依赖 accelerate config 生成的 YAML,也可以直接把后端专属配置传给 TrainingArguments。Trainer.create_accelerator_and_postprocess() 方法会读取这些设置并配置训练。按后端不同,有三种写法:
FSDP:fsdp + fsdp_config
向 TrainingArguments.fsdp_config 传入 JSON 配置文件或字典(fsdp 置 True 开启):
from transformers import TrainingArguments
TrainingArguments(
...,
fsdp=True,
fsdp_config="path/to/fsdp.json",
)
fsdp_config 支持的键与默认值(摘自 training_args.py 参数文档):
version(默认2):2为 FSDP2,1为旧版 FSDP1;reshard_after_forward(默认True):前向后重新分片,False可避免 re-all-gather 但峰值显存更高;cpu_offload(默认False):将参数与梯度卸载到 CPU;activation_checkpointing(默认False):反向时重计算激活以省显存,使用 FSDP 时优先于gradient_checkpointing(后者会在反向中引入冗余的 all-gather);cpu_ram_efficient_loading(默认False):仅首进程加载检查点后广播;state_dict_type(默认"FULL_STATE_DICT"):"FULL_STATE_DICT"为单个 HF 兼容文件,"SHARDED_STATE_DICT"为每 rank 一个文件;auto_wrap_policy(默认"TRANSFORMER_BASED_WRAP"):可选TRANSFORMER_BASED_WRAP、SIZE_BASED_WRAP、NO_WRAP;transformer_layer_cls_to_wrap:要包装的 Transformer 层类名,通常可省略——包装策略会回退到模型的_no_split_modules,覆盖绝大多数 transformers 模型;min_num_params(默认0):SIZE_BASED_WRAP策略下每个模块的最小参数量;xla/xla_fsdp_settings/xla_fsdp_grad_ckpt:PyTorch/XLA FSDP 实验选项。
注意 save_only_model 与 SHARDED_STATE_DICT 检查点格式不兼容,同时设置会在 trainer.py 触发 ValueError。完整 FSDP 指南可参阅 FSDP 文档。
DeepSpeed:deepspeed 参数
向 TrainingArguments.deepspeed 传入 JSON 配置文件或字典:
from transformers import TrainingArguments
TrainingArguments(
...,
deepspeed="path/to/ds_config.json",
)
使用 ZeRO 初始化时,需要在初始化 TrainingArguments 之后(而非之前)实例化模型,否则 ZeRO 不会生效(见 参数文档中的提示)。另外源码中校验:auto_find_batch_size 尚不支持 DeepSpeed ZeRO-3,需改用 ZeRO-1/2 或 FSDP(trainer.py);save_only_model 也不能与 load_best_model_at_end 同时用于 DeepSpeed/FSDP。完整 DeepSpeed 指南见 DeepSpeed 文档。
DDP:ddp_* 顶层字段
DDP 通过 TrainingArguments 的顶层字段直接配置:
from transformers import TrainingArguments
TrainingArguments(
...,
ddp_backend="nccl",
ddp_find_unused_parameters=False,
ddp_bucket_cap_mb=25,
ddp_timeout=1800,
)
各字段的定义与默认值见 training_args.py:
ddp_backend:分布式后端,可选值包括"nccl"、"gloo"、"mpi"、"xccl"、"hccl"(以及源码 choices 中列出的"cncl"、"mccl");ddp_find_unused_parameters:传给DistributedDataParallel的find_unused_parameters;默认在使用梯度检查点时为False,否则为True;ddp_bucket_cap_mb:传给DistributedDataParallel的bucket_cap_mb;ddp_broadcast_buffers:传给DistributedDataParallel的broadcast_buffers,使用梯度检查点时默认False;ddp_static_graph:传给DistributedDataParallel的static_graph;ddp_timeout:torch.distributed.init_process_group的超时时间(秒),默认1800,用于避免分布式运行中慢操作导致的 GPU 套接字超时。
DDP 适用于模型能装入单卡的数据并行场景,详见 DDP 文档。
源码深潜:create_accelerator_and_postprocess 做了什么
Trainer 在初始化阶段调用 create_accelerator_and_postprocess(),其内部流程可以概括为:
- 梯度累积接管:Trainer 自己管理梯度累积(gradient accumulation steps),因此显式把 Accelerate 的
gradient_accumulation_kwargs中num_steps置为 1,避免二次除法;若AcceleratorConfig的num_steps与TrainingArguments的gradient_accumulation_steps > 1冲突,会直接报错(trainer.py#L773-L795)。 - 构建 DataLoader 配置:从
accelerator_config中弹出split_batches、dispatch_batches、even_batches、use_seedable_sampler四个键构造DataLoaderConfiguration,并把data_seed注入其中;non_blocking也被弹出并写入 dataloader 配置(trainer.py#L797-L812)。 - 构建插件与 Accelerator:若
fsdp_plugin_args非空,则实例化FullyShardedDataParallelPlugin;随后通过_build_accelerator_args()汇总 dataloader 配置、FSDP 插件、梯度累积插件(以及可选的TorchDynamoPlugin)创建Accelerator对象(trainer.py#L816-L829)。 - 能力标记与后置校验:根据
accelerator.state中是否存在fsdp_plugin/deepspeed_plugin设置is_fsdp_enabled/is_deepspeed_enabled,并执行前文提到的几项兼容性校验(激活检查点冲突、ZeRO-3 与auto_find_batch_size、save_only_model与分片状态字典等)。
这一调用链印证了原文档的主张:用户只需在配置层表达意图(YAML 或 TrainingArguments),设备移动、包装、优化器创建、梯度缩放等机制全部由 Accelerate 经由该方法落地。
适用前提与版本约束
- Accelerate 是可选依赖:
TrainingArguments在 Accelerate 缺失或版本过低时会要求安装accelerate>=1.1.0(版本下限定义于 src/transformers/utils/import_utils.py);torch_compile相关插件功能则要求 Accelerate1.2.0(trainer.py)。 - 两种方式(配置文件 /
TrainingArguments参数)覆盖相同的配置面,按原文档建议,使用accelerate launch时不必再重复设置fsdp_config/deepspeed参数,避免配置来源不一致。 accelerator_config的split_batches=True会覆盖per_device_train_batch_size(总批大小被均分到所有进程),设置前请确认数据集大小可被进程数整除。
延伸阅读
- DDP 文档:模型能装入单卡时的数据并行训练;
- FSDP 文档:将参数、梯度与优化器状态分片到多张 GPU;
- DeepSpeed 文档:ZeRO 优化与参数/优化器状态卸载;
- Trainer 文档:
Trainer的整体使用方式,与本文的分布式配置互补。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00