關於pytorch 使用DDP模式(torch.nn.parallel.DistributedDataParallel)時,DistributedSampler(dataset)用法解釋

最近由於要用到多卡去訓模型,嘗試着用DDP模式,而不是DP模式去加速訓練(很容易出現負載不均衡的情況)。遇到了一點關於DistributedSampler這個採樣器的一點疑惑,想試驗下在DDP模式下,使用這個採樣器和不使用這個採樣器有什麼區別。

實驗代碼:

整個數據集大小爲8,batch_size 爲4,總共跑2個epoch

import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from torch.utils.data.distributed import DistributedSampler
torch.distributed.init_process_group(backend="nccl")

batch_size = 4
data_size = 8

local_rank = torch.distributed.get_rank()
print(local_rank)
torch.cuda.set_device(local_rank)
device = torch.device("cuda", local_rank)

class RandomDataset(Dataset):
        def __init__(self, length, local_rank):
            self.len = length
            self.data = torch.stack([torch.ones(1), torch.ones(1)*2,torch.ones(1)*3,torch.ones(1)*4,torch.ones(1)*5,torch.ones(1)*6,torch.ones(1)*7,torch.ones(1)*8]).to('cuda')
            self.local_rank = local_rank
        def __getitem__(self, index):
            return self.data[index]
        def __len__(self):
            return self.len

dataset = RandomDataset(data_size, local_rank)
sampler = DistributedSampler(dataset)

#rand_loader =DataLoader(dataset=dataset,batch_size=batch_size,sampler=None,shuffle=True)
rand_loader = DataLoader(dataset=dataset,batch_size=batch_size,sampler=sampler)
epoch = 0
while epoch < 2:
    sampler.set_epoch(epoch)
    for data in rand_loader:
            print(data)
    epoch+=1

運行命令: CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 test.py

實驗結果:

結論分析:上面的運行結果來看,在一個epoch中,sampler相當於把整個數據集 劃分成了nproc_per_node份,每個GPU每次得到batch_size的數量,也就是nproc_per_node 個GPU分一整份數據集,總數據量大小就爲1個dataset

如果不用它裏面自帶的sampler,單純的還是按照我們一般的形式。Sampler=None,shuffle=True這種,那麼結果將會是下面這樣的:

結果分析:沒用sampler的話,在一個epoch中,每個GPU各自維護着一份數據,每個GPU每次得到的batch_size的數據,總的數據量爲2個dataset,

 

 

總結:

一般的形式的dataset只能在同進程中進行採樣分發,也就是爲什麼圖2只能單GPU維護自己的dataset,DDP中的sampler可以對不同進程進行分發數據,圖1,可以誇不同進程(GPU)進行分發。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章