Add DeepSeek V4 DSpark proposer - #25
Conversation
3411a4d to
32dd326
Compare
|
Could you share your |
|
Oh, it seems my local model DeepSeek-V4-Flash-DSpark is corrupted. |
|
vllm main has merged DSpark support, I'm trying to rebase first, and see what we are lacking |
|
vllm-start.sh: exec "$_VLLM_BIN" serve "$@" >> "$LOG_FILE" 2>&1 |
|
Updated in The v1 kernel reread the same Kernel microbench on RTX PRO 6000 Blackwell:
Upstream DSpark uses a different path: topk-index sparse-MLA reuse on SM90/SM100 and FlashInfer sparse-MLA on SM100/SM120. I did not benchmark upstream on SM100, so I am not claiming a direct SM100 win. The closest measured comparison for this V4-Flash shape was the general FlashInfer sparse-MLA path on SM120, which was flat at ~133 us/call; v2 is ~15 us/call on the same shape. Upstream still has the cleaner long-term framework/reuse story, but this kernel is the better fit for this PR's current SM120 V4-Flash path. This is a kernel cleanup/latency win rather than a claimed end-to-end TPS win for V4-Flash; earlier live A/B was throughput-neutral because target forward dominates the step. Local validation:
|
I'm rebasing upstream now. |
|
Rebased, please rebase |
Enable the fused probabilistic Markov sampler by default for method=dspark and remove the VLLM_DSPARK_FUSED_MARKOV_SAMPLER environment variable. The config field remains available for explicit bisects. Reuse envs.env_bool for DSpark SpeculativeConfig gates and document the same-step aliasing invariant for the shared draft-probs no-copy fast path.
Document that the Python seed counter must not be frozen by any future CUDA graph capture around sampling. Avoid an unnecessary clone on the top-k/top-p fused sampler path when dtype conversion already produced a float32 copy, while preserving a clone for existing float32 inputs.
370b45a to
c95e38c
Compare
|
rebased and fixed |
|
I need more time to verify. And I'm also testing Model Runner 1 vs 2 |
|
Update: I took the branch further and I think the headline finding is good news for your design — your V1 I checked it out, activated the V1 path, and validated on 2×RTX PRO 6000 (SM120, TP=2) with the DSpark checkpoint. The V1 path is complete and just needed un-gatingThe V1 Why V1 is worth defaulting toThe decisive reason is correctness: on our stack the V2 runner has a DeepSeek-V4 long-context recall bug (needle recall collapses under concurrency): plain V4-Flash and DSpark on V2 both score ~3/16 on an arthur-style needle test at ~28k context / concurrency 8, while V1 is 16/16. So DSpark-on-V2 inherits it; DSpark-on-V1 doesn't. On perf (same build, same workload, fixed seeds, fresh serve per cell; single-sample spec-decode throughput is very noisy so treat tok/s ranges with care):
Interesting tradeoff: V1's draft acceptance is markedly higher (your V1 (The DSpark draft model reports it doesn't support Three small edits to make V1 the clean default (branch
|
…stence DSpark (PR #25) shipped a complete V1 DSparkProposer but was force-routed to the V2 runner, where DeepSeek-V4 long-context recall collapses under concurrency (arthur 3/16 @28k vs V1 16/16). Validated DSpark on the V1 runner on 2xRTX SM120: recall 16/16 @28k conc8, coherent, 218 tok/s (~1.3x MTP2). - vllm/config/vllm.py: drop the dspark->V2 force so DSpark follows normal runner selection (V1 by default for DeepSeek-V4). V2 speculator remains reachable via VLLM_USE_V2_MODEL_RUNNER=1 for A/B. - kernel_warmup.py: make _deepseek_v4_slot_mapping_warmup dual-interface (V1 input_batch/query_start_loc + V2 block_tables/input_buffers). PR #25 had rewritten it V2-only, so it silently no-opped on the V1 runner and reintroduced first-request JIT for ALL DeepSeek-V4 serving (MTP/DFlash/plain). - nvidia/model.py: gate _is_dspark_runtime_layer on method=="dspark". The flag dspark_fused_shared_experts_quant defaults True on every SpeculativeConfig and the MTP block sits at layer_idx==num_hidden_layers, so without this gate the unvalidated fused FP8 shared-experts kernel would engage on production MTP.
|
V2 vs V1 - good catch, i did not run high concurrency tests! Debugged and fixed though, PR coming. |
Summary
This is a stacked DSpark prototype branch on top of Jasl DeepSeek V4 Flash SM120 enablement branch.
Stack base: vllm-project#41834 (
jasl:codex/ds4-sm120-min-enable, currentlya5ebb5f66b).This PR adds:
method="dspark"speculative config and proposer wiring.method="dspark"; obsolete env gates and dead BF16/runtime-layer ablations were removed. Only the draft-forward CUDA graph remains env-gated for now.embed_tokens/lm_headstorage for DSpark to recover KV-cache headroom.Validation
Unit/local:
compileallon touched config/env/proposer/runner/sampler/test filesgit diff --checkPYTHONPATH=/home/ubuntu/llm-src-dss-pr-minimal FLASHINFER_DISABLE_VERSION_CHECK=1 /home/ubuntu/vllm-env-ds4/bin/python -m pytest tests/v1/spec_decode/test_dspark.py -q->14 passedPYTHONPATH=/home/ubuntu/llm-src-dss-pr-minimal FLASHINFER_DISABLE_VERSION_CHECK=1 /home/ubuntu/vllm-env-ds4/bin/python -m pytest tests/v1/sample/test_rejection_sampler.py::test_perfect_match tests/v1/sample/test_rejection_sampler.py::test_early_mismatch tests/v1/sample/test_rejection_sampler.py::test_multiple_sequences -q->3 passedLive on 2x RTX PRO 6000 Blackwell, TP=2, DSpark hybrid checkpoint:
temperature=1.0, server--max-num-seqs 10: avg305.0 tok/s, median308.2 tok/s, all runs full 2048 tokens