feat(mtp): add optional ASD acceptance policy for greedy MTP verification - #1555
Kissmetothemoon wants to merge 2 commits into
Conversation
|
Thank you for your contribution. We’ll also test the performance gains on the H100. |
…t precompute - Register --mtp_asd_regret_budget/--mtp_asd_local_regret_ratio/ --mtp_asd_block_max_mismatch in api_cli.py so the documented launch command parses (fields already exist in StartArgs) - Clamp row_draft_token_ids to >= 0 before logits.gather: rows that do not verify a real draft (bonus row, -1 padding in sparse buffers) could read token id -1 and trip a device-side OOB assert; their regrets are masked out in the kernel, so clamping is semantics-neutral Addresses review on ModelTC#1555.
…tion Approximate Speculative Decoding (arXiv:2608.03447): relax strict greedy MTP verification by accepting draft tokens whose target-logit regret stays within a bounded per-request budget. Default off (strict, lossless); budget=0 or max_mismatch=0 recovers strict verification exactly. All ASD logic lives in the new plugin module triton_kernel/mtp_asd.py; existing files only carry config fields and the dispatch seam. Implements ModelTC#1552.
…t precompute - Register --mtp_asd_regret_budget/--mtp_asd_local_regret_ratio/ --mtp_asd_block_max_mismatch in api_cli.py so the documented launch command parses (fields already exist in StartArgs) - Clamp row_draft_token_ids to >= 0 before logits.gather: rows that do not verify a real draft (bonus row, -1 padding in sparse buffers) could read token id -1 and trip a device-side OOB assert; their regrets are masked out in the kernel, so clamping is semantics-neutral Addresses review on ModelTC#1555.
bbc281b to
4394702
Compare
|
Implements the proposal in #1552. Closes #1552. Bug 1 — CLI flags not registeredFixed in Bug 2 — gather OOB on bonus-row padding (-1)Fixed in Validation report (8×L20, CUDA 12.8, torch 2.9.1+cu128, FA3 backend)Re-validated on the rebased branch (fresh offline venv, clean working copy):
Quick throughput signal (GSM8K, 16 prompts, concurrency 16, fixed 256 output
ASD vs mean(strict): TPS +20.1% (one-sided +14.2%…+26.6%), verify steps −9.8%, |
Implements the proposal in #1552.
Motivation
Strict greedy MTP verification (
_fwd_kernel_mtp_verify) discards the whole draft suffix atthe first mismatched token. ASD (Approximate Speculative Decoding, arXiv:2608.03447,
Apache-2.0 reference implementation) relaxes this:
a draft token is accepted while its local regret against the target logits,
r_i = max_v z_i(v) - z_i(x_i), stays within an explicit per-request budget. This raisesaccept length and throughput for greedy users in exchange for a bounded, user-configurable
deviation. Budget
B=0(orm=0) recovers strict verification exactly — enforced as aunit-test gold standard — and the default (flag unset) keeps today's behavior bit-for-bit.
ASD is the acceptance-side counterpart of LightSpec: LightSpec decides how much to verify;
ASD decides how strictly to accept. The planner only consumes
accept_lenstatistics, sothe two compose without interference.
Measured on the paper's research evaluator (pure PyTorch, Qwen3-14B + DSpark block-7 draft,
8xL20, greedy, 1319 GSM8K requests): strict 66.21 tok/s / 79.682% vs ASD (B=2.0625)
75.04 tok/s (+13.34%) / 79.454% (-0.227pp); the B=0 arm is token-identical to strict
on every request. Engine-level LightLLM numbers will be filled in below before marking this
PR ready.
Modifications
StartArgs):--mtp_asd_regret_budget(B, defaultNone= strict),--mtp_asd_local_regret_ratio(g, suffix-value-weighted local cap), and--mtp_asd_block_max_mismatch(m, per-verify-step relaxed-token cap); validated in_launch_subprocesses(requires an enabledmtp_mode, non-negative values)._fwd_kernel_mtp_asd_verify+mtp_asd_verify()inlightllm/common/basemodel/triton_kernel/mtp_utils.py, mirroringmtp_verify's launchcontract. Per-row regrets are precomputed on device (max + gather over the same logits
that produced
next_token_ids; no host synchronization); the kernel applies the threeASD gates with the same accept_len semantics as strict verification (first infeasible
position stops, the target row is still committed). Rows accepted under a nonzero regret
commit the draft token into
next_token_idsin place, so the token counter,scatter_mtp_next_tokens, and response construction all work unchanged.ReqSamplingParamsManager.req_to_asd_cum_regret(allocated only whenASD is enabled, zeroed per request at the prefill seam
init_req_sampling_params,updated in-kernel after each verify step).
verify_mtp_tokensroutes to ASD only when the flag is set AND the wholebatch is greedy (
top_k == 1, same rule assample); sampled/mixed batches take thestrict path unchanged. The three decode call sites (
chunked_prefill,dp_backend,dp_backendoverlap) passlogitsandrun_reqsthrough; the overlap path refreshesthe pinned
next_token_idscopy after verify when ASD is enabled (the early copy racesahead of the in-place commit).
unit_tests/server/router/model_infer/mtp_speculative/test_mtp_asd_verify.py(6 CUDA tests: B=0/m=0 strict equivalence vs
mtp_verify, hand-computed budgetdeduction, local-ratio gate, mismatch cap, all-accepted bonus semantics, cross-step
budget persistence) + ASD arg-validation cases in
unit_tests/server/test_mtp_start_args.py.Accuracy Tests
pytest unit_tests/server/router/model_infer/mtp_speculative/test_mtp_asd_verify.py— 6 CUDA tests(B=0/m=0 strict equivalence vs
mtp_verify, hand-computed budget deduction, local-ratiogate, mismatch cap, all-accepted bonus semantics, cross-step budget persistence).
Written alongside the kernel; I do not have a CUDA box at hand right now, so these are
intended to run on GPU CI — happy to post results once CI (or a maintainer's GPU run)
executes them.
pytest unit_tests/server/test_mtp_start_args.py— ASD arg-validation cases pass locally(CPU, monkeypatched launch path).
to be run on GPU hardware during review; the algorithm-level numbers above come from the
paper's research evaluator.
Speed Tests
The only added hot-path work when ASD is enabled is one
max+gatherreduction overthe verify logits plus a per-request verify kernel with the same launch shape as
mtp_verify; strict path is untouched (zero overhead when disabled).Usage
Unset
--mtp_asd_regret_budget= strict verification, zero behavioral change.--mtp_asd_regret_budget 0= ASD code path with exact strict semantics (sanity arm).ASD is approximate decoding: outputs may deviate from strict greedy within the configured
budget; v1 applies to all-greedy batches only (sampled batches fall back to strict).