Repository navigation
glm cuda: DFlash2 reads a solo pass's taps whole, so TF_GLM_CHUNK_SOLO=4096 serves beside --drafter - #2219
Merged
Conversation
Bizuayeu
marked this pull request as ready for review
November 5, 2026 03:44
Owner
|
Thanks @Bizuayeu, and @MiaAI-Lab for the patch this follows. Drafted equal to plain and concurrent equal to alone, with the cold first token 6.1% and 7.0% sooner at 32K and 64K, makes this an easy one. It's in the queue; we'll add the changelog line. |
ashhart
added a commit
to Bizuayeu/TensorFold
that referenced
this pull request
Nov 5, 2026
ashhart
force-pushed
the
pr/glm-solo-dflash2
branch
from
November 5, 2026 07:57
7c2f08f to
ab57445
Compare
ashhart
added a commit
to Bizuayeu/TensorFold
that referenced
this pull request
Nov 5, 2026
ashhart
force-pushed
the
pr/glm-solo-dflash2
branch
from
November 5, 2026 08:57
ab57445 to
0273843
Compare
…O=4096 serves beside --drafter A solo pass takes 4,096 rows, and --drafter was refused beside it: DFlash2's tap buffer and promptRun's bound held one 2,048-row chunk. The drafter keeps only the prompt's last 2,048 rows (promptRun's window), so its ingest buffers stay as they are; only taps_prefill, which the forward writes for every row of a pass, now takes the engine's prompt buffers' rows (tapRows: 4,096 with solo, 2,048 without, so 80 MiB more on each rank with solo and nothing without). promptRun checks a pass against that buffer. The refusal and its test go. The bound was found by Mia's AI Lab's patch 0095 (MiaAI-Lab/GLM-5.3-Flash-DGX-Sparks-1104), for its 4,096-row grid.
ashhart
force-pushed
the
pr/glm-solo-dflash2
branch
from
November 5, 2026 10:54
0273843 to
71a6865
Compare
Owner
|
Thank you @Bizuayeu. This is merged into main with your commits under your own name, so you're listed as a TensorFold contributor. It ships in the next release, credited to you in the changelog and the release notes. |
8 tasks done
Owner
|
Thanks @Bizuayeu and @MiaAI-Lab! This is in TensorFold 1.2.3, out now: https://github.com/ashhart/TensorFold/releases/tag/v1.2.3 |
8 of 9 tasks
This was referenced Nov 5, 2026
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.
On two GB10s at TP=2 with
--drafter(DFlash2),TF_GLM_CHUNK_SOLO=4096now serves instead of being refused at load.Against main with the same drafter, a cold prompt's first token comes 6.1% sooner at 32K tokens and 7.0% sooner at 64K
(0.7 and 1.7% at 2K and 8K), with the same tokens and the same decode speed:
--drafter--drafter,TF_GLM_CHUNK_SOLO=4096ttft_s, 2K / 8K / 32K / 64K tokens (bench_cache.py --require-cold)fibonacci-raw/gpu-chat-no-think, sampled (bench_openai.py)bench_concurrent.py --prompts tools/bench_prompts.json)bench_cache.pyread upstream'stools/*.pyatc085aab04, tokenized by the server's/tokenizeand cut intodisjoint 2K, 8K, 32K and 64K-token slices;
bench_openai.pyandbench_concurrent.pyran 256 tokens, three reps,medians.
What this changes
TF_GLM_CHUNK_SOLO=4096lets a lone prompt pass take 4,096 rows, and #1842 refused it beside--drafter, becauseDFlash2's prompt tap buffer and
promptRun's bound held one 2,048-row chunk. The drafter keeps only the prompt's last2,048 rows, so its ingest buffers can stay as they are: only
taps_prefill, which the forward writes for every row of apass, now takes the engine's prompt buffer rows (
tapRows: 4,096 with solo, 2,048 without), andpromptRunchecks apass against that buffer. The refusal and its test go. Solo costs 80 MiB more on each rank; without it nothing changes.
This follows @MiaAI-Lab's patch 0095 in MiaAI-Lab/GLM-5.3-Flash-DGX-Sparks-1104,
which found the bound for its 4,096-row grid.
c085aab04, where the receipt ran; it merges cleanly with main at8abb30f6f), one commit.atc overlap --json(2026-11-05 03:09 UTC, basefb0895099;complete: false, as atc could not read every open pullrequest's files): of the eight open pull requests that share files with this one, seven merge cleanly and GLM CUDA: opt-in context copies priced by the lane host #2146
conflicts in
glm/cuda_native.zig, where it addsBadCopyPolicy's line beside theGlmSoloWithDrafterline thisremoves: whichever lands second keeps
BadCopyPolicy's and dropsGlmSoloWithDrafter's.Checks on this head
7c2f08fcfzig build test-glm-prompts-host8/8 (7/7 on the base; the new test is in thisstep),
test-cuda-host4,793 of 4,816 (23 skipped),test2,252 of 2,288 (36 skipped; Zig's cache kept the stepsanother run had built from the same inputs),
test-glm-prompt-settings-host6/6,test-glm-tp3-host8/8,test-glm-prompt-arena-host1/1,test-glm-startup-host,test-glm-pages-host,test-golden,compile-cuda-tests(also aarch64),compile-config-server: no failures.zig fmt --check build.zig zigandgit diff --check: clean.release-paths).
181 GiB does not fit one GB10).
Receipt
c085aab04(main) and this head, each built with Zig 0.17.0 and nvcc 13.3.73 for sm_121; two GB10s(128 GB unified memory each, Ubuntu 24.04.5, kernel 7.0.0-1019-nvidia, driver 580.178.04) at TP=2 over RoCE;
Bizuayeu/GLM-5.3-Flash-XSFP4at88736f91; drafterincoai/GLM-5.3-Flash-DFlash2atbf582e4e;--context 524288 --parallel 4(DFlash2 leaves 1M's four streams no room),TF_KV_PAGESunset (pages),TF_GLM_KV_SHARE=16,TENSORFOLD_PREFILL_SHARE=0.7, and for the table--prompt-cache-gib 0. WithTF_GLM_KV_SHAREthe kept prompts stayon the pool's pages even so: each prompt's first request was cold (a fresh server, disjoint prompts), and
bench_cache.py's repeats at 8K to 64K resumed from it.--drafter(DFlash2), on rank 0 and the following ranks; without--drafternothing changes, and with it but without solo the drafter's buffers are main's. Run: TP=2 on two GB10s(sm_121), main and this head. Not run: TP=3, other SMs.
bench_concurrent.py --tokens 256 --reps 3 --temperatures 0 --levels 1,4 --alone --serialon this headwith solo: every reply at one and four streams equalled its request alone (code and chat, 3 and 12 of 3 and 12), and
the alone runs equalled
"draft": false.bench_cache.pyat 2K to 64K: on main and on this head, each prompt'srepeats and concurrent requests gave its first request's tokens, resuming from it at 8K to 64K (6,144 to 63,488
tokens cached; a 2K prompt keeps no shorter state), and each prompt's tokens were the same on main and on this head;
bench_openai.py's replies were the same on both,sampled and greedy. With the prompt cache at its default, prompts of about 7K, 15K and 30K tokens and the decode
check's count prompt (256 greedy tokens) gave the same
token_sha256drafted and with"draft": false, with solo andwithout; a short request sent 3 s into a 30K-token prompt gave the same tokens as alone, and the long prompt's second
run, resumed from its kept state (28,672 tokens cached), equalled its first.
bench_openai.py --tokens 256 --reps 3 --temperatures 1.0,0).ttft_sfrombench_cache.py --require-cold).4.0).
Raw results
bench_cache.py --require-cold(and its repeats and concurrent requests), main =mu, this head =ou:bench_openai.py --tokens 256 --reps 3 --temperatures 1.0,0:bench_concurrent.py --tokens 256 --reps 3 --temperatures 0 --levels 1,4 --alone --serial, this head:bench_concurrent.py --prompts tools/bench_prompts.json --tokens 256 --reps 3 --temperatures 1.0,0 --levels 1,4:Checklist
glm_prompt_host.zigon the base fails to build:promptRuntakes no bound there anddflashhas notapRows; ithas no dependency to skip on).
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo (Exactnessabove).
changes: a buffer's rows and a bound).
--drafter,no slower than without it, greedy and sampled (the table above at one and four streams, sampled and greedy; without
--drafterthis head runs main's code).