From 83966581e36beca5c006588435375d9aea72f56a Mon Sep 17 00:00:00 2001 From: wangcc57 Date: Sun, 23 Aug 2026 15:30:21 +0800 Subject: [PATCH 1/3] speculative: keep DFlash draft positions contiguous across mtmd Keep DFlash draft positions in the independent draft KV context's consecutive position space across multimodal mtmd chunks. --- common/speculative.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/common/speculative.cpp b/common/speculative.cpp index 01c7ee41b87..b79c920d099 100644 --- a/common/speculative.cpp +++ b/common/speculative.cpp @@ -1096,7 +1096,17 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { const int32_t n_ubatch = (int32_t) llama_n_ubatch(ctx_dft); - // Flatten token-wise encoder work into shared chunks while preserving each row's position and sequence. + // The target context may advance over a vision chunk using positions that the + // independent DFlash context cannot reproduce exactly. Keep the draft in its + // own consecutive position space so a later decode always satisfies the + // one-axis RoPE invariant (Y = X + 1). + auto * mem_dft = llama_get_memory(ctx_dft); + std::vector dnext(n_seq, 0); + for (llama_seq_id seq_id = 0; seq_id < (llama_seq_id) n_seq; ++seq_id) { + dnext[seq_id] = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; + } + +// Flatten token-wise encoder work into shared chunks while preserving each row's position and sequence. for (int32_t offset = 0; offset < n_tokens; offset += n_ubatch) { const int32_t n_chunk = std::min(n_ubatch, n_tokens - offset); features_buf.resize((size_t) n_chunk * n_embd_enc); @@ -1139,7 +1149,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { GGML_ASSERT(batch_in.n_seq_id[j] == 1); const llama_seq_id seq_id = batch_in.seq_id[j][0]; GGML_ASSERT(seq_id >= 0 && seq_id < (llama_seq_id) n_seq); - batch_inject.pos[i] = batch_in.pos[j]; + batch_inject.pos[i] = dnext[seq_id]++; batch_inject.n_seq_id[i] = 1; batch_inject.seq_id[i][0] = seq_id; batch_inject.logits[i] = false; @@ -1163,7 +1173,8 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { common_batch_clear(batch); - // build one batch holding every drafting sequence's noise block into a single decode) + auto * mem_dft = llama_get_memory(ctx_dft); +// build one batch holding every drafting sequence's noise block into a single decode) // record where each block starts and its size std::vector i_block_beg(n_seq, -1); std::vector n_block (n_seq, 0); @@ -1176,7 +1187,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { common_sampler_reset(smpls[seq_id].get()); - const int32_t n = (int32_t) dp.n_past; + const int32_t n = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; const int32_t n_draft = params.n_max; From fbe93ca60ebf189deb4f7a2ac173ca893e31d8e7 Mon Sep 17 00:00:00 2001 From: wangcc57 Date: Sun, 23 Aug 2026 15:37:43 +0800 Subject: [PATCH 2/3] style: format DFlash mtmd position fix Normalize indentation in the DFlash2 mtmd position fix. --- common/speculative.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/speculative.cpp b/common/speculative.cpp index b79c920d099..16b067b83de 100644 --- a/common/speculative.cpp +++ b/common/speculative.cpp @@ -1096,7 +1096,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { const int32_t n_ubatch = (int32_t) llama_n_ubatch(ctx_dft); - // The target context may advance over a vision chunk using positions that the + // The target context may advance over a vision chunk using positions that the // independent DFlash context cannot reproduce exactly. Keep the draft in its // own consecutive position space so a later decode always satisfies the // one-axis RoPE invariant (Y = X + 1). @@ -1106,7 +1106,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { dnext[seq_id] = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; } -// Flatten token-wise encoder work into shared chunks while preserving each row's position and sequence. + // Flatten token-wise encoder work into shared chunks while preserving each row's position and sequence. for (int32_t offset = 0; offset < n_tokens; offset += n_ubatch) { const int32_t n_chunk = std::min(n_ubatch, n_tokens - offset); features_buf.resize((size_t) n_chunk * n_embd_enc); @@ -1149,7 +1149,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { GGML_ASSERT(batch_in.n_seq_id[j] == 1); const llama_seq_id seq_id = batch_in.seq_id[j][0]; GGML_ASSERT(seq_id >= 0 && seq_id < (llama_seq_id) n_seq); - batch_inject.pos[i] = dnext[seq_id]++; + batch_inject.pos[i] = dnext[seq_id]++; batch_inject.n_seq_id[i] = 1; batch_inject.seq_id[i][0] = seq_id; batch_inject.logits[i] = false; @@ -1173,8 +1173,8 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { common_batch_clear(batch); - auto * mem_dft = llama_get_memory(ctx_dft); -// build one batch holding every drafting sequence's noise block into a single decode) + auto * mem_dft = llama_get_memory(ctx_dft); + // build one batch holding every drafting sequence's noise block into a single decode) // record where each block starts and its size std::vector i_block_beg(n_seq, -1); std::vector n_block (n_seq, 0); @@ -1187,7 +1187,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { common_sampler_reset(smpls[seq_id].get()); - const int32_t n = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; + const int32_t n = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; const int32_t n_draft = params.n_max; From a789917337f8a03bd0b7523238ab54bd664014ff Mon Sep 17 00:00:00 2001 From: wangcc57 Date: Sun, 23 Aug 2026 15:41:21 +0800 Subject: [PATCH 3/3] Fix formatting in speculative.cpp Align the draft position declaration with the surrounding code. --- common/speculative.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/speculative.cpp b/common/speculative.cpp index 16b067b83de..bd34c27e545 100644 --- a/common/speculative.cpp +++ b/common/speculative.cpp @@ -1187,7 +1187,7 @@ struct common_speculative_impl_draft_dflash : public common_speculative_impl { common_sampler_reset(smpls[seq_id].get()); - const int32_t n = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; + const int32_t n = llama_memory_seq_pos_max(mem_dft, seq_id) + 1; const int32_t n_draft = params.n_max;