Distribution goals and execution dependencies
Distribution serves three distinct goals: fitting required state, finishing fixed work sooner, and processing more independent work. Communication and waiting can offset saved computation. A capacity improvement therefore need not improve request latency.
| Partition | Work assigned to devices | Required exchange |
|---|---|---|
| Data parallelism | Model copies process different inputs. | Training gradients coordinate updates. |
| Tensor parallelism | Devices compute pieces of an operation. | Partial results or output pieces. |
| Pipeline parallelism | Devices execute successive layer groups. | Intermediate results pass between stages. |
| Independent serving replicas | Complete executable instances handle separate requests. | No training-gradient synchronization between replicas. |
A tensor is a multidimensional array. Parameters are learned values; activations are intermediate results. Forward computation produces predictions, backward computation produces gradients—the derivatives used for updates—and an optimizer changes parameters using those gradients and retained optimizer state. Distribution must preserve that chain. Training objectives and device execution supply the underlying context.
Prefill processes a known prompt; autoregressive decoding selects successive tokens conditioned on earlier selections. Processing a selected token produces new internal representations; the token itself is not a key or value vector. Distributing stages preserves these dependencies rather than removing them. Prefill and iterative decoding explains the local execution.
State ownership and per-device memory
A replica is a complete copy; sharding assigns separate portions to different owners. Distributed memory requires communication to access remote values: aggregate capacity is not automatically a shared address space.
| Allocation | Ownership and lifetime |
|---|---|
| Parameters | Owned shards may coexist with temporary full-layer parameters. |
| Gradients and optimizer state | Replication or partitioning depends on the sharding stage. |
| Activations | Forward intermediates needed later can remain large after parameter sharding. |
| KV cache | Context-dependent attention keys and values consume request memory beyond weights. |
| Communication and runtime buffers | Collectives, attention backends and temporary workspaces consume additional memory. |
Activation recomputation, also called activation checkpointing, regenerates intermediates during backward computation instead of retaining all of them. It exchanges computation for memory; it does not save a durable restart point. Offloading selected intermediates to CPU memory adds another transfer-and-prefetch tradeoff.
In serving, profile non-cache demand before assigning remaining memory to request state. Weights fitting alone does not establish useful concurrency. KV state and the resident memory budget explains the cache; distributed placement adds ownership and transfer constraints.
Workers, groups and collective communication
A worker is an executing process. Its rank identifies it within a participating group; a communicator supplies that group's communication context. A collective involves the group under a shared operation contract. NCCL implements such communication for participating GPU devices.
| Operation | Result ownership |
|---|---|
| Sum all-reduce | Both receive [4,6]. |
| All-gather | Both receive [1,2,3,4]. |
| Sum reduce-scatter | Rank 0 receives [4]; rank 1 receives [6]. |
| Broadcast from rank 0 | Both receive [1,2]. |
Reduction and concatenation differ
ExampleIdentical inputs yield different values and ownership.
Read the diagram as text
- Rank 0: [1,2].
- Rank 1: [3,4].
- Sum all-reduce.
- All-gather.
- Each rank: [4,6].
- Each rank: [1,2,3,4].
- Rank 0: [1,2] → Sum all-reduce: Sum contribution.
- Rank 1: [3,4] → Sum all-reduce: Sum contribution.
- Rank 0: [1,2] → All-gather: First piece.
- Rank 1: [3,4] → All-gather: Second piece.
- Sum all-reduce → Each rank: [4,6]: Reduced values.
- All-gather → Each rank: [1,2,3,4]: Concatenated values.
NCCL participants must supply matching counts and datatypes. Violations can hang, crash or corrupt data. Collective definitions specify the ownership changes.
MPI's nonblocking contract separates initiation from local buffer-safe completion. Participants initiate collectives in matching order; local completion need not mean every peer finished. GPU frameworks require their own completion rules. A point-to-point transfer instead connects a particular sender and receiver.
Physical topology and communication cost
A node is a machine; an interconnect carries data between devices or machines. Latency measures startup delay, while bandwidth measures bytes transferred per time. Shared interfaces and competing traffic can reduce effective bandwidth.
Collective algorithms determine communication rounds and paths. Rings circulate pieces through participants and can use bandwidth efficiently, but startup costs grow with group size. Trees reduce communication depth. A hierarchy can reduce-scatter locally, all-reduce between corresponding shard owners across nodes, then all-gather locally. NVIDIA's historical NCCL report illustrates these choices; no algorithm is universally fastest.
Frequent small exchanges can dominate decoding even when aggregate memory increases. Alex Cheema describes this capacity-versus-speed problem in a local tensor-parallel cluster. Advertised link bandwidth alone cannot predict the accumulated synchronization delay.
Data-parallel updates and loss normalization
Synchronous data-parallel workers start from matching parameters, compute local gradients, aggregate them, then update. Matching optimizer state and synchronized gradients preserve matching replicas. DistributedDataParallel, or DDP, performs gradient synchronization; it does not make arbitrary input weighting correct.
Two tokens with mean loss 1 and six with mean loss 3 yield token mean 2.5, not worker mean 2. DDP averaging requires compensation.
# Equal iteration counts across ranks; no implicit loss scaling.
window = next_local_window()
N = sum_all_ranks(count_scored_tokens(window))
optimizer.zero_grad()
if N > 0:
for i, batch in enumerate(window):
with synchronize_gradients(i == len(window) - 1):
loss_sum = model.summed_token_loss(batch)
(world_size * loss_sum / N).backward()
optimizer.step()Use actual counts for partial windows. Framework accumulation scaling needs separate compensation. Sampling and loss contribution explains the objective.
Equal partition lengths do not ensure exactly-once coverage. PyTorch's DistributedSampler can pad with repeated indices or drop a tail. Shared shuffle seeds and set_epoch control coordinated reshuffling. Check sample identities, not just counts; a rank cannot simply stop participating while peers continue ordinary collectives.
Sharded training state and temporary materialization
| Stage | Partitioned state |
|---|---|
| ZeRO-1 | Optimizer state |
| ZeRO-2 | Optimizer state and reduced gradients |
| ZeRO-3 | Optimizer state, reduced gradients and parameters |
Fully sharded data parallelism temporarily gathers parameters for computation. Layer-level grouping limits materialization; deeper prefetch can overlap communication with computation, but increases residency. Workers still execute model operations on different inputs.
Owned shards and temporary access
Sharded ownership does not imply shard-only residency.
Gather for local forward computation.
Read the diagram as text
- Layer L.
- Owned parameter shards.
- Full parameters: forward.
- Forward materialization released.
- Full parameters: backward.
- Reduced gradient shards.
- Updated parameter shards.
- Layer L → Owned parameter shards: Owned state.
- Owned parameter shards → Full parameters: forward: All-gather.
- Owned parameter shards → Forward materialization released: Retained ownership.
- Owned parameter shards → Full parameters: backward: All-gather.
- Full parameters: backward → Reduced gradient shards: Backward; reduce-scatter.
- Reduced gradient shards → Updated parameter shards: Owner update.
- Layer L → Updated parameter shards: New state.
- Forward access. Gather for local forward computation. Active: Layer L, Owned parameter shards, Full parameters: forward. New: Layer L, Owned parameter shards, Full parameters: forward.
- Release. Keep shards; release full parameters. Active: Layer L, Owned parameter shards, Forward materialization released. New: Forward materialization released.
- Backward access. Gather again; reduce computed gradients. Active: Layer L, Owned parameter shards, Full parameters: backward, Reduced gradient shards. New: Full parameters: backward, Reduced gradient shards.
- Update. Owners retain the new parameter version. Active: Layer L, Reduced gradient shards, Updated parameter shards. New: Updated parameter shards.
Partitioning persistent state does not eliminate activation pressure. Long-context training can still exhaust memory after parameter sharding. Smaller activation buffers or recomputation address a different allocation category; adding more parameter shards alone may leave the limiting peak unchanged.
Tensor partitions and result reconstruction
For X=[1,2] and W=[[1,−1],[2,1]], contracted partitions produce [1,−1] and [4,2]. Their sum is [5,1]. Applying ReLU, which replaces negative values with zero, before summing produces [5,2] instead: the reconstruction boundary matters.
Megatron pairs a column-partitioned first matrix with local elementwise activation and a row-partitioned second matrix. Intermediate features stay local; second-matrix partial outputs reduce. Backward likewise combines contributions to shared inputs. Its original MLP uses one forward and one backward all-reduce, not a universal count.
Smaller local work must repay repeated communication. In ordinary decoding, the next prediction waits for the current model execution, exposing collective latency along each token's path.
Pipeline schedules and bubbles
Pipeline stages exchange forward activations and backward gradients; microbatches overlap. Fill-drain runs all forwards, then all backwards, retaining activations until used. Synchronous one-forward-one-backward (1F1B) warms up with forwards, alternates forward/backward, then drains remaining backwards. Earlier backward completion releases activations, bounding outstanding microbatches by pipeline depth. Both retain dependency-induced idle intervals—pipeline bubbles—and update parameters only after all backwards, preserving consistent versions.
Two microbatches occupy successive stages
Example timingsDifferent microbatches overlap; each retains stage dependencies.
Read the diagram as text
- Stage 0 window. 0 to 3 schedule slots; duration 3 schedule slots.
- A forward. 0 to 1 schedule slots; duration 1 schedule slots. Parent: Stage 0 window.
- B forward. 1 to 2 schedule slots; duration 1 schedule slots. Parent: Stage 0 window.
- Stage 1 window. 0 to 3 schedule slots; duration 3 schedule slots.
- A forward. 1 to 2 schedule slots; duration 1 schedule slots. Parent: Stage 1 window.
- B forward. 2 to 3 schedule slots; duration 1 schedule slots. Parent: Stage 1 window.
Unequal prompt lengths can unbalance stages. Increasing microbatch count cannot remove a persistently slow stage or transfer bottleneck. During inference, independent requests can overlap across stages, while each autoregressive request still depends on its preceding token.
Composed parallelism and device placement
A device mesh organizes logical groups; it does not certify physical links. This eight-device assignment uses two data replicas, two pipeline stages and two tensor workers per stage.
| Ranks | Data coordinate | Pipeline coordinate | Tensor coordinates | Machine |
|---|---|---|---|---|
| 0,1 | 0 | 0 | 0,1 | A |
| 2,3 | 0 | 1 | 0,1 | B |
| 4,5 | 1 | 0 | 0,1 | C |
| 6,7 | 1 | 1 | 0,1 | D |
Tensor groups are {0,1}, {2,3}, {4,5}, {6,7}; pipeline groups are {0,2}, {1,3}, {4,6}, {5,7}; data groups are {0,4}, {1,5}, {2,6}, {3,7}. Each varies one coordinate while fixing the others.
Corresponding parameter slices repeat across data replicas unless further state sharding partitions them. A separate replicate-by-shard layout can shard within each host and replicate across hosts. State ownership follows the selected group, not the total device count.
First reject layouts whose peak state cannot fit. Then compare local computation, collective frequency and stage balance on the actual links. Keeping frequent exchanges within a node is a useful candidate, not a rule. In serving, fewer devices per executable instance may leave room for more independent replicas.
Overlap, readiness and the critical path
The critical path is the dependency chain determining completion. DDP groups gradients into buckets and starts reduction when a bucket is ready, preserving collective order. Independent backward work can continue before the optimizer consumes synchronized gradients.
Small buckets invite more startups; large buckets can become ready too late. Bucket contents that poorly match gradient readiness delay launch. Measure exposed waiting rather than treating every communication interval as added elapsed time.
Communication duration versus exposed waiting
Example timingsOnly unfinished prerequisite work delays the consumer.
Read the diagram as text
- Execution interval. 0 to 12 ms; duration 12 ms.
- Produce transfer input. 0 to 3 ms; duration 3 ms. Parent: Execution interval.
- Independent computation. 3 to 8 ms; duration 5 ms. Parent: Execution interval.
- Transfer to completion. 3 to 10 ms; duration 7 ms. Parent: Execution interval.
- Dependent computation. 10 to 12 ms; duration 2 ms. Parent: Execution interval.
A straggler is a participant that finishes later than its peers. Variable generation lengths make synchronous sampling wait for the longest response while completed requests leave capacity idle. Removing that barrier changes coordination semantics; asynchronous reinforcement learning additionally introduces policy-staleness constraints.
Aligned worker traces should separate readiness, transfer and dependent execution. A late collective completion can reflect a late producer, not merely a slow network. Timeline-led diagnosis and span boundaries explain how to preserve those distinctions.
Serving replicas, routing and request state
A serving replica is a complete executable model instance, possibly spread across a tensor-and-pipeline group. Routing chooses an instance; communication inside that instance executes the request. One shard cannot independently serve the whole model. KV capacity still limits concurrent state after weights fit; a logged concurrency estimate is not measured sustainable throughput.
Request affinity favors workers holding reusable state. Cache-aware routing balances that benefit against projected prefill and decode load: a colder but less busy destination can finish sooner. Cache creation and release events inform locality estimates. Destination selection and movement of KV state remain separate responsibilities.
Prefix reuse saves processing for compatible repeated token prefixes, not semantically similar text or future output tokens. Cache compatibility and local batching remain relevant inside every distributed instance.
Admission control bounds accepted work against available resources. Request count alone hides differences in computational cost. Preserve explicit rejection behavior when capacity is exhausted; queueing and sustainable capacity develops this boundary. Operational ownership belongs in AI Platform Engineering.
Prefill–decode separation and handoff
Separate prefill and decode pools can reduce scheduling interference and support different resource allocations. Short prompts offer less interference to remove; excessive prefill supply queues behind decode, while excess decode capacity waits idle. The operating point and request-length distribution determine whether separation helps.
DistServe transfers prompt KV state and the first generated token to decoding workers. Transfer demand depends on prompt length and arrival rate.
Separation adds a state handoff
Decode depends on usable transferred state.
Read the diagram as text
- Select workers.
- Process prompt.
- Transfer KV state.
- Continue decoding.
- Request failure.
- Select workers → Process prompt: Control: dispatch.
- Select workers → Transfer KV state: Control: destination.
- Process prompt → Transfer KV state: Success: derived KV data.
- Process prompt → Request failure: Prefill error.
- Transfer KV state → Continue decoding: Usable state received.
- Transfer KV state → Request failure: Handoff error.
The network can erase phase-specific advantages. In a heterogeneous local demonstration, cache traffic accidentally used Wi-Fi, leaving transfer exposed before decode. The intended Ethernet connection was a setup choice, not a universal sufficient bandwidth threshold.
A usable handoff needs compatible model execution, cache layout, positions and destination storage. Matching registered service names does not establish those properties. Dynamo's documented route returns prefill or handoff failure after dispatch rather than automatically falling back to aggregated execution. Local scheduling supplies the colocated alternative.
Correctness across partition boundaries
A bounded reference comparison starts with cloned parameters and optimizer state, identical examples and masks, and one intended update. Compare intermediate quantities as well as final parameters. A matching scalar loss can conceal a different gradient or input allocation.
| Boundary | Discriminating evidence |
|---|---|
| Input assignment | Compare example identities, padding, dropped tails and epoch order. |
| Shared update | Compare synchronized gradients and updated replicas from matching starting state. |
| Numerical result | Inspect error magnitude and structure under changed reduction order. |
| Request continuation | Check retained history and constraint state, not merely plausible output. |
Floating-point operations are not associative, so reordered reductions can differ numerically. Choose tolerances from numerical type, value scale and a trusted reference; no universal threshold excuses arbitrary error. Compare fixed-context inference outputs separately from sampled text. Numerical correctness explains the testing discipline.
Useful scaling and measurement boundaries
Strong scaling increases devices for fixed total work. Weak scaling increases total work while holding work per device fixed. These answer different performance questions.
Training throughput does not determine time to useful quality when batch size or learning behavior changes. MLPerf Training measures wall-clock time to a specified quality target and repeats runs. Retain that distinction when comparing your own corpus, objective and training recipe.
Serving goodput counts completed requests meeting declared latency criteria per benchmark second. Report offered load, errors and latency distributions separately; timely output can still be incorrect. Define first-content and continuation timing precisely. Serving experiments explains workload controls; cost and performance engineering extends the economic comparison.
Busy devices need not perform useful arithmetic efficiently. Krea used tensor-core utilization as a diagnostic proxy beyond GPU busy time. Neither replaces end-to-end completion or quality measurements.
Failure propagation and coordinated shutdown
A failure domain contains components exposed to a common failure. Missing participants can prevent collective completion and disable a cooperating model group. Independent replicas can continue only if their required devices and links remain usable. NCCL documents asynchronous communication errors and communicator abort/recreation; recreating communication does not restore lost application state.
Separate slow progress from process or device loss, broken communication, exhausted memory and numerical corruption. An elapsed timeout identifies missing progress, not its cause. Krea's experience shows why device counters alone are insufficient: fabric errors exposed faults despite apparently healthy GPUs. Failure localization requires competing explanations and per-worker evidence.
Recovery policy is implementation-specific. Under torchrun's documented elastic policy, worker failure stops and restarts the worker group within its restart limit. Membership changes also form a new group with new ranks and world size. Surviving processes are not a substitute for checkpointed progress.
Gang scheduling admits cooperating workers together. It addresses resource availability before execution, not restoration after failure. Krea separated queued-workload priority from execution priority and encountered stale capacity quotas as nodes changed.
Coherent checkpoints and training restart
A distributed restart needs one coherent training state, not unrelated shard files. A checkpoint manifest identifies saved tensor pieces. Distributed Checkpoint coordinates planning, rank writes and coordinator completion; loading writes into destination-allocated storage and can reshard tensors. Training continuity defines the resumable state beyond weights.
Asynchronous saving separates staging into CPU memory from storage upload. Protect source parameters until staging completes, including before the next optimizer mutation; other mutable training state needs equivalent protection. Upload completion is a later boundary. Await it before another save or final cleanup. Background staging also consumes CPU capacity and memory.
Shard writes precede reader entry
Reported write success gates metadata publication.
Read the diagram as text
- Stable checkpoint K.
- Write and synchronize shards.
- Gather write results.
- Publish final metadata.
- Reader enters K.
- Save failed.
- Stable checkpoint K → Write and synchronize shards: Shard data.
- Write and synchronize shards → Gather write results: Results or exceptions.
- Gather write results → Publish final metadata: No reported failures.
- Gather write results → Save failed: Reported failure.
- Publish final metadata → Reader enters K: Final metadata available.
In the inspected fresh-directory filesystem path, synchronized shard writes precede final metadata publication. The reader requires .metadata. Final metadata is not independent shard-integrity verification. Overwriting an existing checkpoint lacks an atomic old-or-new guarantee, and the path lacks parent-directory synchronization needed to establish stronger crash-durability claims.
Reported rank-write failures prevent coordinator finish. A vanished participant is outside that ordinary gathered-exception path.
Resharding changes storage ownership, not automatically the intended next update. Preserve effective batch size, loss weighting and input progress when worker count changes. Validate restoration through the next update, not merely successful tensor loading. Compare checkpoint overhead, lost work and actual restart time together.
Serving restoration and interrupted requests
| Responsibility | What it establishes |
|---|---|
| Discovery and routing | Removes unavailable endpoints; does not reconstruct interrupted requests. |
| Infrastructure reconciliation | The Dynamo Operator manages deployment resources; Grove represents configured worker groups and coordinated scaling. |
| Orchestration probes | Inspected worker readiness does not itself determine Dynamo traffic eligibility. Active health checks default off in that code. |
| Executable health | An active canary exercises backend inference. Frontend HTTP 200 can coexist with no discovered workers. |
A deployment can require whole-group replacement after losing a model shard. Its re-entry policy should explicitly require model loading, communication initialization, warmup, executable checks and routing registration. These are conditions to implement and test, not one universal Dynamo recovery sequence; configured grouping and controller policy determine replacement scope.
Retained output can exceed observed output
ExampleMigration tracks backend responses, not client acknowledgements.
Read the diagram as text
- Request R.
- Backend returns token b.
- Migrator retains a,b.
- Forward b upstream.
- Client snapshot: a only.
- Replacement attempt. Same request ID; reduced remaining generation budget.
- New continuation.
- Terminate request.
- Request R → Backend returns token b: Backend response.
- Request R → Client snapshot: a only: Separate observation.
- Backend returns token b → Migrator retains a,b: Record first.
- Migrator retains a,b → Forward b upstream: Then forward.
- Migrator retains a,b → Replacement attempt: Migratable error; parent active.
- Replacement attempt → New continuation: Replacement succeeds.
- Replacement attempt → Terminate request: Cannot continue.
Model artifacts, reconstructible KV state and client-observed output have different recovery boundaries. A service can fail an interrupted request or replay retained context. Planned shutdown first stops admission and can drain existing work. Replacing capacity does not by itself complete either policy for requests already underway.
The inspected migrator records returned token IDs before forwarding, adjusts remaining generation budget, and preserves request identity. That retained history is not a client acknowledgement cursor.
Replay support is bounded by tracking length and attempt limits. Multi-choice and structured-output requests need additional continuation state and are unsupported by the documented migration path. Replaying tokens does not advance a newly initialized constraint machine. Generation constraints explains why text history alone is insufficient.
Cancellation propagates through linked request contexts, but engines must observe it and stop computation. A received-signal metric does not confirm resource reclamation. Graceful stop does not retract already-streamed results; kill behavior depends on engine support. Streaming delivery separates generation, buffering and client observation.
A worker-loss test should record routing removal, restored executable capacity, interrupted-request outcome and client-visible output separately. Inject cancellation during recovery and observe actual engine termination. A passing minimal canary establishes executable reachability, not representative-load performance or seamless continuation.
Open questions
Adaptive placement must respond to changing request lengths without spending its savings on cache movement. Progress requires workload-shift experiments that include transfer, queueing and latency compliance, rather than a fixed optimal worker ratio.
Checkpoint publication still needs backend-specific integrity and power-loss guarantees. Metadata visibility alone cannot establish them; progress would include corrupted-shard, interrupted-write and concurrent-reader tests with explicit accepted restart states.
Elastic restart must preserve the intended update after group membership changes. Tensor resharding is easier than preserving sample progress and weighting; a decisive test compares the next restored update with an uninterrupted reference using identical examples.
Streaming recovery needs a delivery contract across frontend loss and reconnection. Backend replay lacks a client acknowledgement boundary; progress requires token-offset reconciliation plus cancellation tests that verify actual engine cleanup.







