后端
同样可以在本地机器上运行的 Ludwig 配置 / Python 代码,无需任何代码更改即可在远程以分布式方式执行。这种分布式执行包括预处理、训练和批量预测。
在大多数情况下,Ludwig 能够自动检测您是否在支持分布式执行的环境中运行,但您也可以通过命令行参数 --backend
或在 Ludwig 配置 YAML 中提供 backend
部分来明确指定。
backend:
type: ray
cache_dir: s3://my_bucket/cache
cache_credentials: /home/user/.credentials.json
processor:
type: dask
trainer:
strategy: ddp
loader: {}
参数
type
: 作业将如何分布,可选项:local
,ray
,deepspeed
,horovod
。cache_dir
: 预处理数据将写入磁盘的位置,默认为输入数据集的位置。有关更多详细信息,请参阅 云存储cache_credentials
: 用于写入缓存的可选凭证字典(或凭证 JSON 文件路径)。有关更多详细信息,请参阅 云存储processor
: (仅 Ray) 配置分布式数据处理执行的参数。trainer
: (仅 Ray) 配置分布式训练执行的参数。loader
: (仅 Ray) 配置从已处理数据到训练批次的数据加载参数。
处理器¶
processor
部分配置分布式数据处理。local
后端使用 Pandas dataframe 库,它在单个进程中运行,并将整个数据集加载到内存中。为了使数据处理可扩展到大型数据集,我们在 ray
后端支持两种分布式 dataframe 库
dask
: (默认) 分布式 Pandas 的惰性执行版本。modin
: 分布式 Pandas 的即时执行版本。
Dask¶
Dask 是当在 Ray 上使用 Ludwig 时默认的分布式数据处理库。它在数据的并行分区上执行分布式 Pandas 操作。Dask 的一个有利特性是它采用惰性执行,这使得它能够流式处理非常大的数据集,而无需一次将整个数据集保存在分布式内存中。
Dask 的一个缺点是可能需要一些调优才能获得最佳性能。我们在 Ludwig 中暴露了一个用于调优 Dask 的旋钮
parallelism
: 将数据集分割成的分区数量(默认为让 Dask 自动确定)。
Modin¶
Modin 是一个即时执行的分布式 dataframe 库,与 Pandas 的行为非常相似。因为它与 Pandas 的行为几乎完全相同,并且能够将数据集分布到 Ray 集群中,所以需要配置以优化其性能的事项较少。
对 Modin 的支持目前尚处于实验阶段。
示例
backend:
type: ray
processor:
type: modin
训练器¶
trainer
部分配置分布式训练策略。目前我们支持以下策略(下文详细描述),未来将支持更多策略
- 分布式数据并行 (DDP)
- DeepSpeed
- Horovod
以下参数可以为任何分布式策略配置
strategy
:horovod
,ddp
, 或fsdp
之一。use_gpu
: 是否使用 GPU 进行训练(当集群至少有一个 GPU 时,默认为true
)。num_workers
: 用于训练的 Horovod worker 数量(默认为 GPU 数量,如果未找到 GPU,则为 1)。resources_per_worker
: 分配给每个 Horovod worker 的 Ray 资源(如果可用,默认为 1 个 CPU 和 1 个 GPU)。logdir
: 日志应持久化的文件目录路径。max_retries
: Ray actor 失败时的重试次数(默认为 3)。
有关这些参数的更多详细信息,请参阅 Ray Train API。
示例
backend:
type: ray
trainer:
strategy: ddp
use_gpu: true
num_workers: 4
resources_per_worker:
CPU: 2
GPU: 1
在大多数情况下,您无需显式设置这些值,因为 Ludwig 会代表您设置它们以最大化集群中的可用资源。但是,在以下两种情况下显式设置这些值是合理的
- 您的 Ray 集群使用自动扩缩容(在这种情况下,Ludwig 不会知道扩缩容后有多少 GPU 可用)。
- 您的 Ray 集群同时运行多个工作负载(在这种情况下,您可能希望为其他作业保留资源)。
分布式数据并行 (DDP)¶
分布式数据并行(Distributed Data Parallel)或 DDP 是 PyTorch 原生的数据并行库,无需安装任何额外的软件包即可使用。它是使用 ray
后端时的默认策略。
backend:
type: ray
trainer:
strategy: ddp
DeepSpeed¶
DeepSpeed 是一个数据 + 模型并行框架,用于训练参数分布在多个 GPU 上的超大型模型。
使用 DeepSpeed 的主要场景是当您训练的模型太大而无法放入单个 GPU 时(例如,微调 Llama-2 等大型语言模型)。然而,当模型小到足以放入单个 GPU 时,基准测试表明通常最好使用 DDP 或 Horovod 等数据并行框架。
backend:
type: ray
trainer:
strategy: deepspeed
DeepSpeed 附带了许多配置选项,其中大部分可以在 Ludwig 配置中提供,如 DeepSpeed 文档所示。
Ludwig 中当前支持的 DeepSpeed 配置部分包括
zero_optimization
, 控制用于减少训练期间 GPU 内存压力的优化阶段。fp16
, 是否使用 float16 精度进行训练。bf16
, 是否在支持的硬件(例如,Ampere 架构 GPU 及以上)上使用 bfloat16 精度进行训练。
诸如批量大小、梯度累积和优化器参数等其他参数作为正常 Ludwig 配置的 trainer
部分的一部分指定。当使用 DeepSpeed 作为后端时,Ludwig 会自动将这些设置的实现延迟给 DeepSpeed。
使用 ZeRO stage 3、优化器卸载和 bfloat16 的 DeepSpeed 配置示例
backend:
type: ray
trainer:
use_gpu: true
strategy:
type: deepspeed
zero_optimization:
stage: 3
offload_optimizer:
device: cpu
pin_memory: true
bf16:
enabled: true
Horovod¶
Horovod 是一个分布式数据并行框架,针对带宽受限的计算环境进行了优化。它利用 Nvidia 的 NCCL 进行快速的 GPU 到 GPU 通信。
在基准测试中,我们发现 DDP 和 Horovod 的性能几乎相同,因此如果您还没有使用 Horovod,DDP 是在 Ludwig 中开始分布式训练的最简单方法。
示例
backend:
type: ray
trainer:
strategy: horovod
加载器¶
loader
部分配置从已处理数据(通常缓存为 Parquet 格式)到用于训练模型的张量批次的“最后一公里”数据摄取。
大规模训练深度学习模型时,整个链条的强度取决于其最薄弱的环节——换句话说,数据加载管道的速度至少要与 GPU 的前向/后向传递速度一样快,否则整个过程将受到数据加载器的瓶颈限制。
在大多数情况下,Ludwig 的默认设置足以获得良好的数据加载性能,但如果您注意到即使扩大批量大小后 GPU 利用率仍然下降,或者长时间处于 0% 利用率然后才再次飙升,您可能需要调整下面的 loader
参数以提高吞吐量
fully_executed
: 通过将所有块加载到集群内存/存储中来强制对预处理数据集进行完整评估(默认为true
)。如果数据集远大于分配给 Ray 对象存储的总集群内存,并且您注意到训练期间频繁发生对象溢出,请禁用此选项。window_size_bytes
: 以此大小的离散窗口加载和洗牌预处理数据集(默认为null
,表示数据不进行分窗)。如果洗牌花费很长时间(表现为每个训练 epoch 启动需要很长时间),请尝试配置此选项。一般来说,较大的窗口大小会导致更均匀的洗牌(在某些情况下可以提高模型性能),而较小的窗口大小加载速度更快。此设置在对大型数据集运行超参数优化时特别有用。
示例
backend:
type: ray
loader:
fully_executed: false
window_size_bytes: 500000000