Skip to content

qwen3_5 cuda: a chat's next turn can resume at the previous turn's history (opt-in) - #2176

Draft
ashhart wants to merge 4 commits into
mainfrom
lead/pr1335
Draft

ashhart wants to merge 4 commits into
mainfrom
lead/pr1335

Conversation

@ashhart

@ashhart ashhart commented Nov 4, 2026

Copy link
Copy Markdown
Owner

This carries @gilby's #1335 forward at their request: their commit with their authorship, rebased onto main, with the opt-in they asked us to add. Part of #1334.

  • Off by default: TF_QWEN_REQUEST_STARTS=1 turns on exact message cuts for eligible Qwen families. Unset, zero, empty or anything else behaves as main does, with a test.
  • Beside shared KV it's refused by name. Exact cuts would need partial-page snapshots, and that's a step of its own.

Host tests pass and lean stays at 425. Not yet run on a GPU: the six-turn tables on a GB10 against main are ours, and it won't land until those are posted.

@ashhart

ashhart commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

/atc exchange 18b05daeca073604fd3bf7e24e29a1372246863a5edc5b4d8f2c29ce5e617eb2

@ashhart

ashhart commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

This now takes the per-family switch from @laidick's #2404 (commit 90e7309ba): requestStep reads the switch the family names (request_starts_switch), so turning on Qwen's TF_QWEN_REQUEST_STARTS sends message starts only to Qwen's two CUDA entry points, a family that names no switch never gets them, and with every switch unset every CUDA family is on main's path. Qwen's switch name, its refusal with TF_QWEN_KV_SHARE and its tests are unchanged; a host test walks all twelve registered CUDA families. When #2404 rebases onto this, its copy of that plumbing can go. This PR still waits on its six-turn tables.

@ashhart

ashhart commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

The six-turn tables are in: one GB10, Qwen3.8-27B MLX 4-bit with the DFlash2 drafter, main's merge base 09e2f7fa6 against this head 90e7309ba. Each arm ran two fixed six-turn chats, a short one (1.5K tokens) and a long one (21.4K tokens), on a warm server, and then each turn again on a cold server.

Replies are equal on every arm and turn. Unset, the switch runs main's path: new-off is level with base everywhere. TF_QWEN_REQUEST_STARTS=1 beside TF_QWEN_KV_SHARE above 0 is refused by name before serving.

First-token time on the warm server, turns 2 to 6:

Chat main this PR, unset this PR, TF_QWEN_REQUEST_STARTS=1
Long (21.4K) 0.93-1.06 s, 20,480 cached 0.93-1.07 s, 20,480 cached 0.17-0.27 s, 21,371 cached
Short (1.5K) 1.16-1.36 s, 0 cached 1.16-1.35 s, 0 cached 0.11-0.22 s, 1,450 cached

Main resumes on the 2,048-row grid, so the short chat never resumes and the long one re-prefills about 900 rows a turn. With the switch on, both resume within a few rows of turn 1's end. Turn 1 costs 0.04 s more on the long chat and 0.17 s on the short one, for the extra cuts. Cold servers are level with main in every arm (16.2-16.4 s and 1.1-1.4 s).

One thing the tables show: cached_tokens stays at turn 1's history end (21,371 and 1,450) for turns 2 to 6. Later turns resume from turn 1's state and prefill the rest, so the remaining prefill grows by about 50 rows a turn rather than staying a few rows. It's still exact and still well ahead of main, but it isn't "the next turn resumes where its history ended" for turn 3 onwards. We'll look at whether a later turn's own cuts should be kept too, as a follow-up. The opt-in itself is ready to land once it's rebased onto main.

gilby and others added 4 commits November 7, 2026 03:51
…s opt-in sends no other family message starts

requestStep reads the switch the family names (request_starts_switch) through
profile.lookup; a family that names none gets no message starts. Qwen's dense
and MoE entry points name TF_QWEN_REQUEST_STARTS, so its name, its refusal
with TF_QWEN_KV_SHARE and its tests are unchanged, and unset is main's path.
The shape follows #2404's (0279d37), without its GLM engine changes, so #2404
can drop its copy. A host test walks the real CUDA registry: Qwen's switch
reaches only Qwen, a second family's switch only that family, unset none.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants