Skip to content

EXL3 Flash Next: CUDA graphs and the device planner (7/8) - #1445

Open
BlivionIaG wants to merge 260 commits into
ashhart:mainfrom
BlivionIaG:pr/exl3-s5-graphs
Open

BlivionIaG wants to merge 260 commits into
ashhart:mainfrom
BlivionIaG:pr/exl3-s5-graphs

Conversation

@BlivionIaG

@BlivionIaG BlivionIaG commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Current head: fb4158a917. Main 90b4fae62d, bafe3e07cb, 948e748584, d001c28f29 and release 09a9eb3317 and the #1444 TP=2 paging fix were added after the checks and device measurements below; those device measurements were not repeated on this head. CI is running on this head.

What this changes

EXL3 decode graphs over shared attention, plus the device planner. UNIFORM_LINES=0 means off. The new modes are opt-in (TF_FLASHNEXT_EXL3_GRAPH=eager|1); the default is the host planner.

Checks before the release merge

  • Head 9ed74b507c. The device results below ran on 01dcbf4a8757; this head differs from it by the merges of main at 0591c4e85d, c34ff562ca, a3aecd8d0f and 484437b6ac and f8dacd777f, and the pin fixture gradient-serving.tsv. The device cells were not repeated on this head.
  • python3 tools/pr_check.py --base <main> --pr 1445: exit 0, 0 errors, 0 warnings; lean 339 vs 341 on main, 0 new. zig fmt --check zig: clean.
  • Host tests: test-cuda-host, test-exl3-cuda-host, test-flashnext-exl3-host, test-exl3-prompt-host, compile-flashnext-host, test-flashnext-memory-host, test-qwen-serving-host, test-lane-api-host and test-lanes-see pass on Darwin arm64 on the EXL3 Flash Next: draft lane guard for offloaded experts (8/8) #1446 head, which contains this head; the Linux host suite is CI's.
  • Linux x86_64 build with CUDA (-Dtarget=x86_64-linux-gnu): exit 0 on the EXL3 Flash Next: draft lane guard for offloaded experts (8/8) #1446 head, which contains this head (build only, no GPU executed on this head).
  • CI: see the checks on this PR.

Device results on 01dcbf4a8757

Two 16 GB sm_120 GPUs, Linux x86_64, checkpoint above. One run per cell unless stated.

Cell Result
Planner cell device plan equals host plan
eq-tp1, eq-tp1-lanes off, device-plan and graph rounds are bit-equal; verify windows; two streams
1445-hash-tp1, five servers (GRAPH=0, eager, 1, 1 with ASYNC=1, 1 with shared attention) greedy and seeded token hashes equal in all five (4081 s; passed on a rerun with a larger cap)
Aggregate tok/s, GRAPH=0 against eager / 1, one stream (greedy and temperature 1.0, code and chat) 12.5 to 15.9 against 2.5 to 5.5: the new modes are not faster on this offloaded TP=1 setup
The same, four streams within about 5% of GRAPH=0 in every mode (one run per leg; the graph legs include their captures; no steady-state alternation was run)
1445-eq-tp2 (TP=2, both ranks) pass: device-plan and graph logits bit-equal to the host cut in 48/48 rounds for three prompts, two streams bit-equal in 32/32 rounds, injected capture failure falls back with bits unchanged; the test's own per-token time is 9 to 15% lower with dplan and between 14% lower and 17% higher with graph than the host planner (one run; not a benchmark)
1445-attn-lanes-kernel the harness marks it fail because its pattern wants control RED as planted as the whole line and the log prints control RED as planted (crossed lane table); the log has 8 passing lane shapes (1 to 32 lanes) and no FAIL line; the gate is unchanged
kernel-contract exl3 flashnext (filtered) 102/102 kernels pass gates 1-4, 43/43 controls red, 138 limit problems: one more than the earlier PRs, from main's pending launch records for tf_exl3_prompt_* (exl3_prompt_pending.zig), which this PR does not touch

Not run or open

  • The ABBA graph timing alternation; this PR makes no speed claim for the graph modes.
  • A TP=2 server hash and speed cell (the TP=2 evidence is the eq-tp2 unit test above).
  • Main against this head (main refuses this checkpoint).

Receipt

  • Boxes it reaches: decode graphs and the device planner.
  • New switch: none in this update.
  • Environment: Zig 0.17.0. Host checks on Darwin arm64. Device runs on Linux x86_64 with two 16 GB sm_120 GPUs. Checkpoint turboderp/Qwen3.8-Flash-Next-exl3 at 69e33439ae950f17bcbe95c98f117d80f759ab6d.
  • Kernel contract: Kernels changed: flashnext_exl3_dplan.cu (new), exl3_experts.cu. The filtered contract above covers them.
  • Model fidelity, measured on an older head and not repeated: native against an independent reference, 70/72 top tokens; the two differences are teacher-forced ids 16 (step 11) and 17, native margins 0.25 and 0.5 against reference 0.125 and 0.25. No tie waiver and no perfect-equivalence claim.
  • Licence of new weights or drafter: n/a (Qwen Community License 1.0 on the checkpoint; no weights distributed, no new drafter).

Review requests implemented in source

  • UNIFORM_LINES=0 is off, with docs, changelog and test.
  • DSPINE, host-planning learned-pocket and dense_cut exclusions, and saved tail/nrow are retained.

Checklist

  • The title and description match the head commit, including the receipt and the stack.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency. Host tests pass in CI and the device cells above pass; I did not run the new tests against the parent to show they fail before the change.
  • Comments and docstrings are one line. No measurements or history in the source. Lean check (one-line comments within 120 columns): 0 new problems. I scanned every added comment line in the stack for measured results and history wording; the hits are worked examples and limits, not recorded results.
  • No personal data, machine names, internal hosts or local paths in the diff or its commits. No AI attribution lines. Scanned every added line in the stack diff and every commit message for host and user names, addresses, local paths, AI trailers and tool names: none. No binary files are added. Receipts are not in the repository.
  • Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off. No direct demonstration. The concurrent and drafted device cells run through the lane rounds.
  • Drafted output equals "draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. Concurrent token equality across the five modes passes; drafted equals "draft": false and resumed equals fresh were not run for this PR on its own.
  • No precision traded for speed. If the bits change, the description says which sums change and why. No arithmetic change; off, device-plan and graph rounds are bit-equal on device.
  • Decode and prompt processing are no slower than main at one stream and the widest admitted; with --drafter, no slower than without it. The default is unchanged. The opt-in modes are slower at one stream on this setup (cells above).

@ashhart

ashhart commented Oct 27, 2026

Copy link
Copy Markdown
Owner

CUDA graphs for Flash Next are welcome. Acceptance staying in the core lane engine, with the device code only proposing
and planning, is the right split. Before this can land:

  1. Please add the eager-vs-graph receipt: same binary, graphs on and off, alternating runs. That was the condition on
    [Draft] EXL3 Flash Next on CUDA: TP=2, BF16 paging, cache reuse, graphs #1113.
  2. Please fix capture-failure handling. One failed capture sets gcache.broken
    (exl3/graph/cuda_exl3_graph_cache.zig:71, set at cuda_exl3_graph_hooks.zig:94 and :141), and every later
    round then fails with GraphCaptureFailed (:64, :111) for the life of the process. The round should run
    eagerly instead. On two ranks, the failure aborts the communicator.
  3. Please cut the 20 new graph and planner switches down to the few a user needs.
  4. Please move the engine facts out of process globals (offloaded_layers, dplan.active, tiles_on, state.deep)
    into the engine.
  5. Please give the six planner kernels runner entries.

This PR depends on #1441 to #1444, so it inherits their blockers.

@BlivionIaG
BlivionIaG force-pushed the pr/exl3-s5-graphs branch 4 times, most recently from f13fa73 to 556eb09 Compare October 27, 2026 17:56
@BlivionIaG BlivionIaG changed the title EXL3 Flash Next: CUDA graphs and the device planner (5/7) EXL3 Flash Next: CUDA graphs and the device planner (7/8) Oct 27, 2026
@BlivionIaG
BlivionIaG force-pushed the pr/exl3-s5-graphs branch 19 times, most recently from 3a3714f to 5ca7783 Compare October 29, 2026 19:22
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
#	zig/src/families/flashnext/cuda_lanes_load.zig
#	zig/tests/fixtures/gradient-serving.tsv
# Conflicts:
#	zig/tests/fixtures/gradient-serving.tsv
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md
# Conflicts:
#	CHANGELOG.md

This branch has not been deployed

No deployments
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