Session 24¶
Topic 3: Neural networks and PyTorch¶
- introduction to PyTorch
- automatic differentiation
- basic neural network models and training
- optimization hyperparameters
- distributed training with data parallelism
- distributed training on multiple compute nodes π
Today¶
Distributed training on multiple compute nodes¶
- PyTorch DDP with multiple nodes
PyTorch DDP with multiple nodes¶
From single machine β data center¶
so far:
- single GPU
- multi-GPU (one compute node)
β now: use all available GPUs across nodes
What DDP actually does?¶
each GPU runs:
- its own model copy (identical copies)
- its own data batch (disjoint data)
after the backward pass:
- gradients are averaged (all-reduce)
β all models stay in sync across GPUs
Abstraction: from hardware to software¶
one GPU = one worker = one process
each worker/process: controls one GPU device
each runs:
workers are independent, to agree they average after the backward step β all-reduce communication
Hardware β software mapping¶
num_nodesβ number of compute nodesnum_gpusβ GPUs per nodeWORLD_SIZE = num_nodes Γ num_gpusβΒ total number of workers
\(\Rightarrow\) total number of workers = total number of GPUs
Local vs global rank¶
every worker has two unique identities: local & global
-
local_rank(unique ID within a node)0, 1, ..., num_gpus-1- selects GPU:
cuda:{local_rank}
-
global_rank(unique ID across all nodes)0, 1, ..., WORLD_SIZE-1
how workers are indexed:
global_rank = node_id * num_gpus + local_rank
Example: 2 nodes Γ 4 GPUs¶
node_id |
local_rank |
global_rank |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 0 | 2 | 2 |
| 0 | 3 | 3 |
| 1 | 0 | 4 |
| 1 | 1 | 5 |
| 1 | 2 | 6 |
| 1 | 3 | 7 |
Process Structure¶
What actually gets launched?¶
SLURM, an HPC job scheduler launches:
1 task per node
inside each node, PyTorch launches:
1 process per GPU
β tree structure: nodes β processes β GPUs
Rank 0 = main process π¦¶
only one worker/process:
- logs metrics
- downloads data
- coordinates communication
β the other ranks work silently
How do workers find the main process?¶
MASTER_ADDRβ where rank 0 livesMASTER_PORTβ its communication port
Data parallel workflow¶
the remaining workflow is the same as for multi-GPU:
- initialize processes (
init_process_group) - split dataset across GPUs (
DistributedSampler) - wrap the model (
DistributedDataParallel) - run the training loop
PyTorch handles automatically: synchronization / all-reduce of gradients
Putting it all together¶
The multi-node DDP pipeline¶
- SLURM job scheduler allocates nodes
- each node spawns workers
- each worker:
- gets a
global_rankandlocal_rank - binds to one GPU
- gets a
- all workers:
- sync via
init_process_group - train in lockstep
- sync via
Key takeaways¶
- 1 GPU = 1 worker = 1 process
local_rankselects the GPUglobal_rankidentifies the workerWORLD_SIZE= total parallelism (all workers)
Looking ahead¶
- practice your skills by reviewing the previous sessions
- practice tensors, autograd, optimization, and distributed training