Repository navigation
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR #3: deepseek4: stabilize MTP decode path
Description
Follow-up to the MTP sidecar work originally in nisparks's DSv4 MTP integration (
4a310073csnapshot). That snapshot ran model load + sidecar attach + speculative context init successfully but crashed on the first inference request with three independent bugs in the MTP-enabled decode path. This PR fixes all three.Bug 1: XOR assert in
llama_context::decode()is too strict for MTP sidecar batchesThe existing precondition
GGML_ASSERT((!batch_inp.token && batch_inp.embd) || (batch_inp.token && !batch_inp.embd))requires a batch to provide only tokens or only embeddings, never both. DeepSeek V4 Flash's MTP sidecar graph legitimately needs both — conditioning tokens at one position plus the hidden state row from the target's last decode. The recursive
llama_decode(ctx_mtp, ...)call inhandle_mtp_for_ubatch()hits this assert on the first decode.Fix: relax the XOR to permit
token && embdonly when the loaded arch isLLM_ARCH_DEEPSEEK4_MTP_SUPPORT. Other models retain the original constraint.Bug 2:
common_speculative_state_mtpwritesbatch.token[0]without allocating itllama_batch_init(..., embd=n_embd, ...)allocates only the embedding buffer; the speculative state then writes tobatch.token[0], dereferencing a NULL or unallocated pointer.Fix: explicitly allocate
batch.tokenalongsidebatch.embd.Bug 3: hidden-row offset reads use wrong tensor stride
handle_mtp_for_ubatch()and the MTP-draft hidden-copy path computed row offsets asrow * n_embd * sizeof(float), which assumes a tightly packed F32 tensor with striden_embd. Realggml_tensorstrides come fromtensor->nb[1]; with non-default layouts the wrong offset reads out-of-bounds or stale data. After partial accept + checkpoint restore,last_n_accepted=1can also exceed the target graph's actual visible row count.Fix: read row offsets via
tensor->nb[1]; clamplast_n_acceptedto the actual graph row count; add type/shape/bounds guards that stop the current draft pass rather than crash the server if the source tensor is malformed.Reproduction (before fix)
After fix
Same command; first request completes with valid output. Speculative decoding emits draft tokens and target-side verification finishes cleanly. Probes 7/10 pass (same set as the no-MTP same build — the 3 failing probes are pre-existing nisparks-tree issues unrelated to this fix). MTP-enabled decode now reaches 11-12 tok/s in the naïve configuration — see
fix/deepseek4-mtp-adaptive-fallback(separate PR) for the perf work needed to keep MTP from regressing throughput vs no-MTP.Hardware tested
Why upstream
This fixes an actual crash in any DSv4 MTP-enabled decode path. The XOR relaxation is arch-gated to
LLM_ARCH_DEEPSEEK4_MTP_SUPPORTso it's a no-op for other models. The batch.token allocation and tensor-stride fixes are general correctness improvements on the speculative state and hidden-state read paths — also safe to land independently.The relaxation precedent is important: future hybrid-architecture sidecars (any model that needs simultaneous conditioning tokens + hidden embeddings for a recursive decode) will need the same hook.
Related
4a310073c "wip: mtp patch snapshot"— the WIP that this PR fixesfix/deepseek4-mtp-adaptive-fallback(perf work; this PR is correctness only)