Visual walkthrough — FSDP and sharded training
Step 1 — What is a parameter, and why does it cost bytes?
WHAT. A neural network is, at heart, a huge pile of numbers called parameters. When we say a model "has 175 billion parameters," we mean there are individual numbers that the training process is trying to tune. We call this count .
WHY count bytes. A GPU has a fixed amount of memory (an A100 has 80 gigabytes). Every number we store eats a fixed number of bytes — the unit computers measure memory in. So the whole "can I even train this?" question reduces to one honest tally: how many bytes must live on one GPU at once? Everything below is that tally.
PICTURE. Look at the strip of little boxes. Each box is one parameter. The whole strip is boxes long. The number written under the strip — how many bytes one box weighs — is the quantity we are about to fight over.

Step 2 — Four things live per parameter, not one
WHAT. Training does not store just the parameter. For every single parameter it also keeps three companions:
- — the parameter value ("the weight").
- — the training loss: a single number measuring how wrong the model's predictions currently are. Training tries to make small.
- — the gradient of that loss: how much would change if we nudged . This tells us which way to update.
- and — the Adam optimizer's memory of past gradients (a running average and a running average-of-squares ). See ZeRO Optimizer for why Adam needs these.
WHY. People count "175B parameters" and imagine 175B numbers of memory. But the optimizer secretly quadruples the count. If we forget these companions, our memory estimate is off by 4× — the single most common budgeting mistake.
PICTURE. One parameter box now stacks into a column of four boxes. All four are stored in fp32, so each is bytes: parameter, gradient, momentum, variance.

Step 3 — The baseline: replicate everything (plain Data Parallelism)
WHAT. In ordinary data parallelism, every one of the GPUs (defined at the top) holds a complete photocopy of all four stacks. Multiply the per-parameter cost by parameters:
- — bytes per parameter (Step 2).
- — number of parameters.
- The key sin: this number does not shrink when you add GPUs. Ten GPUs, ten identical photocopies.
WHY show this first. It is the villain. FSDP's whole reason to exist is that is a constant in — throwing more GPUs at the problem buys you zero memory relief.
PICTURE. Four GPUs, each holding an identical full-height column. The columns are carbon copies — same colours, same order. Redundant.

Step 4 — Sharding: cut each strip into pieces
WHAT. Sharding means: take a strip of numbers and slice it into equal pieces, giving piece to GPU . Nobody keeps the whole strip. If GPU 's piece is called , then:
- The vertical bars mean "concatenated end to end."
- Superscript means "the piece owned by GPU ."
- Each piece is the length, so it costs the bytes.
WHY. This is the one idea that turns a constant into a shrinking quantity. FSDP shards all four stacks — , gradient, , and — the same way. That is the "3" in ZeRO Stage 3 (parent note: FSDP = ZeRO-3).
PICTURE. The full strip from Step 1, now sliced by dashed lines into coloured segments, each segment floating over the GPU that owns it. No GPU holds a full row.

Step 5 — The persistent memory after sharding
WHAT. Apply Step 4 to all four stacks. Each GPU now permanently stores only its slice of each:
- — the total bytes of all four stacks across the whole cluster (unchanged; the numbers still exist somewhere).
- — but now spread across GPUs, so each holds only its share.
WHY. This is the payoff line. Where DP gave a flat regardless of , sharding gives — more GPUs literally means less memory each. Doubling the cluster halves the per-GPU load.
PICTURE. Four GPUs, each holding one short column (its slice of all four types), sitting beside the tall greyed-out DP column for contrast. Same total, split four ways.

Step 6 — The catch: the temporary all-gather buffer
WHAT. A GPU cannot compute a layer with only of — matrix multiply needs all of . So right before a layer runs, FSDP performs an all-gather: every GPU temporarily borrows the other shards to rebuild the full parameters of that one layer.
- — the permanent slices (Step 5).
- — the byte-cost of the parameters (the values only, at bytes each) of the single largest layer, rebuilt in full and held only for the instant that layer computes, then discarded. Concretely, — it is raw parameter bytes, not the full stack, because only is all-gathered for the forward compute.
WHY not the whole model? Because we rebuild one layer at a time and throw it away immediately. So the temporary cost scales with layer size, not model size — typically 1–2% of model memory for transformers.
PICTURE. A GPU's short persistent columns, plus one bright temporary block that swells up (all-gather arrow) while a layer computes, then vanishes (discard arrow) — a bubble that inflates and pops per layer.

Step 7 — The degenerate cases (where the formula bites back)
WHAT. Three edge cases the formula does not protect you from:
- (one GPU). Then — sharding buys nothing, and you still pay the all-gather machinery. FSDP is pointless on a single device.
- The model already fits. If GPU memory even without sharding, FSDP adds communication for savings you don't need — the parent's "When FSDP Hurts" example (15–20% slower).
- Activations are NOT in the formula. The term covers parameters, gradients, optimizer states — not activations. Activations cost per layer and are not sharded by vanilla FSDP.
WHY. A reader who trusts blindly will still OOM (out-of-memory) on activations. This is the parent's second big mistake callout.
PICTURE. A bar chart: the sharded bar looks tiny — then a separate, large "activations" bar towers next to it, unaffected by , with an arrow to Activation Checkpointing as the fix.

The one-picture summary
Everything on one canvas: a full DP column (, flat) transforming — slice, distribute, add a small temporary bubble — into the FSDP layout (), with the untouched activation block standing to the side as the honest caveat.

Recall Feynman retelling — say it back in plain words
Every weight in the model drags along three friends: its gradient, and Adam's two memories ( and ). All four are fp32, so that's bytes per weight — and in plain data parallelism every GPU keeps a full photocopy of all of it, so adding GPUs never helps. FSDP's trick: slice each of those four piles into equal pieces (where is how many GPUs you have) and give one piece to each GPU, so the permanent cost drops to — now more GPUs genuinely means less memory each. The price is that to actually compute a layer you need all its weights, so just before each layer runs, everyone borrows the missing pieces (all-gather), computes, then throws the borrowed pieces away — a small temporary bubble sized to one layer's parameters, not the whole model. Three traps: with one GPU it does nothing, if the model already fits it just adds overhead, and it never touches activation memory — those you kill separately with activation checkpointing.
Recall Quick self-check
Bytes per parameter in fp32 Adam training ::: Per-GPU persistent memory with FSDP over devices ::: What does stand for ::: the number of data-parallel GPUs sharing the work Why does plain data parallelism not shrink with more GPUs ::: every GPU keeps a full photocopy, so per-GPU memory stays regardless of What does the temporary buffer scale with ::: the parameter bytes of one layer ( params in the largest layer), not the whole model One thing FSDP does NOT shard ::: activations (fix with activation checkpointing)
Related: FSDP and sharded training · ZeRO Optimizer · Model Parallelism · Pipeline Parallelism · Mixed Precision Training · Communication Collectives