[Model Runner V2][Spec Decode] Add multi-layer MTP speculator - #48892
Conversation
72b61a6 to
4b60fca
Compare
4b60fca to
64844f8
Compare
dc083e1 to
19ffcbf
Compare
|
a41a208 to
f9c0159
Compare
07cca98 to
adb9f78
Compare
adb9f78 to
5a38676
Compare
Signed-off-by: Giancarlo Delfin <gdelfin@inferact.ai>
5a38676 to
f47488b
Compare
WoosukKwon
left a comment
There was a problem hiding this comment.
LGTM. Thanks for the cleanup!
|
Please follow up with the investigation on Pos 0 acceptance rate. It looks very mysterious/suspicious to me 🤔 |
|
@WoosukKwon I investigated the weird pos 0 acceptance rate discrepancy (observed with gsm8k using temp=0) between MTP 1: vs MTP 8: To debug, I bucketed the per-position acceptance rate by the previous step's accepted count (instrumented re-run, same config; headline numbers reproduced at 83.05% / 75.72%). Counts cover the first 25k / 10k drafts of each run. MTP 1:
MTP 8:
In both cases the position 0 acceptance rate is much lower when the previous step ended in a rejection: 70.43% vs 85.66% for MTP 1, and ~71% (prev 0–7, weighted) vs 90.21% for MTP 8. A rejection indicates that the current content is less predictable, so acceptance is strongly autocorrelated with local context difficulty. The discrepancy is a sampling effect, not a regression. A position 0 draft only happens at a chain restart. With MTP 1 that's every token, so only 4214/24887 = 16.9% of position 0 drafts follow a rejection. With MTP 8 it's once per accepted chain, so 7617/9885 = 77.1% of them do — position 0 is measured almost entirely on the hard subset. Applying MTP 1's conditional rates to MTP 8's restart mix predicts |
…roject#48892) Signed-off-by: Giancarlo Delfin <gdelfin@inferact.ai> Signed-off-by: Tej Kiran <kiran.tej@amd.com>
…roject#48892) Signed-off-by: Giancarlo Delfin <gdelfin@inferact.ai> Signed-off-by: root <root@smci355-ccs-aus-m02-09.cs-aus.dcgpu>
This became necessary after vllm-project#48892 made padded idx_mapping entries persist as -1 for all draft sampling modes. Signed-off-by: Yizhou Liu <liu_yizhou@outlook.com>
This became necessary after vllm-project#48892 made padded idx_mapping entries persist as -1 for all draft sampling modes. Signed-off-by: Yizhou Liu <liu_yizhou@outlook.com>
This became necessary after vllm-project#48892 made padded idx_mapping entries persist as -1 for all draft sampling modes. Signed-off-by: Yizhou Liu <liu_yizhou@outlook.com>
…roject#48892) Signed-off-by: Giancarlo Delfin <gdelfin@inferact.ai> Signed-off-by: Wu, Xiaochang <xiaochang.wu@intel.com>
Context
Multi-Module MTP is a variant of MTP that has a separate model layer for each speculative step (i.e. MTP module #i drafts the ith token). Currently the Inkling model's MTP model supports this, with up to 8 specualtive tokens. This PR adds a new speculator class (MultiModuleMTPSpeculator) to support this functionality.
Currently, only single-module MTP is supported in Model Runner V2, which uses the same, single MTP layer for speculating all N tokens.
NOTE: The changes to
vllm/models/inkling/nvidia/model.pywere ported over from #48768NOTE: This feature needs KV cache support (#50062) and multimodal embeddings lookahead (#50306) to function correctly. The benchmark results below were captured with those changes in place. The
MultiModuleMTPSpeculatoris currently DISABLED until the KV cache support PR is merged.This PR
The biggest challenge for implementing multi-module MTP was adding support to the scheduler for re-prefilling tokens from previous decode steps. The reason this is needed is because the last N-1 MTP layers receive draft tokens from previous MTP layers, which may or may not be rejected during target validation. If the R draft tokens are rejected, then the last R-1 MTP layers contain stale kv cache values for the rejected tokens, and must be updated. This necessitates re-prefilling tokens from the last decode step. Below is a concrete example, and how it's resolved:
Most of the changes to the scheduler, KV cache manager and coordinator were to support re-prefilling tokens in the draft model layers like this. Freeing/caching of KV blocks are delayed by the max number of re-prefillable tokens (
num_speculative_tokens - 1) to prevent updating KVs after they've been claimed by another request, or prefix-cached.The entire N token speculation is cudagraph captured. However, we have to build the attention metadata and slot mappings before the drafting loop, because the sequence lengths can change due to re-prefills.
Remaining TODOs
spec_step_idxinto the batch descriptor. Currently disabled.Evals
Server Config
GSM8K — full test set (1319 prompts, concurrency 64)
Full MMAU (scored, 1000 questions,
mmau.py --task all, concurrency 16)Benchmarks
GSM8K, Concurrency = 64, Temperature = 0
Speed-Bench (8K prompt / 2K generation), Concurrency = 16, Temperature = 0
MMAU Audio, Concurrency = 16, Temperature = 0
Speed-Bench (2K prompt / 2K generation / 256 prompts), Concurrency = 16, Temperature = 1)