POC: stop-gradient through context tokens (row-sparse backbone backward) - #3360
Draft
samsja wants to merge 1 commit into
Draft
POC: stop-gradient through context tokens (row-sparse backbone backward)#3360samsja wants to merge 1 commit into
samsja wants to merge 1 commit into
Conversation
Builds on skip_masked_lm_head_tokens: the same label-aligned keep mask is forwarded to the backbone, which keeps the forward bit-identical but makes the backward row-sparse - mask_grad cuts gradient propagation into context rows at every decoder layer input, and q/o/MLP projections run their backward GEMMs on kept rows only. k/v projections keep a full backward (kept queries attend to context k/v). Qwen3 dense only, opt-in via model.stop_grad_context_tokens. NOT gradient-exact by design.
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
model.stop_grad_context_tokens(defaultfalse): keep the forward pass bit-identical (context K/V are still built with current weights), but make the backbone backward row-sparse — gradients only propagate through tokens some loss component reads.Mechanism (
layers/row_sparse.py):mask_gradat every decoder-layer input: identity forward, backward zeroes context-row grads. This stops gradient propagation into context hidden states and everything below them.row_sparse_linearfor q/o and the dense MLP: full-row forward, backward compacted to kept rows (dW = dY[keep]^T @ X[keep],dX[keep] = dY[keep] @ W). Valid because under themask_gradcut their upstream grads are exactly zero on context rows.dK/dVon context rows are nonzero and feed the k/v weight grads — the model keeps learning how to read context; it stops learning how to represent it.Reuses the label-aligned
keep_maskfrom #3326 (hence the config validator requiringskip_masked_lm_head_tokens+ fused head). Wired for the custom Qwen3 dense backbone only; other models raise.Measured (4x RTX 3090, Qwen3-1.7B)
Single-GPU fwd+bwd microbench, seq 2048, on top of head-skip:
SFT A/B (wordle, 12 steps, 4 GPUs,
micro_batch_size=2, kept fraction 0.62): loss curves track closely (step 12: 0.4719 off vs 0.4816 on; grad norms lower with stop-grad, as expected with fewer gradient paths). No e2e speedup visible in this config — the runs were data-loader-bound (~40.8s fwd+bwd wall vs ~15s of GPU compute at these shapes; tokenization/packing dominates on this box), which masks the compute win the microbench isolates.Correctness tests (
tests/unit/train/test_row_sparse.py, all passing on GPU):torch.where(detach)reference (grads exact)Known gaps (POC)
backbone_keep_indexusesnonzero()(one D2H sync per micro-batch, same as the head-skip path in Don't compute the logprobs and their gradients for tokens no loss com… #3326).