快速浏览
根据你的训练环境(如 torchrun、DeepSpeed 等)和可用硬件,有多种方法可以启动和运行你的代码。Accelerate 提供了一个统一的接口,用于在不同的分布式设置中启动和训练,使你可以专注于 PyTorch 训练代码,而不是适应这些不同设置的复杂性。这使你可以轻松地将 PyTorch 代码扩展到分布式设置中,使用 GPU 和 TPU 等硬件进行训练和推理。Accelerate 还提供了大模型推理功能,使加载和运行通常无法放入内存的大型模型变得更加容易。
本快速浏览介绍了 Accelerate 的三个主要功能:
- 用于分布式训练脚本的统一命令行启动接口
- 用于适应 PyTorch 训练代码以在不同分布式设置中运行的训练库
- 大模型推理
统一启动接口
Accelerate 通过从 accelerate config
命令生成的统一配置文件,自动为任何给定的分布式训练框架(如 DeepSpeed、FSDP 等)选择适当的配置值。在某些情况下,例如使用 SLURM 时,你也可以显式地将配置值传递给命令行。
但在大多数情况下,你应该始终先运行 accelerate config
,以帮助 Accelerate 了解你的训练设置。
accelerate config
accelerate config
命令会在 Accelerate 的缓存文件夹中创建并保存一个 default_config.yaml
文件。此文件存储了你的训练环境的配置信息,有助于 Accelerate 根据你的机器正确启动训练脚本。
配置好环境后,你可以使用 accelerate test
来测试你的设置,该命令会启动一个简短的脚本来测试分布式环境。
accelerate test
TIP
在 accelerate test
或 accelerate launch
命令中添加 --config_file
以指定配置文件的位置,如果配置文件保存在非默认位置(如缓存中)。
一旦你的环境设置完成,使用 accelerate launch
启动你的训练脚本!
accelerate launch path_to_script.py --args_for_the_script
要了解更多信息,请查看 启动分布式代码 教程,以获取有关启动脚本的更多详细信息。
我们还提供了一个 配置库,展示了多种预设的 最小 示例配置,适用于你可以运行的各种设置。
适应训练代码
Accelerate 的下一个主要功能是 [Accelerator
] 类,它使你的 PyTorch 代码能够适应不同的分布式设置。
你只需要在训练脚本中添加几行代码,即可使其在多个 GPU 或 TPU 上运行。
+ from accelerate import Accelerator
+ accelerator = Accelerator()
+ device = accelerator.device
+ model, optimizer, training_dataloader, scheduler = accelerator.prepare(
+ model, optimizer, training_dataloader, scheduler
+ )
for batch in training_dataloader:
optimizer.zero_grad()
inputs, targets = batch
- inputs = inputs.to(device)
- targets = targets.to(device)
outputs = model(inputs)
loss = loss_function(outputs, targets)
+ accelerator.backward(loss)
optimizer.step()
scheduler.step()
- 在训练脚本的开头导入并实例化 [
Accelerator
] 类。[Accelerator
] 类初始化分布式训练所需的一切,并根据代码的启动方式自动检测你的训练环境(单机 GPU、多 GPU 机器、多机多 GPU 或 TPU 等)。
from accelerate import Accelerator
accelerator = Accelerator()
- 移除模型和输入数据上的
.cuda()
调用。[Accelerator]
类会自动将这些对象放置到适当的设备上。
WARNING
这一步是 可选的,但最佳实践是让 Accelerate 处理设备放置。你也可以通过在初始化 [Accelerator]
时传递 device_placement=False
来禁用自动设备放置。如果你希望显式地将对象放置到设备上,使用 .to(device)
时,请确保使用 accelerator.device
。例如,如果你在将模型放置到 accelerator.device
之前创建了一个优化器,训练在 TPU 上会失败。
WARNING
Accelerate 默认情况下不会使用非阻塞传输进行自动设备放置,这可能导致不必要的 CUDA 同步。你可以在初始化 [Accelerator]
时通过传递一个 dataloader_config
参数为 non_blocking=True
的 [~utils.dataclasses.DataLoaderConfiguration]
来启用非阻塞传输。通常情况下,非阻塞传输只有在数据加载器也设置了 pin_memory=True
时才会生效。请注意,从 GPU 到 CPU 的非阻塞传输可能会导致在未准备好张量上执行 CPU 操作,从而产生错误结果。
device = accelerator.device
- 在创建后立即将所有相关的 PyTorch 对象(优化器、模型、数据加载器、学习率调度器)传递给 [
~Accelerator.prepare
] 方法。此方法将模型包装在一个针对你的分布式设置优化的容器中,使用 Accelerate 版本的优化器和调度器,并创建一个分片版本的数据加载器以在 GPU 或 TPU 之间进行分布。
model, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
model, optimizer, train_dataloader, lr_scheduler
)
- 将
loss.backward()
替换为 [~Accelerator.backward
],以使用适用于你训练设置的正确backward()
方法。
accelerator.backward(loss)
阅读 Accelerate 的内部机制 指南,了解有关 Accelerate 如何适应你的代码的更多详细信息。
分布式评估
要执行分布式评估,请将你的验证数据加载器传递给 [~Accelerator.prepare
] 方法:
validation_dataloader = accelerator.prepare(validation_dataloader)
在你的分布式设置中,每个设备只接收评估数据的一部分,这意味着你应该使用 [~Accelerator.gather_for_metrics
] 方法将预测结果汇总在一起。此方法要求每个进程中的所有张量大小相同,因此,如果每个进程中的张量大小不同(例如,在批处理中动态填充到最大长度时),你应该使用 [~Accelerator.pad_across_processes
] 方法将张量填充到跨进程的最大大小。请注意,张量需要是一维的,并且我们在第一个维度上连接张量。
for inputs, targets in validation_dataloader:
predictions = model(inputs)
# Gather all predictions and targets
all_predictions, all_targets = accelerator.gather_for_metrics((predictions, targets))
# Example of use with a *Datasets.Metric*
metric.add_batch(all_predictions, all_targets)
对于更复杂的情况(例如 2D 张量,不想连接张量,3D 张量的字典),你可以在 gather_for_metrics
中传递 use_gather_object=True
。这将返回收集后的对象列表。请注意,使用 GPU 张量时,此方法支持不佳且效率低下。
TIP
数据集末尾的数据可能会被重复,以便批处理可以均匀地分配给所有工作进程。[
~Accelerator.gather_for_metrics]
方法会自动移除重复的数据,以计算更准确的指标。
大模型推理
Accelerate 的大模型推理有两个主要功能,[
~accelerate.init_empty_weights]
和 [
~accelerate.load_checkpoint_and_dispatch]
,用于加载通常无法完全放入内存的大模型进行推理。
TIP
请参阅 处理大模型推理 指南,以更好地了解大模型推理的工作原理。
空权重初始化
[
~accelerate.init_empty_weights]
上下文管理器通过创建一个 模型骨架 并在每次创建参数时将其移动和放置到 PyTorch 的 meta 设备上来初始化任意大小的模型。这样,不是所有权重都会立即加载,而是一次只加载模型的一小部分到内存中。
例如,加载一个空的 Mixtral-8x7B 模型所需的内存显著少于在 CPU 上完全加载模型和权重所需的内存。
from accelerate import init_empty_weights
from transformers import AutoConfig, AutoModelForCausalLM
config = AutoConfig.from_pretrained("mistralai/Mixtral-8x7B-Instruct-v0.1")
with init_empty_weights():
model = AutoModelForCausalLM.from_config(config)
加载和分发权重
[~accelerate.load_checkpoint_and_dispatch
] 函数将完整或分片的检查点加载到空模型中,并自动将权重分发到所有可用的设备上。
device_map
参数决定了每个模型层的放置位置,指定为 "auto"
时,会首先将它们放置在 GPU 上,然后是 CPU,最后如果内存仍然不足,则作为内存映射张量放置在硬盘上。使用 no_split_module_classes
参数来指示哪些模块不应被拆分到不同设备上(通常是那些具有残差连接的模块)。
from accelerate import load_checkpoint_and_dispatch
model = load_checkpoint_and_dispatch(
model, checkpoint="mistralai/Mixtral-8x7B-Instruct-v0.1", device_map="auto", no_split_module_classes=['Block']
)
下一步
现在你已经了解了 Accelerate 的主要功能,接下来的步骤可以包括: