Summary
LLM_ARCH_QWEN4EXP is excluded from llm_arch_supports_rs_rollback(), so n_rs_seq clamps to 0 for Qwen3.8-Flash-Next and hybrid-recurrent batched rollback never engages. Force-enabling it shows why: test-recurrent-state-rollback fails test_multi_seq_split_replay with a logits max diff of 9.25 — single-seq checkpoint restore passes, multi-seq split replay corrupts state. If the exclusion is deliberate, this issue documents the concrete gap (and asks what state is missing snapshot coverage); if it's an oversight, the repro below should make it easy to chase.
Repro (~2 min on top of loading the model)
On master @ cc231cb0d:
- Add the arch to the rollback allowlist:
--- a/src/llama-arch.cpp
+++ b/src/llama-arch.cpp
@@ bool llm_arch_supports_rs_rollback(const llm_arch & arch) {
case LLM_ARCH_QWEN35:
case LLM_ARCH_QWEN35MOE:
+ case LLM_ARCH_QWEN4EXP:
case LLM_ARCH_DEEPSEEK4:
- Run the existing test against a Qwen3.8-Flash-Next GGUF (tested with an IQ4_XS quant, CPU backend):
CUDA_VISIBLE_DEVICES="" ./bin/test-recurrent-state-rollback \
--model Qwen3.8-Flash-Next-IQ4_XS-00001-of-00003.gguf -ngl 0
- Output:
main : recurrent rollback checkpoint restored successfully
test_multi_seq_split_replay : multi-seq split replay logits mismatch (max diff 9.25491, first at seq 0 pos 16)
A diff of 9.25 in the logits is state corruption, not numerical noise.
Suspected cause
qwen4exp carries extra per-row recurrent state beyond the gated-delta-net state that the snapshot planes cover for the allowlisted archs:
- the PLE conv history (
ple_layer_ids: [2] — the PLE module sits on a layer that is also a delta-net layer, so both keep conv state in the same recurrent row), and
- possibly QSA indexer state.
If those aren't widened into the (1 + n_rs_seq) snapshot groups, an equal-split replay would restore the GDN state but replay over stale conv/indexer state — consistent with the mismatch appearing early (pos 16) on seq 0.
Why it matters
On hybrid-recurrent archs, server spec decode with --parallel N currently pays a large serialization cost without rollback snapshots. Measured on a GB10 (Grace-Blackwell, 128 GB unified, CUDA sm_121) with Qwen3.8-Flash-Next IQ4_XS + --spec-type ngram-map-k4v --parallel 3: three concurrent streams reach only ~50 tok/s aggregate on rewrite-style workloads vs ~66–70 with speculation disabled — speculation inverts under concurrency. Batched rollback is the structural fix, and it's blocked on this arch by the missing snapshot coverage.
Secondary observation while in this code: common_params_speculative::need_n_rs_seq() only arms n_rs_seq for the draft-model spec types (MTP/EAGLE3/DFLASH/DSPARK). Is there a reason the ngram-* types are excluded? They hit the same partial-acceptance rollback path.
Offer
Happy to test patches on GB10 hardware — the repro takes ~2 minutes here and I can also run before/after server throughput numbers (--parallel 3, ngram spec) on the same box.
Summary
LLM_ARCH_QWEN4EXPis excluded fromllm_arch_supports_rs_rollback(), son_rs_seqclamps to 0 for Qwen3.8-Flash-Next and hybrid-recurrent batched rollback never engages. Force-enabling it shows why:test-recurrent-state-rollbackfailstest_multi_seq_split_replaywith a logits max diff of 9.25 — single-seq checkpoint restore passes, multi-seq split replay corrupts state. If the exclusion is deliberate, this issue documents the concrete gap (and asks what state is missing snapshot coverage); if it's an oversight, the repro below should make it easy to chase.Repro (~2 min on top of loading the model)
On
master@cc231cb0d:A diff of 9.25 in the logits is state corruption, not numerical noise.
Suspected cause
qwen4exp carries extra per-row recurrent state beyond the gated-delta-net state that the snapshot planes cover for the allowlisted archs:
ple_layer_ids: [2]— the PLE module sits on a layer that is also a delta-net layer, so both keep conv state in the same recurrent row), andIf those aren't widened into the
(1 + n_rs_seq)snapshot groups, an equal-split replay would restore the GDN state but replay over stale conv/indexer state — consistent with the mismatch appearing early (pos 16) on seq 0.Why it matters
On hybrid-recurrent archs, server spec decode with
--parallel Ncurrently pays a large serialization cost without rollback snapshots. Measured on a GB10 (Grace-Blackwell, 128 GB unified, CUDA sm_121) with Qwen3.8-Flash-Next IQ4_XS +--spec-type ngram-map-k4v --parallel 3: three concurrent streams reach only ~50 tok/s aggregate on rewrite-style workloads vs ~66–70 with speculation disabled — speculation inverts under concurrency. Batched rollback is the structural fix, and it's blocked on this arch by the missing snapshot coverage.Secondary observation while in this code:
common_params_speculative::need_n_rs_seq()only armsn_rs_seqfor the draft-model spec types (MTP/EAGLE3/DFLASH/DSPARK). Is there a reason thengram-*types are excluded? They hit the same partial-acceptance rollback path.Offer
Happy to test patches on GB10 hardware — the repro takes ~2 minutes here and I can also run before/after server throughput numbers (
--parallel 3, ngram spec) on the same box.