Add correctness-first Domino support to DFlash V2 - #31328
jianuo-huang wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for the Domino speculative decoding projector within the DFlash framework. It adds configuration parsing, runtime validation, weight loading, and sequential greedy rollout logic using a prefix GRU and embedding projection, along with corresponding unit and integration tests. The review feedback suggests optimizing performance by precomputing base logits in a single batched operation instead of sequentially inside the rollout loop, and improving robustness when checking for required projector weights by defensively handling potential parameter prefixes.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
987e10f to
a7bb8af
Compare
…the serve rationale DOMINO is not an engine-level speculative algorithm: engines expose Domino as "dflash" and enable the causal correction head (prefix_gru + embed_proj) from the checkpoint dflash_config.projector_type="domino". A speculative_algorithm=DOMINO would leak into SGLang ServerArgs and fail cryptically, so mirror the vLLM guardrail and raise at the SGLang ServerArgs builder. Also correct both guardrail messages. The previous wording claimed Domino cannot be served and that its correction head is inert, which is wrong: serving with DFLASH keeps the Domino head active on engines that support it (vllm-project/vllm#48241, sgl-project/sglang#31328). Signed-off-by: khazic <khazzz1c@gmail.com>
* feat(backends): add Domino drafter training backend Port the Domino training path from NeMo AutoModel (dflash/domino_core.py) into the SpeCo overlay as a DFlash variant, mirroring how DSpark extends DFlash. Domino adds a causal correction head on top of the DFlash parallel block backbone: a single-layer GRU encodes a causal state from each block's previous tokens, and a low-rank embed_proj over [backbone hidden | GRU state] emits a full-vocab logit delta added to the parallel base logits. Training jointly supervises the refined (final) and backbone-only (base) logits with a base-anchor curriculum loss = (1-lambda)*final + lambda*base, lambda decaying to 0. The shifted-label alignment (target x[a+1:a+1+block], prev [x[a], labels[:-1]], every position supervised) reuses the DSpark alignment, which equals AutoModel's shift_label Domino path. DominoTrainerBackend subclasses DFlashTrainerBackend; only build_model and the training forward differ. Wired through worker dispatch, base_trainer block-drafter gates, auto config routing, oldlogprob aux layers, and config keys. Domino is training-only: its GRU correction has no stock vLLM proposer, so the vLLM config builder raises and directs serving to DFLASH (the trained backbone). AI assistance was used for this change. Signed-off-by: khazic <khazzz1c@gmail.com> * test(domino): add GPU hardware smoke for the Domino backend AI assistance was used for this change. Signed-off-by: khazic <khazzz1c@gmail.com> * fix(domino): compute dual-logit CE in fp32 and avoid full final-logits clone AI assistance was used for this change. Signed-off-by: khazic <khazzz1c@gmail.com> * style(domino): drop unused torch import AI assistance was used for this change. Signed-off-by: khazic <khazzz1c@gmail.com> * fix(domino): guard None drafter model_path in build_model os.path.join crashes with a TypeError when rollout.drafter.model_path is None (training a Domino drafter from scratch with no pre-existing weights). Guard config_path so it falls back to None and the existing checks route to the from-scratch fallback config path instead of crashing. Signed-off-by: khazic <khazzz1c@gmail.com> * test(domino): skip lambda-base test without torch to fix CPU CI test_domino_lambda_base_schedule imported get_lambda_base from domino_trainer_backend, whose module subclasses the torch-based DFlash backend at import time, so the torch-free CPU unit-test job hit ModuleNotFoundError: No module named 'torch'. Guard with pytest.importorskip like every other test in the file. Signed-off-by: khazic <khazzz1c@gmail.com> * feat(domino): guard the SGLang serve path against DOMINO and correct the serve rationale DOMINO is not an engine-level speculative algorithm: engines expose Domino as "dflash" and enable the causal correction head (prefix_gru + embed_proj) from the checkpoint dflash_config.projector_type="domino". A speculative_algorithm=DOMINO would leak into SGLang ServerArgs and fail cryptically, so mirror the vLLM guardrail and raise at the SGLang ServerArgs builder. Also correct both guardrail messages. The previous wording claimed Domino cannot be served and that its correction head is inert, which is wrong: serving with DFLASH keeps the Domino head active on engines that support it (vllm-project/vllm#48241, sgl-project/sglang#31328). Signed-off-by: khazic <khazzz1c@gmail.com> * fix(domino): compute top5_correct so top5_acc is not always zero top5_correct was initialized to zero and never reduced, so the top5_correct_count diagnostic (which base_trainer turns into top5_acc) stayed pinned at 0. DFlash and DSpark both compute it; Domino did not. Mirror the existing top1 idiom in this forward: take topk over the base logits and overwrite the suffix rows from the Domino-corrected logits, so no second [num_active, vocab] tensor is materialized. Guard topk with min(5, vocab) like DSpark does, for small-vocab configs. Adds a CPU regression test that fails without the fix (top5=0 vs top1=2). Signed-off-by: khazic <khazzz1c@gmail.com> * docs(domino): correct the serve rationale in the module docstring The docstring still claimed Domino is training-only and that its correction head has no engine proposer. Domino is a projector_type sub-mode of DFlash: the serve method stays dflash and the head is enabled from the checkpoint, so align this with the guardrails in vllm_runtime and sglang_runtime. Signed-off-by: khazic <khazzz1c@gmail.com> --------- Signed-off-by: khazic <khazzz1c@gmail.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
8a43e4c to
d6222a4
Compare
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
ec28069 to
19ed8f1
Compare
19ed8f1 to
dba1120
Compare
Summary
This PR adds Domino projector support to the current DFlash V2 worker for the
public
Huang2020/Qwen3-8B-Domino-b16checkpoint. It reuses SGLang's existingtarget
verification, continuous-prefix acceptance, bonus-token handling, and KV-cache
commit paths unchanged.
The implementation is independent of the earlier integration in #28998 and is
based on the public Domino reference and the current DFlash V2 interfaces.
Addresses #28977 and #29511.
Design
bias-free prefix GRU and two-layer SiLU correction projector.
the full-vocabulary DFlash argmax; the GRU is initialized with
[verified_token, first_proposal], and every realized proposal is fed backbefore the next correction step.
per-request, block-shared candidate pool with
K=2048by default; set--speculative-domino-candidate-pool-size 0for full-vocabulary correction.nn.GRUfor the two-token prefix and ATenGRUCellfor the 13one-token feedback updates.
eager fallback when the graph is disabled or unavailable.
The four performance changes are documented separately:
Supported and numerical scope
pure_draft_prefix_len=1, and block size 16.--disable-cuda-graph-padding. Padded replay is not claimed.proposal tokens are not generally bit-exact.
K=2048is an approximate search for the correction argmax. Targetverification is unchanged, but the observed K2048-versus-K0 output parity is
limited to the fixed workloads reported below; it is not a general
equivalence guarantee.
Validation
0.950, averagespeculative acceptance length
4.5544(gates:>=0.90and>4.0).0.950in botharms and
0/208fixed-512 ShareGPT text mismatches.0/21,900proposal mismatchesover 20 random trials per batch. GSM8K-200 remained
0.950.32/32output-IDsequences with acceptance length
4.7975; ShareGPT C32 matched128/128texts with acceptance length
3.7980.independence, candidate-pool, sampler, and CUDA Graph replay tests:
22 passed,23 subtests passed.Performance summary
The first table is a standalone Domino-rollout benchmark on one A100 80GB,
BF16/TP=1, 15 proposals, exact batch shapes, and full-vocabulary correction
(
K=0). Target verification and the DFlash backbone are excluded. Values arethe median of six balanced measurements with 30 CUDA-event iterations each.
Parenthesized base-logit time is included in the total but belongs to DFlash; it
is not Domino-specific overhead.
Perf 4 uses a separate candidate-pool harness and aggregation, so it is reported
as its own K0 A/B rather than appended to the table above.
The same parenthesized DFlash base-logit time is included in both Perf 4 arms.
Using SGLang's official serving benchmark runner:
11.2%,3.4%, and1.5%at concurrency 1/8/32.5.8%,3.5%, and1.9%; C32 acceptance length changed by-0.16%.1450.31versus1431.25output tok/s atC32 (
+1.3%). This was one run per K and is treated as exploratory/noise-level,not a serving-speedup claim.
Final end-to-end serving benchmark
A final 135-cell TP1 serving sweep compared target-only decoding, the official
Qwen3-8B DFlash b16 draft, and Domino b16 K2048 on one A100 80GB.
Full settings and all numerical results: benchmark comment.
Rollout microbenchmark speedups are not end-to-end serving claims. Exact setup,
correctness data, caveats, figures, and benchmark commands are in the four
linked performance comments.
Checklist
CI States
Latest PR Test (Base): ❌ Run #33199855245
Latest PR Test (Extra): ❌ Run #33199855055
Latest PR Test (AMD ROCm 7.2): ❌ Run #33199855228