PyTorch分布式DPP启动方式
本篇主要讲解单卡到分布式中DDP(DistributeDataParallel )的使用基础,包括如何使用DDP和相关的一些基础问题。
主要涵盖如下问题:
1、单卡到分布式的过程中,用户代码需要怎么调整?
单卡变成分布式中处理过程差异,以及用户要干什么。
2、DDP的启动方式有几种? 差异在哪?
DDP的启动方式与代码修改如何对应,单进程单卡、单进程多卡、单卡多进程的模式如何启动。
选择分布式前用户首先需要明白自己的场景,是需要数据并行与还是需要考虑模型并行。因为DDP指的是数据并行的分布式,一般适用于单张GPU能够加载一个完全的模型,这一点在PyTorch的-DDP官网文档有说明。明确这点后,再继续往下看:
1 基本使用
直接放一个简单的列子来看一下,单卡到多卡用户的代码如何修改。这里采用一个简单的MNIST分类例子来分析,从单卡代码到分布式变动了哪些地方。
1.1 单卡版本
import torch
import torchvision
import torch.utils.data.distributed
from torchvision import transforms
def main():
# 数据加载部分,直接利用torchvision中的datasets
trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))])
data_set = torchvision.datasets.MNIST("./", train=True, transform=trans, target_transform=None, download=True)
data_loader_train = torch.utils.data.DataLoader(dataset=data_set, batch_size=256)
# 网络搭建,调用torchvision中的resnet
net = torchvision.models.resnet101(num_classes=10)
net.conv1 = torch.nn.Conv1d(1, 64, (7, 7), (2, 2), (3, 3), bias=False)
net = net.cuda()
# 定义loss与opt
criterion = torch.nn.CrossEntropyLoss()
opt = torch.optim.Adam(net.parameters(), lr=0.001)
# 网络训练
for epoch in range(10):
for i, data in enumerate(data_loader_train):
images, labels = data
images = torch.tensor(images).cuda()
labels = torch.tensor(labels).cuda()
opt.zero_grad()
outputs = net(images)
loss = criterion(outputs, labels)
loss.backward()
opt.step()
if i % 10 == 0:
print("loss: {}".format(loss.item()))
# 保存checkpoint
torch.save(net, "my_net.pth")
if __name__ == "__main__":
main()
1.2 多卡分布式
import torch
import torchvision
import torch.utils.data.distributed
from torchvision import transforms
def main():
trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))])
data_set = torchvision.datasets.MNIST("./", train=True, transform=trans, target_transform=None, download=True)
data_loader_train = torch.utils.data.DataLoader(dataset=data_set, batch_size=256)
net = torchvision.models.resnet101(num_classes=10)
net.conv1 = torch.nn.Conv1d(1, 64, (7, 7), (2, 2), (3, 3), bias=