Skip to content

Fix inter-iteration activation retention in HyperConnectionTransforme… - #6017

Closed
htesd wants to merge 2 commits into
NVIDIA:devfrom
htesd:fix/hc-mlp-norm-manager-retention
Closed

Fix inter-iteration activation retention in HyperConnectionTransforme…#6017
htesd wants to merge 2 commits into
NVIDIA:devfrom
htesd:fix/hc-mlp-norm-manager-retention

Conversation

@htesd

@htesd htesd commented Jul 24, 2026

Copy link
Copy Markdown

What does this PR do?

HyperConnectionTransformerLayer._forward_post_mlp_with_fused_hyper_connection never
releases self.mlp_norm_manager after calling group_offload(), unlike the base class
TransformerLayer._forward_post_mlp, which sets self.mlp_norm_manager = None right
after use.

Because FineGrainedActivationOffloadingInterface.__init__ stores the wrapped tensor
unconditionally (self.tensor = tensor, even when offload=False), the manager left
attached to the layer module keeps a reference to one microbatch's pre-MLP-norm input
until the next forward pass overwrites it. The memory is retained across the idle window
between iterations.

The effect is strongly amplified with recompute_granularity='full': the retained tensor
is the one produced during the recomputation pass, and its autograd history keeps the
layer's entire recomputation subgraph alive (stream-expanded residual buffers, h_post/BDA
outputs, input grads). Holding one (s, b, h) tensor ends up pinning (s, b, n*h)-sized
buffers several times over.

Measured impact

2-layer GPT config with hyper connections (num_residual_streams=4), bf16, mbs=1, mock
data, recompute_granularity='full', single GPU (H200), measuring
torch.cuda.memory_allocated() in the idle window between iterations:

metric before after
idle floor between iterations, seq 8192 29.30 GB 28.63 GB (−0.67 GB)
floor growth from seq 4096 to 8192 +0.61 GB +0.27 GB

Extrapolated to a 9-layer pipeline stage at 16k sequence length, the retention is roughly
7 GB of wasted per-GPU memory.

The one-line fix mirrors the existing cleanup in the base class _forward_post_mlp.

A possible follow-up hardening (not included here, to keep this minimal): make
FineGrainedActivationOffloadingInterface not store the tensor when offload=False.

…rLayer

Release mlp_norm_manager after group_offload, mirroring the base class
_forward_post_mlp. FineGrainedActivationOffloadingInterface stores the
wrapped tensor unconditionally (even with offload=False), so a manager left
attached to the layer keeps one microbatch's pre-MLP-norm input alive across
iterations; with recompute_granularity='full' its autograd history
additionally pins the layer's recomputation subgraph.

Signed-off-by: iiap <1471127927@qq.com>
@htesd
htesd requested review from a team as code owners July 24, 2026 08:21
@copy-pr-bot

copy-pr-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@hxbai

hxbai commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

/claude strict-review

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strict review passed — no significant issues found. LGTM

The one-line fix (self.mlp_norm_manager = None after group_offload()) correctly mirrors the existing cleanup in the base class TransformerLayer._forward_post_mlp (line 1138). mlp_norm_manager is set unconditionally earlier in the same forward path (line 2144), so it is always non-None at the group_offload call; nulling it afterward only releases the retained reference and has no effect on the returned hidden_states or subsequent computation. No API, config, checkpoint, or process-group concerns.

Findings — CRITICAL: 0, IMPORTANT: 0, SUGGESTION: 0. Risk level: low.

@hxbai

hxbai commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

/ok to test 9e35a29

@htesd

htesd commented Jul 30, 2026

Copy link
Copy Markdown
Author

Hi @hxbai, thanks for the approval! It looks like the CI run was cancelled due to infrastructure issues (unit test jobs were queued for ~42h, then stuck for 28h+ before the whole run was cancelled on Jul 27) — no job actually failed. Since the head commit is unchanged (9e35a29), could you re-trigger with /ok to test or re-run the cancelled workflow when you get a chance? Thanks!

@htesd

htesd commented Jul 31, 2026

Copy link
Copy Markdown
Author

/ok to test 9e35a29

hi there is something wrong in auto CI test could you re-trigger with /ok to test or re-run the cancelled workflow when you get a chance? Thanks!

@yaox12

yaox12 commented Aug 5, 2026

Copy link
Copy Markdown
Member

/ok to test 6a1b608

@htesd htesd closed this Aug 5, 2026
auto-merge was automatically disabled August 5, 2026 06:08

Pull request was closed

@htesd

htesd commented Aug 7, 2026

Copy link
Copy Markdown
Author

Heads-up @yaox12 @hxbai: this PR was not closed by me on purpose. My fork left the upstream fork network on Aug 5 (repo turned private for unrelated internal use), and GitHub auto-closes open PRs from a detached fork, attributing the close to the repo owner — hence the misleading "htesd closed this".

Re-opened as #6338 from a clean fork, rebased onto current dev (c76ff61), same one-line change. Sorry for the noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants