pytorch的多gpu训练

1.多GPU训练,出现out of memory

出现情景:预训练模型是使用gpu0训练得到,然后要在多gpu的服务器上进行微调,使用gpu id为[4,5,6,7],然后出现报错如下:

cuda runtime error (2) : out of memory at /pytorch/aten/src/THC/THCTensorRandom.cu:25

错误原因分析:在加载预训练模型的位置报错,在台式机(只有一块gpu)将模型加载打印输出参数:

代码:

checkpoint = torch.load("/home/final.pth")
for k, v in checkpoint.items():
     print(k)
     print(v)

打印输出出现:

 

发现模型加载的时候就将参数传入到gpu当中,而我在服务器上出现报错应该是模型参数直接加载到了gpu id = 0 的显卡上,但是gpu id= 0的显卡上显存已经满了;所以报出了 内存溢出的问题;但是我在操作的时候,直接使用gpu id = 4的显卡也会出现错误,出现错误的模型加载代码如下:

if conf.pretrained == True:
      checkpoint = torch.load("./model_mobilefacenet.pth",
map_location={'cuda:1':'cuda:0'})
      self.model_mobile.load_state_dict(checkpoint)

然后修改成这样也出错:

if conf.pretrained == True:
      checkpoint = torch.load("./model_mobilefacenet.pth",
,map_location=lambda storage, loc: storage.cuda(0))
      self.model_mobile.load_state_dict(checkpoint)

而自己在进行多gpu训练时,代码如下:

conf.device = torch.device("cuda:4" if torch.cuda.is_available() else "cpu")#从那块gpu开始训练就写那块gpu,这里gpu_id=0

 if torch.cuda.device_count() > 1:
     self.model = torch.nn.DataParallel(self.model, device_ids=[4,5,6,7])
     self.model.to(conf.device)
     self.model_mobile = torch.nn.DataParallel(self.model_mobile, device_ids=[4,5,6,7])
self.model_mobile.to(conf.device)

最终修改成为这样就没有报错了:

self.model_mobile = MobileFaceNet(conf.embedding_size)
if conf.pretrained == True:
      checkpoint = torch.load("./model_mobilefacenet.pth") 
      self.model_mobile.load_state_dict(checkpoint)

if torch.cuda.device_count() > 1:
    self.model = torch.nn.DataParallel(self.model)
    self.model_mobile = torch.nn.DataParallel(self.model_mobile)

训练时,使用如下命名行:

CUDA_VISIBLE_DEVICES="4,5,6,7" python train.py

同时在训练脚本头文件位置加入:

os.environ["CUDA_VISIBLE_DEVICES"] = "4,5,6,7"

这样就是使用多gpu训练,并且不会报错。

不过我也没搞太清楚,之前不加载预训练模型的时候,前一种设置多gpu训练的方式是可用的,但是现在不能用了,有没有小伙伴知道了,希望告知;

原因:加载预训练模型时,参数中带有gpu id的信息,而这个信息是与我训练使用的gpu id不一样,所以加载了预训练模型后,之前的方法不可以用了;

2.pytorch使用多gpu训练时gpu负载不均衡的问题

第一个GPU的计算量往往比较大,后面的gpu占用较少,当将batch size设置变大,训练会因为第一块gpu内存溢出而终止训练,但是其他gpu的显存有可能还没有占到总量的一半;

原因:所有loss都是汇总在主gpu(第一块gpu)中计算;

参考(https://blog.csdn.net/weixin_40087578/article/details/87186613

https://discuss.pytorch.org/t/dataparallel-imbalanced-memory-usage/22551/22

https://www.pytorchtutorial.com/pytorch-large-batches-multi-gpu-and-distributed-training/

解决方法:就是将loss函数的前向计算写入到self.model的前向计算当中,这样就是每块gpu计算loss在都是单独的,不用汇总在独一块gpu中进行计算;

使用之前,四块gpu分别是9G,4G,4G,4G;

使用之后,四块gpu分别是10G,9G,9G,9G;

但是这样操作后有一个弊端,无法在训练过程中,在验证集上进行结果测试,因为model当中不仅仅包括提取图片特征,同时包括loss函数;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是使用 PyTorch 进行多 GPU 训练的示例代码: ```python import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision.datasets import CIFAR10 from torchvision.transforms import transforms # 定义模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(torch.relu(self.conv1(x))) x = self.pool(torch.relu(self.conv2(x))) x = x.view(-1, 16 * 5 * 5) x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) return x # 定义训练函数 def train(model, device, train_loader, optimizer, criterion): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() # 定义测试函数 def test(model, device, test_loader, criterion): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += criterion(output, target).item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) accuracy = 100. * correct / len(test_loader.dataset) print('Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)'.format( test_loss, correct, len(test_loader.dataset), accuracy)) # 定义主函数 def main(): # 设置超参数 batch_size = 128 epochs = 10 lr = 0.01 momentum = 0.9 num_workers = 4 num_gpus = torch.cuda.device_count() # 加载数据集 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) train_dataset = CIFAR10(root='./data', train=True, download=True, transform=transform) test_dataset = CIFAR10(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers) # 初始化模型和优化器 model = Net() if num_gpus > 1: model = nn.DataParallel(model) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) criterion = nn.CrossEntropyLoss() # 训练和测试 for epoch in range(1, epochs + 1): train(model, device, train_loader, optimizer, criterion) test(model, device, test_loader, criterion) if __name__ == '__main__': main() ``` 这个示例代码可以在多个 GPU 上并行训练模型,如果只有一个 GPU,可以将 `num_gpus` 设置为 1。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫猫与橙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值