Repository navigation
Conversation
…s sized to match A 2,048-row chunk leaves the prompt step's per-chunk costs a larger share of a cold prompt. 4,096 rows still fits four 500K windows at TP=3, and at TP=2 without a drafter, and the output does not change. The drafter's prompt taps and context buffers took MAX_CTX = 2048 rows, which a wider chunk overran at startup with a drafter loaded; MAX_CTX now follows prefill_rows. Fixes ashhart#1570
|
Thank you for this, and for the thorough receipts. The cold-prompt gain is clear, and it's good to see the completions match main with and without the drafter. Before we can land it, there are a few things to sort out.
Once those are in, we'll run the device cells and land it. |
@gilby I had the same chunk size under test here, so these are yours to use if they save you a run. At 4,096 rows a warm turn takes 10 to 52% longer, and a decoding stream's longest wait goes from 1.73 to 3.07 s at TP=2 and from 1.45 to 2.52 s at TP=3. The bits match at both sizes. So these receipts support the opt-in setting, not the default. Setup. Warm turns. A chat with a fresh nonce, its history sent cold, then four turns that each add the tokens shown, 32 tokens a reply. Each cell is the mean first token and, in brackets, the mean rows re-filled, over 16 turns at TP=2 and 8 at TP=3:
Every turn resumed at the deepest point of its own grid ( Correction: I first set that against the −6 to −8% from 8K to 128K at Three decodes beside a 32K prompt. Three drafts-off decodes of up to 1,200 tokens, and 4 s later one cold 32K prompt, over 300 and 162 gaps at TP=2 and 192 and 96 at TP=3:
TP=2 fit and first tokens, at TP=3 at a 1M window holds one whole window fewer, with no drafter loaded. The pool goes 6,215 → 5,948 pages and a 1M window takes 2,048, so the streams a 1M window each would serve ( Exactness at both sizes. Prompts of about 8K, 32K and 64K tokens, greedy and sampled (seed 1234, 64 tokens, Why it gains. Per row, For the device cells. Three things that fail or go stale at 4,096 rows, which you may want before the run:
The test changes are about twenty lines; I can post them as a patch if that helps. On the shape. #1554's C would fit GLM too: 4,096 rows a pass only while no other stream decodes, as #1423's pair chooses, and the grid left at 2,048, as #720 does for Nemotron with |
|
Thanks @Bizuayeu, these are exactly the receipts we asked for, and they answer it clearly. At 4,096 rows, against 2,048, on GLM-5.3-Flash:
So 2,048 stays the default: a default can't get slower for warm turns or for streams already decoding. We'd still take 4,096 as an opt-in setting for servers that mostly see cold long prompts, as on #1554 and #1570, with these tables in the recipe so people can choose. If you'd like to reshape the PR that way, it's welcome. The DFlash2 context half can go separately if it stands on its own. |
Thanks, that settles the default. The PR and the claim on #1570 are @gilby's, so the reshape is theirs unless they'd rather hand it over. One question on the shape, since it changes what the recipe's tables say: should the opt-in be a fixed 4,096, or #1554's C? I have C as a local prototype on main, |
|
Measured it anyway, since the hosts were free: #1554's C on GLM at TP=3, in the shape of #1733's table. One build on main
It's two commits, local so far: the lanes' host checks moved to their own file, as #1423's first commit does, and the step, which I'd rename after #1733's variable. It overlaps #1423 in |
|
TP=2 for the table above, and the re-measure from the receipts' correction: I had called the −6 to −8% at
Cold first token, one stream. Cache 0 is one launch a side:
|
|
TP=3 on source, which the last comment left open. Same build, launched unset,
With #1733 in, this could take the same shape: |
What this changes
Fixes #1570. CUDA GLM takes prompt chunks of 4,096 rows instead of 2,048 (
cuda_state.prefill_rows). DFlash2'sMAX_CTX, which sizes the context rows one ingest takes, now followsprefill_rowsinstead of a separate 2048: changing the chunk alone faults at startup with a drafter loaded at TP=3 (CUDA_ERROR_ILLEGAL_ADDRESSincuStreamSynchronize), because the ingest of a 4,096-row chunk overruns the 2,048-row tap and context buffers. The output is unchanged.Receipt
Environment: three DGX Spark (GB10, 128 GB), driver 580, CUDA 13.0, ConnectX-7 RoCE through a switch, NCCL over IB;
nvidia/GLM-5.3-Flash-FP4-Local@ 76348ddb,--context 500000 --parallel 4 --prompt-cache-gib 0 --kv-cache fp8,TF_GLM_INDEX_CUDA=1;zig build native -Dsm=121. Each table's rows come from one session.Prompt speed, cold first token,
tools/bench_cache.py --require-cold --repeats 1 --streams 1 --tokens 16(a fresh random prefix each run), TP=3, no drafter,maina881b6f:mainTP=2 (two ranks), no drafter,
maina881b6f: 32,768 tokens 24.92 → 22.84 s, 131,072 tokens 98.98 → 92.54 s. Startup weights and workspace a rank 93.24 → 95.18 GiB; four 500K windows still fit (11.1 GiB left after them); lowestMemAvailableon a rank during the 131K prompt 12.9 GiB.With the DFlash2 drafter at TP=3,
main7c06889 against this branch: startup 67.19 → 68.97 GiB a rank, four 500K windows fit (36.4 GiB left). 41,943 tokens 26.83 → 25.92 s and 166,700 tokens 103.71 → 96.69 s to the first token, the same 64-token completions (same hashes), and draft acceptance level (34/59 and 33/58, 27/76 and 28/74).Exactness,
tools/bench_concurrent.py --levels 1,4 --tokens 256 --reps 3 --temperatures 1.0,0 --alone --serial: 0 unequal and 0 failed in every cell, without the drafter and with it, both at TP=3; with the drafter, all 540 completion hashes equalmain's with the drafter. Without the drafter, 64-token completions after 41,943- and 166,700-token prompts hash the same at 2,048 and 4,096 rows.Decode speed: level (with the drafter at TP=3, code T=1 one stream 63.5 vs 63.6 tok/s).
Tests:
zig build test-cuda-hoston Linux aarch64 (GB10) at 7c06889 with this change: 270/270 steps, 3,843 of 3,852 tests passed, 9 skipped.zig fmt --checkclean on both files.python3 tools/zig/lean_check.py: 425 problems, the same asmain.Trade-off: at TP=2 with the drafter, the larger chunk and drafter buffers leave 9.90 GiB for streams where
--parallel 4at a 500K window needs 10.44 GiB, so that setup serves--parallel 3(or a shorter window) wheremainfits four. TP=3, and TP=2 without the drafter, still fit four.Not run: the exactness bench at TP=2 (the row split is the same code at any rank count). Metal is not affected (CUDA family path).
Checklist
"draft": falseand concurrent equals solo (the bench above). A prompt split at other rows gives the same bits, so a resumed prompt reads the same caches as a fresh one.