advanced28 min studyLesson 548 in Engineering

Prefetching: hide communication only inside a live-memory budget

Analyze allocation lifetimes and overlap windows instead of estimating peak memory from steady-state shards or CPU enqueue timing.

On this page

What you’ll understand

  • Calculate a peak from explicitly disjoint simultaneously live allocations.
  • Scope PyTorch FSDP prefetch and all-gather rate limiting.
  • Separate an ideal overlap opportunity from a measured critical-path improvement.

A fully sharded model can fit between operations and still run out of memory when current parameters, prefetched parameters, gradients, and activations coexist. Prefetching moves a communication operation earlier; it also moves the start of an allocation’s lifetime earlier. We use PyTorch 2.9’s FullyShardedDataParallel wrapper as the concrete API scope. Its prefetch and rate-limiting options trade scheduling opportunities against memory, but they do not replace a full accounting of actual live storage and allocator behavior.

Peak memory follows overlapping lifetimes

Draw a timeline for persistent shards, current full parameters, next full parameters, unreleased gradients, activations, workspaces, and communication buffers. Count shared storage once: two views into one allocation do not consume two complete allocations, while two independent buffers do. Use measured allocation lifetimes to decide whether the persistent shard remains alongside a full buffer or whether storage is reused. A simple sum is meaningful only when the listed allocations are disjoint and simultaneously live. Otherwise it can either double-count aliases or miss a short but decisive overlap.

Reserved allocator memory and live tensor memory are also different observations. Fragmentation, caches, asynchronous release, and library workspaces can make a process fail below a naive sum of named tensors. Leave a measured margin and record the exact memory statistic used. Activations change with sequence length, microbatch size, and rematerialization policy; a parameter-only budget does not capture that variation. Test a representative worst-case input and the complete update lifecycle, including first-iteration initialization and checkpoint operations if they are part of the claimed capacity envelope.

Mpeak=max⁡t∑a∈L(t)bytes⁡(a)M_{\rm peak}=\max_t\sum_{a\in\mathcal L(t)}\operatorname{bytes}(a)
L(t) contains distinct physical allocations live at time t; aliases are counted once. The result is live allocated bytes under this inventory, not necessarily allocator-reserved or total device memory. Hidden runtime allocations must be added before interpreting a real capacity bound.↔ Scroll wide equations horizontally.

Prefetch options create specific schedules

The pinned FSDP wrapper’s BACKWARD_PRE fetches the next parameter set before the current gradient computation, increasing overlap opportunity while potentially holding current parameters, next parameters, and current gradients together. BACKWARD_POST changes that issue and release order to reduce the simultaneous parameter footprint with less overlap. Its forward-prefetch option follows the learned execution order and is documented for static-graph cases. These are schedule contracts, not interchangeable “faster” switches; dynamic execution and other wrappers require their own analysis.

The limit_all_gathers option throttles CPU issue so that parameter all-gather allocation stays bounded to the relevant consecutive instances in its documented schedule. A deliberate CPU gap can therefore be a memory protection mechanism rather than an idle-GPU bug. It does not bound activations, optimizer state, workspaces, or every allocation in the process. Removing it can issue work earlier while causing an out-of-memory failure. Measure device execution and the actual critical path instead of treating the absence of a CPU enqueue gap as proof of improvement.

Texposedideal=max⁡(0,Tcomm−Tindependent)T_{\rm exposed}^{\rm ideal}=\max(0,T_{\rm comm}-T_{\rm independent})
Both durations are nonnegative seconds. This optimistic two-operation model assumes communication can overlap fully with available independent compute and introduces no contention or extra dependencies. Real exposed time can be larger, and earlier communication may increase live memory.↔ Scroll wide equations horizontally.

Tune overlap under a correctness and capacity constraint

Change one prefetch or wrapping decision while holding the objective and input workload fixed. Check parameter availability and update equivalence, then compare step time, communication completion, peak live memory, and reserved memory. An apparent speedup from a short run can disappear under long sequences or an accumulation window that retains full gradients. Include recovery after a failed allocation in the operational test plan, but do not continue a partially failed distributed step as though the optimizer state were known consistent. Memory safety and collective consistency remain constraints on any throughput experiment.

The queue lab offers only an average outstanding-work analogy. Reset, explicitly set arrival four and service three, predict growth from four items, then Play or Step. Compare a separate Reset with arrival two and service three explicitly restored before predicting drainage. Edits retain elapsed time and recompute the initial-value formula. Items have no byte sizes or lifetimes, and the model contains no FSDP rate limiter, all-gather, stream, or allocator. A live-allocation timeline, not this analogy, establishes the actual prefetch memory peak.

One prefetched unit can cross the memory boundary

A hypothetical rank has four GiB of persistent disjoint storage, three GiB of live activations, 0.5 GiB of other live workspace, and one additional one-GiB current materialized parameter buffer. A next-unit prefetch adds another independent one-GiB buffer before anything is released. The budget is nine GiB.

  1. Without the next buffer, the stated simultaneously live inventory is 4+3+0.5+1=8.5 GiB. This fits the hypothetical budget with 0.5 GiB of modeled headroom, excluding any unlisted allocations.

  2. Prefetching the next unit raises the stated peak to 9.5 GiB. It exceeds the nine-GiB budget by 0.5 GiB even though the persistent sharded state remains four GiB.

  3. A schedule that releases current storage before allocating the next buffer can reduce this overlap, but may expose more communication. Determine whether the actual wrapper, stream dependencies, and aliases support that schedule rather than subtracting a buffer from a spreadsheet without changing its lifetime.

The result

The extra live prefetch buffer breaks the stated capacity budget. Persistent shard size alone would miss the failure.

Explore the model

Interactive lab

Interactive lab · queue

Outstanding work pressure is not GPU memory occupancy

Use independent Reset → explicitly set BOTH rates → predict → Play/Step runs for (λ,μ)=(4,3) and (2,3). Each begins with four abstract items. No item has a byte size, allocation lifetime, or FSDP rate-limiter identity.

Outstanding work pressure is not GPU memory occupancyFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forAn accumulating work queue suggests why bounded issue matters, but only actual live-allocation evidence determines a memory peak.

Check your understanding

A visible CPU gap appears with FSDP limit_all_gathers enabled. Which interpretation is justified?

Try it yourself

A disjoint live inventory contains three GiB persistent storage, two GiB activations, 0.5 GiB workspace, and current and prefetched parameter buffers of 0.75 GiB each. Compare with a 7.25-GiB budget. If communication takes four ms and independent compute offers three ms, what is the ideal exposed time?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Sum only simultaneously live distinct allocations, then use the optimistic overlap formula separately from memory arithmetic.

Compare with the solution

The listed peak is 3+2+0.5+0.75+0.75=7 GiB, leaving 0.25 GiB of modeled headroom. Unlisted runtime allocations, allocator reservations, fragmentation, or a different lifetime can consume that margin. The ideal exposed communication is max(0,4−3)=1 ms under full overlap with no contention or extra dependency. That time model does not prove the actual schedule is feasible or faster. Verify both device events and memory under representative inputs.

Take it with you

  • Budget simultaneous physical allocations rather than only persistent shards.
  • Prefetch and rate limiting change lifetime and issue order.
  • Validate overlap gains within the actual memory and correctness constraints.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.