Skill Tracer
Skills › Scientific Agent Skills › pytorch-lightning › distributed_training.md

distributed_training.md

148 lines · skills/pytorch-lightning/references/distributed_training.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Distributed training contracts
2
3Reviewed against the Lightning 2.6.6 release source. A two-process CPU DDP check validates synchronized means and demonstrates
4evaluation sampler padding. It does not validate CUDA collectives, FSDP,
5DeepSpeed, TPU or multi-node launching. All multi-device commands below are illustrative and require the
6specified hardware, process launcher and compatible dependencies.
7

Distributed training contracts

Reviewed against the Lightning 2.6.6 release source. A two-process CPU DDP check validates synchronized means and demonstrates evaluation sampler padding. It does not validate CUDA collectives, FSDP, DeepSpeed, TPU or multi-node launching. All multi-device commands below are illustrative and require the specified hardware, process launcher and compatible dependencies.

Raw lines 1 to 7
8## Choose using measured memory
9
10DDP keeps a full model, gradients and optimizer replica on each device. Use it
11when each replica plus peak activations fits, and scale after a one-device smoke
12run. FSDP shards training state and adds communication; DeepSpeed offers ZeRO
13stages and offloading. There is no universal 500M/10B parameter cutoff or
14universal fastest strategy: precision, optimizer, sequence length, activations,
15batch size and interconnect determine memory and throughput.
17```python
18from datetime import timedelta
19from lightning.pytorch.strategies import DDPStrategy
20trainer = L.Trainer(
21 accelerator="gpu", devices=4,
22 strategy=DDPStrategy(find_unused_parameters=False,
23 gradient_as_bucket_view=True,
24 timeout=timedelta(minutes=30)),
25 precision="16-mixed", accumulate_grad_batches=4,
27```
29Use `find_unused_parameters=False` only when all relevant parameters participate
30in every backward pass; true adds graph traversal but supports unused parameters.
31Set the process-group timeout with `DDPStrategy(timeout=...)`; `NCCL_TIMEOUT`
32is not a supported replacement. NCCL is the usual CUDA backend, gloo for CPU.
33`ddp_spawn` requires picklable objects and an import-safe main guard and is not a
34generic fix for a distributed configuration bug. Prefer a script for scaling.
36Effective batch size is local batch times world size times accumulation for
37full accumulation windows. A partial final window, token masks and uneven ranks
38need separate accounting. Treat linear learning-rate scaling as a hypothesis to
39validate, not an automatic rule.

Choose using measured memory

DDP keeps a full model, gradients and optimizer replica on each device. Use it when each replica plus peak activations fits, and scale after a one-device smoke run. FSDP shards training state and adds communication; DeepSpeed offers ZeRO stages and offloading. There is no universal 500M/10B parameter cutoff or universal fastest strategy: precision, optimizer, sequence length, activations, batch size and interconnect determine memory and throughput.

from datetime import timedelta
from lightning.pytorch.strategies import DDPStrategy
trainer = L.Trainer(
    accelerator="gpu", devices=4,
    strategy=DDPStrategy(find_unused_parameters=False,
                         gradient_as_bucket_view=True,
                         timeout=timedelta(minutes=30)),
    precision="16-mixed", accumulate_grad_batches=4,
)

Use find_unused_parameters=False only when all relevant parameters participate in every backward pass; true adds graph traversal but supports unused parameters. Set the process-group timeout with DDPStrategy(timeout=...); NCCL_TIMEOUT is not a supported replacement. NCCL is the usual CUDA backend, gloo for CPU. ddp_spawn requires picklable objects and an import-safe main guard and is not a generic fix for a distributed configuration bug. Prefer a script for scaling.

Effective batch size is local batch times world size times accumulation for full accumulation windows. A partial final window, token masks and uneven ranks need separate accounting. Treat linear learning-rate scaling as a hypothesis to validate, not an automatic rule.

Raw lines 8 to 40
41## Sampling, metrics and writes
43Lightning replaces ordinary map-style loader samplers by DistributedSampler
44when needed. To own sampling, use `use_distributed_sampler=False` and implement
45correct rank/worker sharding and epoch reseeding. IterableDataset is not
46sharded automatically. DistributedSampler can pad repeated indices when the
47sample count is not divisible by world size, including validation/test. For
48published metrics use a separate `Trainer(accelerator="cpu", devices=1)` or a
49validated nonduplicating distributed evaluator.
51`self.log(..., sync_dist=True, batch_size=...)` reduces tensor means across
52ranks; all ranks must call it consistently. Use TorchMetrics objects for
53nonlinear metrics. Rank-zero-only logging is unsuitable for monitored metrics
54that all ranks need. Collect predictions using rank-specific outputs and stable
55sample IDs; rank zero alone sees only its shard. `trainer.save_checkpoint` must
56be called by every rank because sharded strategies use collectives. Use
57rank-zero guards for ordinary shared-file writes that need no collectives.

Sampling, metrics and writes

Lightning replaces ordinary map-style loader samplers by DistributedSampler when needed. To own sampling, use use_distributed_sampler=False and implement correct rank/worker sharding and epoch reseeding. IterableDataset is not sharded automatically. DistributedSampler can pad repeated indices when the sample count is not divisible by world size, including validation/test. For published metrics use a separate Trainer(accelerator="cpu", devices=1) or a validated nonduplicating distributed evaluator.

self.log(..., sync_dist=True, batch_size=...) reduces tensor means across ranks; all ranks must call it consistently. Use TorchMetrics objects for nonlinear metrics. Rank-zero-only logging is unsuitable for monitored metrics that all ranks need. Collect predictions using rank-specific outputs and stable sample IDs; rank zero alone sees only its shard. trainer.save_checkpoint must be called by every rank because sharded strategies use collectives. Use rank-zero guards for ordinary shared-file writes that need no collectives.

Raw lines 41 to 58
59## FSDP
61```python
62from lightning.pytorch.strategies import FSDPStrategy
63import torch.nn as nn
64trainer = L.Trainer(
65 accelerator="gpu", devices=4, precision="bf16-mixed",
66 strategy=FSDPStrategy(
67 auto_wrap_policy={nn.TransformerEncoderLayer},
68 activation_checkpointing_policy={nn.TransformerEncoderLayer},
69 sharding_strategy="FULL_SHARD", cpu_offload=False,
70 state_dict_type="sharded",
71 ),
73```
75The policy classes must actually occur in the model. `mixed_precision` on
76FSDPStrategy expects a PyTorch `MixedPrecision` object, not `True`; normally let
77Trainer precision configure it. `FULL_SHARD` reshards parameters after forward
78and backward; `SHARD_GRAD_OP` keeps parameters unsharded between forward and
79backward but reshards after backward. It is not merely gradient/optimizer-only
80sharding with permanently replicated parameters. `HYBRID_SHARD` shards within
81node groups and replicates across them. CPU offloading trades memory for
82transfer overhead and has gradient-accumulation constraints; validate the chosen
83combination.
85Use idempotent `configure_model()` for large model construction in the strategy
86context. Do not allocate a giant model unconditionally in `__init__` or use the
87deprecated `configure_sharded_model` hook. A sharded checkpoint is a directory;
88keep its files together and resume via Trainer with the matching strategy.
89`load_from_checkpoint` does not support sharded checkpoints. Full state dicts
90are more portable but may require substantial rank-zero CPU memory.

FSDP

from lightning.pytorch.strategies import FSDPStrategy
import torch.nn as nn
trainer = L.Trainer(
    accelerator="gpu", devices=4, precision="bf16-mixed",
    strategy=FSDPStrategy(
        auto_wrap_policy={nn.TransformerEncoderLayer},
        activation_checkpointing_policy={nn.TransformerEncoderLayer},
        sharding_strategy="FULL_SHARD", cpu_offload=False,
        state_dict_type="sharded",
    ),
)

The policy classes must actually occur in the model. mixed_precision on FSDPStrategy expects a PyTorch MixedPrecision object, not True; normally let Trainer precision configure it. FULL_SHARD reshards parameters after forward and backward; SHARD_GRAD_OP keeps parameters unsharded between forward and backward but reshards after backward. It is not merely gradient/optimizer-only sharding with permanently replicated parameters. HYBRID_SHARD shards within node groups and replicates across them. CPU offloading trades memory for transfer overhead and has gradient-accumulation constraints; validate the chosen combination.

Use idempotent configure_model() for large model construction in the strategy context. Do not allocate a giant model unconditionally in __init__ or use the deprecated configure_sharded_model hook. A sharded checkpoint is a directory; keep its files together and resume via Trainer with the matching strategy. load_from_checkpoint does not support sharded checkpoints. Full state dicts are more portable but may require substantial rank-zero CPU memory.

Raw lines 59 to 91
92## DeepSpeed
94Lightning 2.6.6's DeepSpeedStrategy explicitly requires CUDA, even though
95DeepSpeed upstream has other accelerator work. Install PyTorch first and use a
96compatible DeepSpeed build; `ds_report` reports available ops. Pip installation
97does not inherently compile every CUDA op: many compile just in time and need
98their own compiler/toolkit dependencies.
100```python
101from lightning.pytorch.strategies import DeepSpeedStrategy
102trainer = L.Trainer(
103 accelerator="gpu", devices=4, precision="16-mixed",
104 strategy=DeepSpeedStrategy(stage=3, offload_optimizer=True,
105 offload_parameters=True),
106 accumulate_grad_batches=4,
108```
110Stage 1 shards optimizer state, stage 2 also gradients, stage 3 also parameters.
111Aliases include `deepspeed_stage_1`, `_2`, `_3`, `_2_offload`, `_3_offload`, and
112`deepspeed_stage_3_offload_nvme`. CPU and NVMe offload are distinct settings;
113ensure memory/storage bandwidth and explicit writable paths.
115Prefer the strategy's typed arguments for a small configuration. If supplying a
116DeepSpeed JSON/dict, use actual numeric sizes: Hugging Face's `"auto"` bucket and
117batch settings are not a general Lightning/DeepSpeed JSON contract. Verify
118optimizer ownership, Trainer accumulation and precision against that config.
119Keep the full sharded checkpoint directory for resume; a consolidated FP32
120weights file is for model loading, not complete optimizer recovery.

DeepSpeed

Lightning 2.6.6's DeepSpeedStrategy explicitly requires CUDA, even though DeepSpeed upstream has other accelerator work. Install PyTorch first and use a compatible DeepSpeed build; ds_report reports available ops. Pip installation does not inherently compile every CUDA op: many compile just in time and need their own compiler/toolkit dependencies.

from lightning.pytorch.strategies import DeepSpeedStrategy
trainer = L.Trainer(
    accelerator="gpu", devices=4, precision="16-mixed",
    strategy=DeepSpeedStrategy(stage=3, offload_optimizer=True,
                              offload_parameters=True),
    accumulate_grad_batches=4,
)

Stage 1 shards optimizer state, stage 2 also gradients, stage 3 also parameters. Aliases include deepspeed_stage_1, _2, _3, _2_offload, _3_offload, and deepspeed_stage_3_offload_nvme. CPU and NVMe offload are distinct settings; ensure memory/storage bandwidth and explicit writable paths.

Prefer the strategy's typed arguments for a small configuration. If supplying a DeepSpeed JSON/dict, use actual numeric sizes: Hugging Face's "auto" bucket and batch settings are not a general Lightning/DeepSpeed JSON contract. Verify optimizer ownership, Trainer accumulation and precision against that config. Keep the full sharded checkpoint directory for resume; a consolidated FP32 weights file is for model loading, not complete optimizer recovery.

Raw lines 92 to 121
122## Multi-node launch
124Setting `num_nodes` does not allocate hosts or open rendezvous ports. Every node
125needs the same code/dependencies and accessible data/checkpoints. For a SLURM
126setup that launches one process per GPU:
128```bash
129#SBATCH --nodes=2
130#SBATCH --ntasks-per-node=4
131#SBATCH --gpus-per-node=4
132#SBATCH --time=01:00:00
133srun python train.py
134```
136The guarded script constructs `Trainer(accelerator="gpu", devices=4,
137num_nodes=2, strategy="ddp")`. On a manually managed cluster, configure the
138actual LightningEnvironment variables consistently (MASTER_ADDR, MASTER_PORT,
139NODE_RANK) and launch the script on every node, or use a supported `torchrun`
140launch with the correct node ranks. Merely parsing `--node_rank` without passing
141it to the launcher/environment has no effect.
143Sources: [DDP strategy](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/src/lightning/pytorch/strategies/ddp.py),
144[FSDP strategy](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/src/lightning/pytorch/strategies/fsdp.py),
145[FSDP guide](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/docs/source-pytorch/advanced/model_parallel/fsdp.rst),
146[DeepSpeed strategy](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/src/lightning/pytorch/strategies/deepspeed.py),
147[DeepSpeed install](https://www.deepspeed.ai/tutorials/advanced-install/),
148[cluster guide](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/docs/source-pytorch/clouds/cluster_advanced.rst).

Multi-node launch

Setting num_nodes does not allocate hosts or open rendezvous ports. Every node needs the same code/dependencies and accessible data/checkpoints. For a SLURM setup that launches one process per GPU:

#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --gpus-per-node=4
#SBATCH --time=01:00:00
srun python train.py

The guarded script constructs Trainer(accelerator="gpu", devices=4, num_nodes=2, strategy="ddp"). On a manually managed cluster, configure the actual LightningEnvironment variables consistently (MASTER_ADDR, MASTER_PORT, NODE_RANK) and launch the script on every node, or use a supported torchrun launch with the correct node ranks. Merely parsing --node_rank without passing it to the launcher/environment has no effect.

Sources: DDP strategy, FSDP strategy, FSDP guide, DeepSpeed strategy, DeepSpeed install, cluster guide.

Raw lines 122 to 148
Runs code python train.py :133