Repository navigation
Conversation
… head pass A stream with a temperature above zero was left out of the shared round's batched MTP head pass and drafted alone, one head forward per draft token. Now it joins the pass: each step, after the shared best-column download, a sampled lane's score row is downloaded and its draft drawn on the host under the lane's own keyed rule at the drafted position, the draw its lone pick makes, so drafts, probabilities, the confidence stop and replies are unchanged. Greedy lanes keep their best column. TF_FLASHNEXT_SAMPLED_HEADS=0 restores the previous behaviour; TF_FLASHNEXT_BATCH_HEADS=0 still drafts every stream alone. The parity checker now also runs sampled and mixed shapes, each lane under its own seed and position, at confidence 0 and 0.5.
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.
What this changes
A shared round's Flash Next streams with a temperature above zero now draft in the batched MTP head pass on CUDA instead of one at a time: each step, after the shared best-column download, a sampled lane's score row is downloaded and its draft drawn on the host under its own keyed rule at the drafted position, the draw its lone
pickmakes, so drafts, probabilities, the confidence stop and replies are unchanged. Greedy lanes keep their best column.TF_FLASHNEXT_SAMPLED_HEADS=0restores the previous behaviour;TF_FLASHNEXT_BATCH_HEADS=0still drafts every stream alone. The parity checker gains sampled and mixed shapes with per-lane seeds and positions. Fixes #1608.Receipt
Full receipt in
docs/receipts/flashnext-cuda-sampled-heads/(README, the fourbench_concurrentreports, the parity output,commit.txt).03d08f1e) plus this change (measured there; the branch is rebased ontomainatc9c3aa03, which does not touch these files, with the source byte-identical), built from source with Zig 0.17.0 and nvcc 13.3 innvcr.io/nvidia/pytorch:26.07-py3(PyTorch unused by the native server); one DGX Spark (GB10, sm_121, 128 GB), kernel driver 580.178.04, CUDA 13.3 forward-compatibility driver 610.43.02;nvidia/Qwen3.8-Flash-Next-FP4-Localatb9ce18a6887e18c089fdea8509a33e63429a3300;--context 131072 --parallel 5 --kv-cache bf16 --temperature 1.0 --top-p 0.95 --top-k 20 --thinking.tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false:bench_concurrent.py --alone(every concurrent reply against its lone run), baseline and this PR, two runs each, 64 cellsbench_concurrent.py --serial(every lone run against"draft": false), baseline and this PR, two runs each, 64 cellstf-cuda-test flashnext-mtp-parity: 6 greedy shapes (confidence 0, 2) and 12 sampled and mixed shapes (confidence 0, 0.5)tools/bench_openai.py: measured withbench_concurrent.pyon the same prompts and settings, one binary. Baseline isTF_FLASHNEXT_SAMPLED_HEADS=0, the behaviourmainhas today; this PR is the change (on by default). Two runs each, alternated baseline, this PR, baseline, this PR; each figure is the mean of the two runs (per-run values are in the receipt README). Aggregate tok/s:Time to first token, the median request's
ttft_sin the same runs, mean of the two runs:tools/bench_cache.py --tokens 64 --repeats 2 --streams 2 --require-coldon the 12,001-token fixture prompt (zig/tests/cuda/flashnext/lr7/long12k.ids), a fresh server for each side, both qualified cold (prefill-baseline.json,prefill-this-pr.jsonin the receipt):ttft_s(mean of the two cold requests)ttft_sttft_szig build test-cuda-host(the newdrawPicktest included)tf-cuda-test flashnext-mtp-parityon the GB10zig fmt --checkon the changed filestools/zig/lean_check.pymainatc9c3aa03(428 on both at 1.1.8, when measured); none addedzig build compile-flashnext-mtp-parity-hostkernel-contractChecklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.SUMMARYline is in the receipt. (No kernel changed.)draftMany, which has no sampling input; the planted control fails as before.)Prior art: Metal's shared rounds draw a sampled stream's drafts under its keyed rule since 1.1.7 (#1340, #1343, @gilby);
draftManyfor greedy streams on CUDA is #1155 (@jschmied); MiaAI-Lab's Flash Next recipe for one Spark carries the same idea for CUDA on v1.1.4 as its patch 0007 (TF_FLASHNEXT_SAMPLED_HEADS=1). This is an independent implementation against 1.1.8.Overlap (
atc check1608: free, claimed;git merge-treeagainst every open PR that touches these files): #1446, the last part of the EXL3 Flash Next stack, inserts its deferred-draft check right after the line inbatchedthat this changes, and adds EXL3 early returns besidepickanddraft; the hunks are adjacent, not the same logic, and both apply (keep this skip line, then the EXL3 check). I will rebase onto whichever lands first.CHANGELOG.mdconflicts with every open PR, as usual.A pre-existing observation, untouched here:
headGroup(the batched head's pass) does not passDraft.pgwhereforwardHeaddoes, so batched heads and paged KV (TF_FLASHNEXT_KV_PAGES, off by default) have not met.Authored by JRB AI in a private capacity. This contribution does not represent the views or positions of any organisation.