Skip to content

perf(qwen35): improve concurrent AR prefill latency - #622

Draft
Graffioh wants to merge 2 commits into
Luce-Org:mainfrom
Graffioh:codex/ar-prefill-latency
Draft

perf(qwen35): improve concurrent AR prefill latency#622
Graffioh wants to merge 2 commits into
Luce-Org:mainfrom
Graffioh:codex/ar-prefill-latency

Conversation

@Graffioh

@Graffioh Graffioh commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

This PR is based directly on main. Its complete GitHub diff contains only server runtime code, server documentation, and server-side tests. The benchmark tooling and detailed measurement methodology are isolated in #596.

What this changes

  • sizes the Qwen3.6 target-step graph for mixed packed-prefill plus compact-decode schedules, fixing the C16 abort caused by a ninth recurrent segment;
  • permits bounded prefill-only traversals while preserving paused decoder token, KV, and recurrent state exactly;
  • preserves FIFO packed-cohort behavior by default, with wide-cohort round-robin available as an explicit opt-in for future C32+ work;
  • exposes bounded prefill-burst and idle-token budgets with fail-closed parsing;
  • removes the unconditional 15-byte SSE tool-parser delay from ordinary requests with no declared tools, while preserving split reasoning-marker detection and conservative tool/stop handling.

Runtime behavior

The screened default remains DFLASH_PREFILL_FIRST_BURST_STEPS=0. Prefill-first bursts can improve a native prefill tail but delay decode, so they remain opt-in. DFLASH_PREFILL_COHORT_ROUND_ROBIN is also opt-in; the default remains FIFO plus the existing intra-cohort partial-budget cursor.

Dynamic graph sizing retains the old 16,384-node capacity through eight recurrent segments, then adds 2,048 nodes per additional segment. The observed C16 mixed schedule requires 16,741 nodes, so it receives an 18,432-node graph.

Strix Halo validation

The benchmark tooling lives in #596. One-repeat screens ran exclusively on gfx1151 / Radeon 8060S.

  • C16 short: Luce goodput 30.96 versus llama.cpp 22.67 tok/s; max TTFT 23.404 versus 29.561 s.
  • C16 long: Luce goodput 6.08 versus llama.cpp 5.19 tok/s; max TTFT 158.331 versus 180.800 s.
  • Native Luce C16 prefill throughput was broadly flat across context cohorts (about 349-363 tok/s); latency growth primarily followed total prompt work.

The SSE follow-up used the exact same long-C16 selected prompt set (54,148 prompt tokens, 16/16 valid, exactly 64 output tokens/request). Median TTFT moved from 140.464 s to 123.210 s (-12.3%); max TTFT was essentially unchanged at 157.854 s. This is a one-repeat screen, so the direct emitter regression test and the reduced visible-minus-native delay are the stronger causal evidence.

Validation

  • scheduler plan: 139 checks passed;
  • sequence-engine contract: 13 checks passed;
  • graph-sizing regression passed;
  • complete server unit suite: 362/362 passed;
  • final HIP dflash_server built and linked for gfx1151;
  • production long-C16 smoke completed 16/16 without graph or scheduler faults;
  • rewritten server tree is byte-identical to the previously tested and benchmarked server tree;
  • complete PR diff against main contains only 13 server/ files.

Review notes

  • omitted decoder rows do not append or commit KV and do not advance recurrent state;
  • a bounded prefill burst always yields to the complete live decoder cohort after N pauses;
  • idle epochs reset burst and cohort state;
  • ordinary no-tool content streams immediately, while partial <think> / </think> fragments remain boundary-safe.

@Graffioh

Copy link
Copy Markdown
Contributor Author

Emitter latency follow-up (commit abae692)

Upstream behavior checked before implementation:

  • vLLM buffers only request stop-string suffixes in its incremental detokenizer; reasoning/tool parsing is handled separately.
  • SGLang emits clean incremental text immediately and mainly delays incomplete UTF-8.

Luce had imposed its 15-byte tool-syntax holdback even for ordinary requests with no declared tools. This follow-up makes ordinary content immediate while retaining split reasoning-marker detection; requests with tools or custom stops retain the existing conservative buffering.

Validation:

  • server unit suite: 362/362 passed, including immediate short content and a split opener regression
  • production gfx1151 HIP server linked
  • exact long-C16 Strix screen: same selected prompt hash, 54,148 prompt tokens, 16/16 valid, 64 output tokens/request
  • median TTFT: 140.464 s -> 123.210 s (-17.254 s, -12.3%)
  • max TTFT: 158.331 s -> 157.854 s (essentially flat)
  • median visible-minus-native-prefill delay: 28.339 s -> 22.367 s

This is a one-repeat screen. Prefill order varied between runs, so the direct unit regression and visible-minus-native gap are the cleaner causal evidence. Six C16 requests became visible about 0.33 s after native prefill; ten still waited about one 22.37 s traversal because their first sampled token produced no visible text. That remaining delay is a separate scheduler/detokenizer follow-up.

@Graffioh
Graffioh force-pushed the codex/ar-prefill-latency branch from abae692 to 4742333 Compare August 18, 2026 10:40
@Graffioh
Graffioh force-pushed the codex/ar-prefill-latency branch from 4742333 to 812eabc Compare August 18, 2026 10:42
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.

1 participant