Repository navigation
Conversation
|
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. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review: 3
Please check the settings in the CodeRabbit UI or the
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3001 +/- ##
=======================================
Coverage 79.79% 79.80%
=======================================
Files 661 661
Lines 74935 74936 +1
=======================================
+ Hits 59798 59799 +1
Misses 15137 15137
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:
|
edd263c to
de964a6
Compare
de964a6 to
515d225
Compare
…lexAttention in the DFlash2 recipe Add training.dataloader_in_order (default false) to the speculative-decoding training arguments. With dataloader workers, a rank then takes whichever batch a worker finishes first instead of waiting for its slowest outstanding sample, and DDP no longer turns one rank's slow fetch into a stall on every rank. HF Trainer forwards the flag itself only from transformers 5.15, and accelerate's DataLoaderShard forwards attribute reads, not writes, to the torch loader it wraps. EagleTrainerWithAccLog.get_train_dataloader therefore sets it on that loader. The field shares HF's name, so on 5.15+ it overrides HF's own default. Context parallelism keeps in-order delivery: accelerate gives every rank of a CP group the same data shard, and each loads it on its own, so out of order they would split different sequences at the same step. Measured on DFlash2 streaming training, 8 trainer nodes x 4 GPUs, DDP, global batch 64, seq 4096, 8 workers per rank, same data_seed: - in_order=False at 8 serve + 8 trainer nodes: 0.655 -> 0.523 s/step; serve replicas 26% -> 3% idle; worst per-rank batch wait 5.9 s -> ~2 s. - Over ~2.5K steps: mean |loss diff| <= 0.016, mean acceptance diff within +-0.003. Also turn on dflash_use_torch_compile and dflash_use_flex_attention in the DFlash2 recipe, the configuration the numbers below were measured with. With the trainer as the bottleneck (12 or 16 serve + 8 trainer nodes) compile gave 0.445 -> 0.386 and 0.446 -> 0.389 s/step with no recompiles over 2.5K steps; when serve-bound it gave nothing. On one GPU at the shipped online example's shape (PyTorch 2.10, tf32 off) the recipe goes from 1612 to 985 ms/step (1.64x). On PyTorch 2.9/2.10 the recipe's tf32: true makes Inductor's TF32 check raise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
515d225 to
a35712e
Compare
Stack (merge in this order; each PR's base is the branch of the one before it). [4/4] reproduces nvidia/Muse-Spark-Open-816B-A42B-DFlash2 and needs all of them.
What does this PR do?
Type of change: new feature
Two speculative-decoding training speedups.
1. Out-of-order training batches. New
training.dataloader_in_order, defaultfalse. With DataLoader workers, a rank takes whichever batch a worker finishes first instead of waiting for its slowest outstanding sample (head-of-line blocking). Per-sample fetch latency varies, and DDP lockstep turns one rank's stall into a stall on every rank.in_orderonly from transformers 5.15. accelerate'sDataLoaderShardforwards attribute reads, not writes, to the torch loader it wraps, soprepared.in_order = Falsesilently does nothing.EagleTrainerWithAccLog.get_train_dataloadertherefore sets it on the underlying loader. The field shares HF's name, so on transformers >= 5.15 it overrides HF's own default.training.dataloader_in_order=truerestores it. Nothing changes withdataloader_num_workers=0, the online-mode default.init_distributed_envsets the flag totruewhencp_size > 1.skip_first_batchesrebuilds the loader and carriesin_orderover (accelerate >= 1.3). With older accelerate, the first partial epoch after a resume runs in order. The resume position is exact only to within the batches in flight at the save, at mostnum_workers x prefetch_factorper rank.2. Compile + FlexAttention in the DFlash2 recipe:
dflash_use_torch_compileanddflash_use_flex_attentiongofalse -> trueingeneral/speculative_decoding/dflash2.yaml, the configuration the multi-node numbers below were measured with.dflash,domino,dspark,lilicorr*and the launcher examples are unchanged; they are possible follow-ups.One GPU (RTX PRO 6000, PyTorch 2.10,
tf32=false), the shipped online example's shape (Qwen3-8B, seq 4096, 512 anchors, SWA 2048, bs 1), 40 steps:Measured on DFlash2 streaming training. A large MoE target is served by vLLM replicas (TP4/EP4), and the trainer pulls hidden states over RDMA. 8 trainer nodes x 4 GB300, DDP, global batch 64, seq 4096, 8 workers per rank, same
data_seedthroughout. These numbers come from a fork of this repo, not frommain:in_order=False, 8 serve + 8 trainer nodes: 0.655 -> 0.523 s/step (+25%). Serve replicas went from 26% idle to 3%, and the worst per-rank batch wait from 5.9 s to ~2 s.dflash_use_flex_attentionon, as this recipe now does, with DDP and bf16.Compile caveats, found while testing this PR:
tf32: truemakes Inductor raise on the first step ("mix of the legacy and new APIs to set the TF32 status"). transformers enables TF32 throughtorch.backends.fp32_precision, and Inductor 2.9/2.10 then reads the legacyallow_tf32flag, which raises. Inductor reads it whenever the compiled graph has an fp32 CUDA matmul, and the draft's rotary embedding is one. PyTorch 2.8 and >= 2.11 are fine, and so is the launcher's default TRT-LLM container (an NGC 2.11 pre-release). Workaround:training.tf32=false, ordflash.dflash_use_torch_compile=false.dflash_num_anchors, while eager sizes it to the batch. With short answers the padding costs more than compile saves: in a toy run with ~35-token answers at seq 512, steps were 3.6x slower._get_attn_fncaches the attention function on the module inside the compiled region.Usage
Testing
tests/unit/examples/test_speculative_decoding_main.py::test_dataloader_in_order_reaches_the_torch_loader[False/True]test_context_parallelism_keeps_batches_in_order[1/2]:init_distributed_envforces in-order delivery forcp_size=2only. Thecp_size=2case fails without the guard.tf32=false: also 1.05x. Adding flex: compile is 1.11x over eager-with-flex, 1.64x over the current recipe.tf32on) end to end on PyTorch 2.11; the table above is 2.10 withtf32=false. Not run in this tree: multi-node DDP (the numbers above come from the fork), FSDP, and acceptance-length eval.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.).training.dataloader_in_order=truerestores it), and the DFlash2 recipe now compiles and uses FlexAttention.CONTRIBUTING.md: N/AAdditional Information
🤖 Generated with Claude Code