DistributedDataParallel is a module in PyTorch that allows parallel training of a single model across multiple GPUs, nodes, and processes. Here is a step-by-step guide on how to use DistributedDataParallel for distributed deep learning training across multiple nodes using PyTorch:
Step 1: Set up the environment Youll need to ensure that all nodes have the same software versions, and the data is accessible at each node. Install the necessary requirements on each node and configure them to be able to communicate with each other.
Step 2: Initializing PyTorch Initialize PyTorch and set the backend to either Gloo or MPI, depending on your preference. Initialize the communication between the nodes.
import torch.distributed as dist
import torch.multiprocessing as mp
def main():
# initialize the process group
dist.init_process_group(backend="gloo",
init_method="env://",
world_size=4,
rank=rank) # where rank is the rank of the current process
if __name__ == "__main__":
mp.spawn(main, nprocs=4, args=())
Step 3: Setting up the model The next step is to set up the model for training. Make sure that the model is an instance in each process.
def setup_model(rank, world_size):
# initialize the model
model = MyModel()
# configure the device
torch.cuda.set_device(rank % torch.cuda.device_count())
# create distributed model
model = model.to(rank)
model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[rank % torch.cuda.device_count()])
return model
Note: The torch.cuda.set_device() function sets the device for the current process. device_ids takes a list of devices that you want the model to use.
Step 4: Defining data loaders Create data loaders for the data to be used in training. You will need to use the Sampler classes and the DistributedSampler.
train_dataset = get_dataset()
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset,
num_replicas=world_size,
rank=rank)
train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
shuffle=(train_sampler is None),
sampler=train_sampler)
Step 5: Setting up the optimizer Set up the optimizer as usual. Then, wrap it with the DistributedOptimizer class from PyTorch.
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
optimizer = torch.nn.parallel.DistributedDataParallel(optimizer, device_ids=[rank % torch.cuda.device_count()])
Step 6: Training Next, iterate through the training loop as usual. Make sure to define the loss function and backpropagate the gradient in each process.
def train_loop(rank, world_size):
model = setup_model(rank, world_size)
optimizer = setup_optimizer(model)
data_loader = setup_data_loader(rank, world_size)
loss_fn = MyLossFn()
for epoch in range(num_epochs):
for batch_idx, (data, target) in enumerate(data_loader):
optimizer.zero_grad()
outputs = model(data)
loss = loss_fn(outputs, target)
loss.backward()
optimizer.step()
dist.destroy_process_group()
Step 7: Running the training script Finally, distribute the training across the nodes using the following command:
python -m torch.distributed.launch --nproc_per_node=4 distributed_training.py --arg1=val1 --arg2=val2 ...
It is also possible to run the script with launched workers manually. In that case, you can start the workers with this command:
CUDA_VISIBLE_DEVICES=<range> python distributed_training.py --world-size <num_nodes> --rank <rank_on_this_node>
DistributedDataParallel is an efficient way of scaling up training on multiple nodes, increasing throughput and reducing training time on large datasets.