PyTorch 單機多卡操作總結(jié):分布式DataParallel,混合精度,Horovod)

極市導讀
?本文介紹了數(shù)種實現(xiàn)單機多卡操作的方法,含有大量代碼,并給出了實踐中作者踩過的坑及其解決方案。>>加入極市CV技術交流群,走在計算機視覺的最前沿

1. 先問兩個問題
參與訓練的 GPU 有哪些,device_ids=gpus。 用于匯總梯度的 GPU 是哪個,output_device=gpus[0] 。
model = nn.DataParallel(model.cuda(), device_ids=gpus, output_device=gpus[0])
# main.py
import torch
import torch.distributed as dist
gpus = [0, 1, 2, 3]
torch.cuda.set_device('cuda:{}'.format(gpus[0]))
train_dataset = ...
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=...)
model = ...
model = nn.DataParallel(model.to(device), device_ids=gpus, output_device=gpus[0])
optimizer = optim.SGD(model.parameters())
for epoch in range(100):
for batch_idx, (data, target) in enumerate(train_loader):
images = images.cuda(non_blocking=True)
target = target.cuda(non_blocking=True)
...
output = model(images)
loss = criterion(output, target)
...
optimizer.zero_grad()
loss.backward()
optimizer.step()
稍微解釋幾句:model.to(device)將模型遷移到GPU里面,images.cuda,target.cuda把數(shù)據(jù)遷移到GPU里面。
nn.DataParallel(model.to(device), device_ids=gpus, output_device=gpus[0])包裝模型。
在每個訓練批次(batch)中,因為模型的權重都是在一個進程上先算出來,然后再把他們分發(fā)到每個GPU上,所以網(wǎng)絡通信就成為了一個瓶頸,而GPU使用率也通常很低。 除此之外,nn.DataParallel 需要所有的GPU都在一個節(jié)點(一臺機器)上,且并不支持 Apex 的 混合精度訓練。
2. 使用 torch.distributed 加速并行訓練:
2.1 介紹
DistributedDataParallel 解決 DataParallel 速度慢,GPU 負載不均衡的問題,目前已經(jīng)很成熟了。
在喂數(shù)據(jù)的時候,一個batch被分到了好幾個進程,每個進程在取數(shù)據(jù)的時候要確保拿到的是不同的數(shù)據(jù)( DistributedSampler);要告訴每個進程自己是誰,使用哪塊GPU( args.local_rank);在做BatchNormalization的時候要注意同步數(shù)據(jù)。
2.2 使用方式
2.2.1 啟動方式的改變
評論
圖片
表情
