torch.DistributedDataParallel复盘

本文详细介绍如何使用PyTorch的DistributedDataParallel (DDP)进行单机多GPU训练。包括初始化进程组、定义数据采样器、配置模型、处理输入数据及调整学习率等方面的关键步骤。
部署运行你感兴趣的模型镜像

用多GPU跑torch程序,DDP是最好的工具。在研究过程中基本是单机多GPU而不是多机多GPU,此处对单机多GPU的情况做一个总结。
import torch.DistributedDataParallel as DDP
import torch.distributed as dist
用法:

  1. 由于是单机多GPU,所以rank == local_rank. 使用argparse从外部获取–local_rank后,加入dist.init_process_group(backend=‘nccl’) 这一句话来初始化。
  2. 数据集方面。使用sampler = th.utils.data.distributed.DistributedSampler(training_set) 来定义training set 的sampler,这样可以保证在训练时,不同GPU使用不同(没有交集)的batch.注意!!!在测试的时候要想清楚测试数据的顺序是不是有影响。例如今天写的代码,要使用前四个测试数据来画图,这个时候shuffle要设为false, sampler也不用定义,一定不能惯性思维。batch_size的设置也要格外留意。
  3. 网络方面,要在.cuda()后加上model = DDP(model, device_ids=[dist.get_rank()], output_device=dist.get_rank()) # 再次强调,在单机多卡的情况下,rank == local_rank,所以在这里直接使用rank就行
  4. .cuda的问题。 在这里,模型和数据不能简单地input.cuda(), model.cuda(),而要在cuda()中指定device,否则会有数据和模型在不同 GPU上的情况。正确的做法是 input.cuda(torch.device(“cuda”, dist.get_rank())).
  5. 学习率要随着batch_size的变化而变化。batch_size增大几倍,学习率就要相应增大几倍。

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

### PyTorch `torch.nn.parallel.DistributedDataParallel` 使用指南与实现原理 #### 使用指南 `torch.nn.parallel.DistributedDataParallel`(DDP)是 PyTorch 提供的一种高效的数据并行化方法,适用于单节点多 GPU 和多节点多 GPU 的硬件拓扑结构。DDP 的核心思想是将模型复制到每个进程中,每个进程处理一部分数据,并通过分布式通信机制同步梯度。 使用 DDP 的基本步骤如下: 1. **初始化分布式环境** 在使用 DDP 之前,必须初始化分布式环境。可以通过 `torch.distributed.init_process_group` 来设置后端(如 `nccl`、`gloo` 等)和通信参数。通常在脚本的开头调用此函数。 ```python import torch.distributed as dist dist.init_process_group(backend='nccl') ``` 2. **创建模型并封装为 DDP** 创建模型后,将其封装为 `DistributedDataParallel` 对象。这样,模型的参数将被自动同步到所有进程中。 ```python from torch.nn.parallel import DistributedDataParallel as DDP model = DDP(model) ``` 3. **准备数据加载器** 为了确保每个进程只处理数据的一部分,需要使用 `DistributedSampler`。该采样器会自动将数据划分为多个子集,并分配给不同的进程。 ```python from torch.utils.data.distributed import DistributedSampler train_sampler = DistributedSampler(dataset) train_loader = DataLoader(dataset, batch_size=..., sampler=train_sampler) ``` 4. **运行训练脚本** 使用 `torch.distributed.launch` 启动训练脚本。该工具会自动启动多个进程,并分配 GPU。命令模板如下: ```bash CUDA_VISIBLE_DEVICES=1,2,3 python -m torch.distributed.launch --nproc_per_node=3 train.py ``` 其中,`--nproc_per_node` 参数指定每个节点上使用的 GPU 数量,`CUDA_VISIBLE_DEVICES` 指定可见的 GPU 设备。 5. **训练模型** 在训练过程中,每个进程独立进行前向传播和反向传播,梯度通过 `all-reduce` 操作在所有进程中同步,确保模型参数的一致性。 #### 实现原理 `DistributedDataParallel` 的实现基于分布式计算的基本原理,主要包括以下几个方面: - **数据并行化** DDP 是一种数据并行化方法,即将数据划分为多个部分,每个进程处理一部分数据。每个进程拥有完整的模型副本,并在本地数据上进行前向和反向传播。 - **梯度同步** 在反向传播完成后,每个进程计算的梯度需要通过 `all-reduce` 操作在所有进程中同步。`all-reduce` 是一种分布式通信操作,它将所有进程的梯度求和,并将结果广播给所有进程。这样,所有进程的模型参数保持一致。 - **进程组管理** DDP 支持自定义进程组,允许用户将不同的模型或模块分配到不同的进程组中。这可以通过 `process_group` 参数实现,通常使用 `torch.distributed.new_group` 创建新的进程组。 ```python process_group = torch.distributed.new_group(range(torch.distributed.get_world_size())) model = DDP(model, process_group=process_group) ``` - **单节点与多节点支持** DDP 不仅支持单节点多 GPU 的训练,还支持多节点多 GPU 的训练。这意味着可以在多个计算节点上部署模型,充分利用集群资源。 - **优化的通信效率** DDP 通过优化通信机制(如使用 `NCCL` 后端)来提高分布式训练的效率。`NCCL` 是 NVIDIA 提供的一种高效的 GPU 通信库,特别适合多 GPU 的场景。 #### 优势与适用场景 - **优势** - **更高的并行加速比**:相比 `DataParallel`,DDP 提供了更高的并行加速比,尤其是在多 GPU 和多节点的场景下。 - **更好的可扩展性**:DDP 支持多节点多 GPU 的硬件拓扑结构,适合大规模分布式训练。 - **更低的通信开销**:DDP 使用高效的通信机制(如 `all-reduce` 和 `NCCL`),减少了通信开销。 - **适用场景** - **大规模模型训练**:当模型参数和数据量较大时,DDP 可以有效利用多 GPU 资源,加速训练过程。 - **多节点集群**:DDP 适用于多节点集群环境,能够充分利用集群的计算能力。 #### 注意事项 - **初始化分布式环境**:在使用 DDP 之前,必须正确初始化分布式环境,否则会导致错误。 - **数据划分**:使用 `DistributedSampler` 确保每个进程只处理数据的一部分,避免重复训练。 - **进程组管理**:如果需要将不同的模块分配到不同的进程组中,必须正确创建和管理进程组。 - **设备分配**:每个进程应绑定到特定的 GPU 设备,避免资源竞争。 #### 示例代码 以下是一个简单的 DDP 训练示例代码: ```python import torch import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP from torch.utils.data.distributed import DistributedSampler from torch.utils.data import DataLoader, Dataset class SimpleDataset(Dataset): def __init__(self, size=1000): self.data = torch.randn(size, 10) self.labels = torch.randint(0, 2, (size,)) def __len__(self): return len(self.data) def __getitem__(self, idx): return self.data[idx], self.labels[idx] def train(): # 初始化分布式环境 dist.init_process_group(backend='nccl') # 创建模型 model = torch.nn.Linear(10, 2).cuda() ddp_model = DDP(model) # 创建数据集和数据加载器 dataset = SimpleDataset() train_sampler = DistributedSampler(dataset) train_loader = DataLoader(dataset, batch_size=32, sampler=train_sampler) # 定义损失函数和优化器 loss_fn = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(ddp_model.parameters(), lr=0.001) # 训练循环 for epoch in range(10): for inputs, labels in train_loader: inputs, labels = inputs.cuda(), labels.cuda() outputs = ddp_model(inputs) loss = loss_fn(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() print(f"Epoch {epoch} completed") if __name__ == "__main__": train() ``` ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值