[Dev] Add schedule-aware cross-stream tensor lifetime management - #6948
Draft
lhb8125 wants to merge 3 commits into
Draft
[Dev] Add schedule-aware cross-stream tensor lifetime management#6948lhb8125 wants to merge 3 commits into
lhb8125 wants to merge 3 commits into
Conversation
lhb8125
force-pushed
the
hongbinl/schedule-aware-tensor-lifetime
branch
4 times, most recently
from
September 2, 2026 14:38
f5ee850 to
7123086
Compare
lhb8125
force-pushed
the
hongbinl/schedule-aware-tensor-lifetime
branch
from
September 2, 2026 14:44
7123086 to
611cb83
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
This PR adds an opt-in, schedule-aware lifetime path for the two cross-stream tensors retired by fine-grained EP overlap:
free_inputpolicy;The implementation is deliberately local to one
TransformerModelChunkSchedulePlan/ microbatch. It does not maintain a process-wide tensor provenance registry, event generations, replay epochs, or autograd hooks.For a normal schedule-local edge, the layer topology already identifies the owner stream:
After the consumer returns, the manager stores one strong-reference payload in
pending[owner_stream]. A later real node on the owner stream executes the existing plan-event wait first, then drains that queue:The wait must precede
resize_(0): resizing is a host-side allocator operation, so making the block allocator-visible before enqueueing the owner-stream wait would create a reuse race.Forward retirement uses
untyped_storage().resize_(0). Backward retirement only holds and later drops an extra strong reference; it never resizes gradient storage. Inputs from an unknown external boundary and detached extra gradients retain the conservativerecord_stream()fallback.The feature is disabled by default:
Why?
record_stream()correctly prevents use-after-free, but a logically freed block remains pending until the recorded consumer event completes and the allocator observes completion. Under fine-grained overlap this can raise the allocator high-water mark when CPU enqueue gets ahead of GPU consumers or completion has a long tail.The schedule already has the required producer/consumer dependency. Reusing that dependency lets the owner stream reclaim the tensor without introducing a host synchronize or an additional cross-microbatch dependency.
Corner cases
NoopScheduleNodecarries the same object through to the next real consumer.N-2offset is encoded.record_stream()fallback.Validation
All tests and benchmarks below ran directly from commit
611cb8355. Focused unit tests usedone 8x B200 node; the wide/long-sequence memory and performance A/B used 32 GB300 GPUs.
optim_grads_params/optim_grads: 4 passed.tools/autoformat.shcheck and copyright check pass. The local lint environment reports the repository's existing missing dependency/type-stub mypy diagnostics; black, isort, pylint, and ruff pass.Memory A/B
The hero case keeps DeepSeek-V3's full hidden/expert width while increasing the sequence length:
14 layers (3 dense + 11 MoE), hidden size 7168, FFN 18432, 256 experts, MoE FFN 2048,
MTP1, TP1/PP1/EP16, MBS2/GBS1024, sequence length 6144, MXFP8, HybridEP combined-1F1B,
eager mode, 32 GB300 GPUs. Each iteration contains 16 microbatches. Only rank 31 records
allocator history; control and feature snapshots contain 193,551 and 193,620 allocator events.
The dominant dispatch/FC2 blocks are about 1.32 GiB each. Control has six dispatch and six
grouped-GEMM outputs simultaneously pending; feature reduces the target peak to one trace-level
free_requested -> free_completedtransient, with zero target pending at its reserved high-water.Reserved savings are reported from the actual allocator high-water and are not inferred from the
pending-byte delta.
Performance A/B
The same hero configuration was run without memory history for 12 steps per arm. To eliminate
GB300 node-group variation, feature explicitly reused the exact same eight nodes immediately after
control. Results exclude iterations 1-4 and the periodic-GC iteration 11.
Both arms completed normally with no skipped or NaN iterations. Median and mean are well inside
the predefined +0.5% regression threshold, so this is treated as performance parity, not a speedup.
Scope
This PR does not change the other
record_stream()call sites used by residual paths, shared experts, or loss-storage helpers. The new behavior remains opt-in while broader production-scale and full-iteration CUDA Graph coverage is collected.