import os
import torch
import torch.nn.functional as F
from torch.utils.data import Dataset,DataLoader
import torch.multipleprocessing as mp
from torch.utils.data.distributed import DistributedSampler
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.distributed import init_process_group,destory_process_group
Basics:
- All to one:reduce:one to all:broadcast
- rank:[0,world_size]
ddp_size
def ddp_setup(rank,world_size):
"""
Args:
rank:Unique identifier of each process
world_size:Total number of process
"""
#rank 0 process
os.environ["MASTER_ADDR"]="localhost"
os.environ["MASTER_PORT"]="12355"
#nccl:NVIDIA Collective Communciation Library
#分布式情况下的gpus间通信
init_process_group(backend="nccl",rank=rank,world_size=world_size)
torch.cuda.set_device(rank)
custom Trainer(自定义trainer)
class Trainer:
def __init__(self,model:torch.nn.Module,train_dataloader:DataLoader,optimimzer:torch.optim.Optimizer,gpu_id:int)->None:
#rank
self.gpu_id = gpu_id
self.model = model.to(gpu_id)
self.train_dataloader = train_dataloader
self.optimizer = optimizer
self.model = DDP(model,device_ids=[gpu_id])
def _run_batch(self,xs,ys):
self.optimizer.zero_grad()
output = self.model(xs)
loss = F.cross_entropy(output,ys)
loss.backward()
self.optimizer.step()
def _run_epoch(self,epoch):
batch_size = len(next(iter(self.train_dataloader))[0])
print(f'[GPU:{self.gpu_id}] Epoch:{epoch}|Batchsize:{batch_size}|Steps:{len(self.train_dataloader)})
self.train_dataloader.sampler.set_epoch(epoch)
for xs,ys in self.train_dataloader:
xs = xs.to(self.gpu_id)
ys = ys.to(self.gpu_id)
self._run_batch(xs,ys)
def train(self,max_epoch:int):
for epoch in range(max_epoch):
self._run_epoch(epoch)
pipeline
class MyTrainDataset(Dataset):
def __init__(self,size):
self.size=size
self.data=[(torch.rand(20),torch.rand(1))for _ in range(size)]
def __len__(self):
return self.size
def __getitem__(self,index):
return self.data[index]
train_dataset =MyTrainDataset(2048)
train_dataset[0]
def main(rank:int,world_size:int,max_epochs:int;batch_size:int):
ddp_setup(rank,world_size)
train_dataset = MyTrainDataset(2048)
train_dataloader = DataLoader(train_dataset,batch_size=bacth_size,pin_memory=True,shuffle=False,sample=DistributedSample(train_dataset))
model=torch.nn.Linear(20,1)
optimizer= torch.optim.SGD(model.parameters(),lr=1e-3)
trainer = Trainer(model=model,gpu_id=rank,optimizer=optimizer,train_dataloader=train_loader)
trainer.train(max_epoches)
destory_process_group()
分布式training
python -m torch.distributed.launchtorchrun
world_size=torch.cuda.device_count()
world_size
2048/32
!python ddp_gpus.py --max_epochs 5 --batch_size 32
batch_size固定,batch_step会分布在多个gpus上,且一个epoch中gpu的先后执行顺序不同
torchrun运行
torchrun- Work RANK and WORLD_SIZE are asssigned automatically
python -m torch.distributed.launch --use-env
!torchrun ddp_gpus_torchrun.py --max_epochs 5 --batch_size 32
!torchrun --nproc-per-node=2 ddp_gpus_torchrun.py --max_epochs 5 --batch_size 32
!python -m torch.distributed.launch --use-env --nproc-per-node=2 ddp_gpus_torchrun.py --max_epochs 5 --batch_size 32