From e706b81007adeba0e8eb8566e30c7af7e5ebf849 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Mon, 3 Jun 2024 11:40:05 -0300 Subject: [PATCH] fix broadcast and reduce gradients distributeddataparallel and tensor hooks --- build/cuda.cu.o | Bin 220752 -> 220752 bytes build/distributed.o | Bin 188328 -> 188432 bytes build/tensor.o | Bin 54568 -> 54432 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 20157 -> 20576 bytes norch/csrc/tensor.cpp | 5 - norch/libtensor.so | Bin 401240 -> 401240 bytes norch/nn/__pycache__/parameter.cpython-38.pyc | Bin 736 -> 736 bytes norch/nn/parallel.py | 37 +++++- .../optimizers/__pycache__/sgd.cpython-38.pyc | Bin 1239 -> 1243 bytes norch/tensor.py | 11 ++ train.py | 69 +++------- train_multigpu.py | 120 ++++++++++++++++++ 12 files changed, 180 insertions(+), 62 deletions(-) create mode 100644 train_multigpu.py diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 00a18960d68b41a4099d899c15a5bacc3750d626..1d8c326abdd0622a8d7c1024c4c6e6b32801a8c7 100644 GIT binary patch delta 25 hcmcbxhxfuB-i8*&ElkpvSPfDPQ!TbDTw*fl0RV}h38?@8 delta 25 hcmcbxhxfuB-i8*&ElkpvSd9&gj7_&ITw*fl0RV;_2}A$@ diff --git a/build/distributed.o b/build/distributed.o index 11a92efd3ddd3446c173d42c05df16f04f65edb9..58e0ef2fc765a84fc1bcb9cc82363ac3a6823f2f 100644 GIT binary patch delta 7618 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 b_Njj1f18ZL2u{x|I}}c*4Z|N&UjP3G$!Q5M delta 9207 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�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

Enk<_d*MHt{#umPD(K~~7vZj5zxf|ae-pJ{) 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 diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index 2381a0f80ce358482ebd4ed05a4df8ec956d0ea2..8505635cae1e65dbd99dee53f7aa7be84ac97f3f 100644 GIT binary patch delta 3735 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, "cuda") == 0)) { cuda_to_cpu(tensor); } - - else { - fprintf(stderr, "Could not send tensor to device %d", device_id); - exit(1); - } } Tensor* add_tensor(Tensor* tensor1, Tensor* tensor2) { diff --git a/norch/libtensor.so b/norch/libtensor.so index f50c17ca1d13524ab6f6cd33cacf99f2743366c7..bc35ee296b4615736fe0e00bbe00296f7b697df0 100755 GIT binary patch delta 48689 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 delta 48582 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 dSvGCem1bVKHc2N)r=;jimhOgNw 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�rrX@ z2`@#A1d~XV;3`ric!?Df+KMa*P9j&r5W(&POd?2vtB8@{B@!i+z@PU6CW#di){86& z_{CufYw_3ofR!Rh!nYzu!j~dZLaIoSFhQ)4&|G9m2o|{#Y6|ucFh~SR*dt;j_=!Xb z6GV!HY_UQ@n8=dwk;s*>ORz@(E`lTsz#j+$Mv6oU7eoqOT=B@UBHJeZl;A1uN*EyA zA7cpqfw;%`gx^<@Fjq{F7hj66Bn%b5OIRrW2JjsR#61V6vcltuqa%NHK=?dytN_dE zKEaTNqPv6%Vgi6qJS6Tta;)Gq+8G^F?2wcl;^GsOLRrD`@Tr0blF(elNa!RI|KHWM zfY)@T?Q>4fj)Wu<5^*BPQ51DcON(MeQBgEex448Dm!vKuipI4$bt%Rz2Cqw9j#i4n zNPkoGN1aZ`PX{B~8a&z&Q~krB(oq$4`QPuX@BA~}`+0b?zV}_<`qtWOt-bc`Y=O~y z{fO`}`~nUH1PV|lz=w{0AiM~#z!szlgz=po!UXsPF2OIb2LXYbC=+M~=f4OM@CtAz z3UDV1G=@*0Is5_*5D;jHG6C+4yM%7=3iLpl0OJ%G1)sp%@C&R)KwvY<1opxCBjICs z1^6r80%wpTz@1@Iet|0p2=EJX0yiayI@XubJVL;Gj}~53{?VQ6j$vO%ju_Zi1)|^= zsD*$)6O;+?m9U=(t>G2uz!%sF{D}>LZ1@Cn;TM>XfWTUm39N(jK4BZY0_%__@GWu# zI>RTh0e*t(-rtZEX(d^!W4XXWnJ~NHtR(aJ0yc+}xl5)c(r99{

OcPaqq9fvpG# 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 LIH(goF6{pR(y=j- diff --git a/norch/nn/__pycache__/parameter.cpython-38.pyc b/norch/nn/__pycache__/parameter.cpython-38.pyc index fc6933883746daeab7d27fa762862d0ce7c372a4..14bb0692963118abaefee14811bc7562f61be0e2 100644 GIT binary patch delta 44 xcmaFB`hb-?l$V!_0SJDciQUNE$s~M>J1@T|IYY0sBr~VDh#4poHF-IcB>*hQ4Q&7b delta 44 xcmaFB`hb-?l$V!_0SHb$4BW`w$s`=botIyfoS|1*l9^Ln#0-?VHF-IcB>*214MqR} diff --git a/norch/nn/parallel.py b/norch/nn/parallel.py index 16eca59..c021537 100644 --- a/norch/nn/parallel.py +++ b/norch/nn/parallel.py @@ -1,6 +1,7 @@ from .module import * import norch.distributed as dist import os +import norch class DistributedDataParallel(Module): def __init__(self, module): @@ -8,16 +9,40 @@ class DistributedDataParallel(Module): self.module = module + + self.broadcast_parameters() + self.register_grads_hooks() + def forward(self, *inputs, **kwargs): return self.module(*inputs, **kwargs) - def backward(self): - self.module.backward() - for module, name, _ in self.parameters(): - parameter = getattr(module, name) - dist.allreduce_mean_tensor(parameter) - setattr(module, name, parameter) + def broadcast_parameters(self): + """ + Broadcast parameters of device 0 to all devices + """ + for _, _, parameter in self.parameters(): + dist.broadcast_tensor(parameter) + + def allreduce_grads_hook(grad): + """ + Everytime a gradient is assign to some value, it calculates mean of this gradient among all devices + """ + if isinstance(grad, norch.Tensor): + dist.allreduce_sum_tensor(grad) + grad /= dist.get_world_size() + return grad + + def register_grads_hooks(self): + """ + Everytime a gradient is assign it calls this allreduce hook + """ + for _, _, parameter in self.parameters(): + parameter.register_hook(self.allreduce_grads_hook) + + + + diff --git a/norch/optim/optimizers/__pycache__/sgd.cpython-38.pyc b/norch/optim/optimizers/__pycache__/sgd.cpython-38.pyc index c1b0789c9b83c4adc74041b9646e684dac65d982..7336b8ecea49832c6630b61684847c7482efdc92 100644 GIT binary patch delta 51 zcmcc4d7G0vl$V!_0SI(9M{newz{u!5c@Co*dqAaMeo=D9=A(>{7#VL(Uco$tQE{>@ G%PatNvJce& delta 47 zcmcc3d7YCxl$V!_0SKhmT5jZ?z{u!6c@Co*b6S4>=97$%7#X7`uVJ3Ts4&@)WflM| C0S%x4 diff --git a/norch/tensor.py b/norch/tensor.py index 2e80e72..0a1ecab 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -39,6 +39,7 @@ class Tensor: self.numel *= s self.requires_grad = requires_grad + self.hooks = [] self.grad = None self.grad_fn = None @@ -59,6 +60,7 @@ class Tensor: self.ndim = None, self.device = device self.requires_grad = None + self.hooks = [] self.grad = None self.grad_fn = None @@ -79,6 +81,15 @@ class Tensor: flat_data, shape = flatten_recursively(nested_list) return flat_data, shape + def __setattr__(self, name, value): + if name == 'grad': + for hook in self.hooks: + value = hook(value) + super().__setattr__(name, value) + + def register_hook(self, function): + self.hooks.append(function) + def ones_like(self): Tensor._C.ones_like_tensor.argtypes = [ctypes.POINTER(CTensor)] diff --git a/train.py b/train.py index 96cbc8d..4eb30c6 100644 --- a/train.py +++ b/train.py @@ -3,52 +3,21 @@ import norch import norch.distributed as dist import norch.distributed +import norch.nn as nn +import norch.optim as optim +from norch.utils.data.dataloader import DataLoader +from norch.nn.parallel import DistributedDataParallel +from norch.utils.data.distributed import DistributedSampler +from norch.norchvision import transforms as T +import numpy as np +import matplotlib.pyplot as plt +import random +random.seed(1) + def main(): - local_rank = int(os.getenv('OMPI_COMM_WORLD_LOCAL_RANK', -1)) - rank = int(os.getenv('OMPI_COMM_WORLD_RANK', -1)) - world_size = int(os.getenv('OMPI_COMM_WORLD_SIZE', -1)) - - dist.init_process_group(rank, world_size) - - tensor = norch.Tensor([1,1,1]).to(rank) - tensor = (rank + 1) * tensor - print(f"BEFORE on rank {rank}: {tensor} \n\n") - - dist.allreduce_sum_tensor(tensor) - - print(f"AFTER ALLREDUCE on rank {rank}: {tensor} \n\n") - - print("###############\n\n\n") - - tensor = tensor * 10 - print(f"BEFORE BROADCAST on rank {rank}: {tensor} \n\n") - - dist.broadcast_tensor(tensor) - - print(f"AFTER BROADCAST on rank {rank}: {tensor} \n\n") - -def main2(): - import norch - import norch.nn as nn - import norch.optim as optim - from norch.utils.data.dataloader import DataLoader - from norch.nn.parallel import DistributedDataParallel - from norch.utils.data.distributed import DistributedSampler - from norch.norchvision import transforms as T - import numpy as np - import matplotlib.pyplot as plt - import random - random.seed(1) - - local_rank = int(os.getenv('OMPI_COMM_WORLD_LOCAL_RANK', -1)) - rank = int(os.getenv('OMPI_COMM_WORLD_RANK', -1)) - world_size = int(os.getenv('OMPI_COMM_WORLD_SIZE', -1)) - - dist.init_process_group(rank, world_size) - BATCH_SIZE = 32 - device = local_rank + device = "cpu" epochs = 10 transform = T.Compose( @@ -65,8 +34,7 @@ def main2(): ) train_data, test_data = norch.norchvision.datasets.MNIST.splits(transform=transform, target_transform=target_transform) - distributed_sampler = DistributedSampler(dataset=train_data, num_replicas=world_size, rank=local_rank) - train_loader = norch.utils.data.DataLoader(train_data, batch_size=BATCH_SIZE, sampler=distributed_sampler) + train_loader = norch.utils.data.DataLoader(train_data, batch_size=BATCH_SIZE) class MyModel(nn.Module): def __init__(self): @@ -90,9 +58,6 @@ def main2(): optimizer = optim.SGD(model.parameters(), lr=0.01) loss_list = [] - print(f"Local rank: {local_rank}") - print(f"World size: {world_size}") - for epoch in range(epochs): for idx, batch in enumerate(train_loader): @@ -102,17 +67,19 @@ def main2(): target = target.to(device) outputs = model(inputs) - loss = criterion(outputs, target) optimizer.zero_grad() + print("#####################\n\nantes backward") + print(model.module.fc1.bias.grad) loss.backward() - print(f"AFTER rank {local_rank}: {model.module.fc2.bias.grad}") - print("\n\n") + print(model.module.fc1.bias.grad) + print("\n\n\n###############\n\npós backward") optimizer.step() + print("@@") break break diff --git a/train_multigpu.py b/train_multigpu.py new file mode 100644 index 0000000..20e3b6e --- /dev/null +++ b/train_multigpu.py @@ -0,0 +1,120 @@ +import os +import norch +import norch.distributed as dist +import norch.distributed + +def main(): + + local_rank = int(os.getenv('OMPI_COMM_WORLD_LOCAL_RANK', -1)) + rank = int(os.getenv('OMPI_COMM_WORLD_RANK', -1)) + world_size = int(os.getenv('OMPI_COMM_WORLD_SIZE', -1)) + + dist.init_process_group(rank, world_size) + + tensor = norch.Tensor([1,1,1]).to(rank) + tensor = (rank + 1) * tensor + print(f"BEFORE on rank {rank}: {tensor} \n\n") + + dist.allreduce_sum_tensor(tensor) + + print(f"AFTER ALLREDUCE on rank {rank}: {tensor} \n\n") + + print("###############\n\n\n") + + tensor = tensor * 10 + print(f"BEFORE BROADCAST on rank {rank}: {tensor} \n\n") + + dist.broadcast_tensor(tensor) + + print(f"AFTER BROADCAST on rank {rank}: {tensor} \n\n") + +def main2(): + import norch + import norch.nn as nn + import norch.optim as optim + from norch.utils.data.dataloader import DataLoader + from norch.nn.parallel import DistributedDataParallel + from norch.utils.data.distributed import DistributedSampler + from norch.norchvision import transforms as T + import numpy as np + import matplotlib.pyplot as plt + import random + random.seed(1) + + local_rank = int(os.getenv('OMPI_COMM_WORLD_LOCAL_RANK', -1)) + rank = int(os.getenv('OMPI_COMM_WORLD_RANK', -1)) + world_size = int(os.getenv('OMPI_COMM_WORLD_SIZE', -1)) + + dist.init_process_group(rank, world_size) + + BATCH_SIZE = 32 + device = local_rank + epochs = 10 + + transform = T.Compose( + [ + T.ToTensor(), + T.Reshape([-1, 784, 1]) + ] + ) + + target_transform = T.Compose( + [ + T.ToTensor() + ] + ) + + train_data, test_data = norch.norchvision.datasets.MNIST.splits(transform=transform, target_transform=target_transform) + distributed_sampler = DistributedSampler(dataset=train_data, num_replicas=world_size, rank=local_rank) + train_loader = norch.utils.data.DataLoader(train_data, batch_size=BATCH_SIZE, sampler=distributed_sampler) + + class MyModel(nn.Module): + def __init__(self): + super(MyModel, self).__init__() + self.fc1 = nn.Linear(784, 30) + self.sigmoid1 = nn.Sigmoid() + self.fc2 = nn.Linear(30, 10) + self.sigmoid2 = nn.Sigmoid() + + def forward(self, x): + out = self.fc1(x) + out = self.sigmoid1(out) + out = self.fc2(out) + out = self.sigmoid2(out) + + return out + + model = MyModel().to(device) + model = DistributedDataParallel(model) + print(f"parameter bias on Rank {rank}: {model.module.fc1.bias}\n\n") + criterion = nn.CrossEntropyLoss() + optimizer = optim.SGD(model.parameters(), lr=0.01) + loss_list = [] + + for epoch in range(epochs): + for idx, batch in enumerate(train_loader): + + inputs, target = batch + + inputs = inputs.to(device) + target = target.to(device) + + outputs = model(inputs) + + loss = criterion(outputs, target) + + optimizer.zero_grad() + + loss.backward() + print(f"GRADIENT AFTER rank {local_rank}: {model.module.fc2.bias.grad}") + print("\n\n") + + + optimizer.step() + break + + break + +if __name__ == "__main__": + main() +