Repository navigation
Conversation
…ction The DFlash family reads the draft's [rows, vocab] logits only through per-row statistics: KD cross-entropy against the teacher, label cross-entropy, the log-normalizer, argmax and top-k. New DFlashConfig.dflash_fused_loss (default off) computes them in row chunks fused with the frozen lm_head projection (plugins/dflash_fused_head.py). Each chunk is projected and reduced to its statistics, through torch.compile on CUDA, and every differentiable statistic writes its hidden-space Jacobian [rows, H] in the same pass. Backward is sum_t grad_t[r] * J_t[r], so any downstream combination is exact and no vocab-wide tensor outlives its chunk. The top-k logits are a differentiable output whose backward gathers the head rows one chunk at a time. Wired into HFDFlashModel._compute_loss (KD on the teacher's logits or its final hidden, label CE, D-PACE confidences, accuracy), the DFlash2 selector's candidates and the LiLiCorr lattice's candidates and normalizer. With the flag off every eager line runs as before. Convert refuses the flag when the class owning forward or _compute_loss does not declare support (DSpark, Domino), when lm_head is not a plain bias-free nn.Linear, and when lm_head is trainable. Loss path forward + backward at hidden 8192, vocab 202048, 4096 draft rows, one RTX PRO 6000, bf16 autocast, this tree's eager path vs fused: DFlash KD, hidden teacher 226 -> 184 ms, peak +12.3 -> +3.2 GiB DFlash KD, logits teacher 177 -> 130 ms, peak +12.3 -> +3.9 GiB DFlash CE 133 -> 122 ms, peak +7.7 -> +2.4 GiB DFlash2 CE+lambda + selector 147 -> 137 ms, peak +9.5 -> +2.4 GiB DFlash2 KD + selector 247 -> 201 ms, peak +12.3 -> +3.2 GiB LiLiCorr 242 -> 260 ms, peak +17.2 -> +5.1 GiB Loss rel <= 1.7e-5, accuracy and metrics equal, hidden-grad rel L2 3.5-4.4e-3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Contributor
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3010 +/- ##
========================================
Coverage 79.85% 79.85%
========================================
Files 661 662 +1
Lines 74935 75363 +428
========================================
+ Hits 59836 60181 +345
- Misses 15099 15182 +83
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This branch has not been deployed
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?
Type of change: new feature (training performance)
DFlash-family training projects the draft's rows through the frozen
lm_headinto[rows, vocab]logits, but the loss reads those logits only through per-row statistics:tv/lambda;New
dflash_fused_loss(defaultfalse) computes exactly those statistics in row chunks fused with the projection. The logits are never materialized whole.plugins/dflash_fused_head.py,fused_head_stats):torch.compile, on CPU eagerly.[rows, H]in the same pass. Backward is thensum_t grad_t[r] * J_t[r], so any downstream combination of the statistics is exact, and no vocab-wide tensor outlives its chunk.c * tanh(x / c)cap) is supported as explicit arguments. No head onmainapplies one, so the integration passes none.HFDFlashModel._compute_loss: KD with the teacher's logits (online) or its final hidden (offline/streaming), label CE, D-PACE confidences and accuracy._DFlashLossTerms.head_stats. With the flag off, every eager line runs as before.forwardor_compute_lossdoes not declare support in its own body. DSpark and Domino add a trainable[r -> V]projection to the logits, which this PR does not cover. They overrideforward, not_compute_loss, so both owners are checked.lm_headthat is not a plain, bias-freenn.Linearwith no forward hooks (e.g. quantized or accelerate-hooked);lm_head(dflash_freeze_base_model=false): the fused pass computes no head gradient.Results re-verified on this branch. One RTX PRO 6000 (250 W cap), torch 2.11, bf16 autocast as in the recipes. Shapes are those of the measured target: hidden 8192, vocab 202048, 2 x 256 blocks x 8 = 4096 draft rows. Timings are the loss path's forward + backward from the draft hidden, median of 5; peak is memory allocated above the step's inputs.
LigerFusedLinearJSDLoss(beta=0, no cap, no per-row weights, scalar output) at 4096 x 8192 x 202048: 278 ms, vs 194 ms forfused_head_stats(KD CE with per-row weights + TV), and 206 ms with the top-16 and the soft cap as well.Results from a fork of this repo (not
main), where this was first built. The fork's eager path did more redundant work thanmain's:.item()), against one onmain.The setup was a DFlash2 drafter (5 layers, hidden 8192, 24K MLP, block 8, 256 anchors) on a 202K-vocab MoE target whose head applies x0.177 and 20·tanh(x/20). Streaming training, per-device batch 2, seq 4096, DDP, compile + FlexAttention on.
What changed from the fork's version:
[rows, k, H]head rows held until backward (1 GiB at the shape above);mainreads them);torch.compile, so eager-attention runs with a varying row count do not recompile per shape.Online KD (teacher = the base's own logits) still costs what it costs today: the base builds
[B, seq, vocab]logits and the teacher rows are gathered as[rows, vocab](1.5 GiB in bf16 at the shape above). The fused path removes only the draft's side.Usage
Testing
tf_min/tf_latest). Each takes <= 0.3 s on 4 cores.test_dflash_fused_head.py: the primitive vs autograd on materialized logits, in fp32 with 5 chunks. It covers every statistic and its gradient under random per-row upstream weights, the top-k ids and their logits' gradient, no transform / multiplier / multiplier + cap, a hidden and a logits teacher, and values underno_grad.test_hf_dflash.py::TestDFlashFusedLoss: one training step, eager vs fused, comparing loss, accuracy and every draft gradient. Cases: online KD (logits teacher, D-PACE), offline KD (hidden teacher, decay) and CE.lm_headand a hookedlm_head.test_hf_dflash2.py: the same for DFlash2 with the selector live,ceandlambda.test_hf_lilicorr.py: the same for LiLiCorr with every lattice term on. Its gradient tolerance is scaled to each tensor, because the normalizer's share of the gradient is below a fixedatol.test_dflash_fused_head.py,test_hf_dflash.py,test_hf_dflash2.py,test_hf_lilicorr.py,test_hf_dspark.py,test_hf_domino.pyandtest_hf_dflash_offline.py: 312 passed on 5.5.4 and on 5.18.0.tests/gpu/torch/speculative/plugins/test_hf_dflash.py: 16 passed, 1 skipped (needs 2 GPUs). The newTestDFlashFusedLossGPUruns the compiled path for DFlash KD and DFlash2 + selector.Dependencies / related PRs
This PR is against
mainand needs no other PR._compute_lossintodflash_losses.LossContextand conflict with this PR inhf_dflash.py,hf_dflash2.pyandhf_lilicorr.py. Whichever lands second re-ports.LossContextwhosece,teacher,tvdand argmax come from one fused pass:kd->kd_ce;tvd->2 * tv;ce/tv/lambda->hard_cewith gradient;backbonelogits of DSpark and Domino could be fused._teacher_logits, which_fused_head_statscurrently applies itself.tvdterm would read the primitive'stv.[B, seq, vocab]base logits and the gathered teacher rows.hf_dflash.py; its per-row weights compose exactly with the fused statistics.CHANGELOG.rstonly. perf(speculative): deliver training batches out of order; compile + FlexAttention in the DFlash2 recipe #3001's compile + FlexAttention + out-of-order loading were on in the fork measurements.test_hf_dflash.pyonly.lm_headis refused here, because the fused pass computes no head gradient.lm_head, teacher top-1 metrics or extralkmodes tomain.Before your PR is "Ready for review"
Make sure you read and follow Contributor guidelines and your commits are signed (
git commit -s -S).Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded
trust_remote_code=True,torch.load(..., weights_only=False),pickle, etc.).CONTRIBUTING.md: N/AAdditional Information
🤖 Generated with Claude Code