Repository navigation
Conversation
…emory With TF_GLM_HOST_CACHE=1 on every rank, the snapshot arena is pinned host memory mapped into the device's address space, so the existing device-to-device copies move a kept state across PCIe. The family reports host_snaps, so the server sizes the cache from --prompt-cache-gib in host memory and the KV pool plan sets no device cache aside. Fixes ashhart#1735, refs ashhart#1510.
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
On CUDA, GLM-5.3-Flash keeps its prompt states in one device arena that gets only the memory the KV pool leaves over.
On discrete cards that is often a fraction of a GiB, so a long conversation's state is refused and every turn
prefills the whole conversation again (#1510).
With
TF_GLM_HOST_CACHE=1on every rank:HostBuffer.allocMapped), so theexisting
cuMemcpyDtoDAsynckeep/restore copies move a state across PCIe.host_snaps, so the server uses its existing host-cache path:--prompt-cache-gibsizes the cache inhost memory, and the KV pool plan sets no device cache aside.
Fixes #1735. Refs #1510: this is a host-memory route to that issue, complementing #1732 (prompts as pool pages) rather
than replacing it; the two combine (see "Not run"). No kernel, scheduler or arithmetic change.
Overlap with #1732: both add a field at the end of GLM's
Loadedstruct incuda_native.zig, a one-line textualconflict. Nothing else overlaps (
atc overlap: #1411 and #1655 merge cleanly). Happy to rebase whichever lands second.Why: the first step toward GLM-5.3-Flash on two 96 GB cards with system memory
The goal. Serve GLM-5.3-Flash (
Mia-AiLab/GLM-5.3-Flash-EXL3-4bpw-TensorFold) on two RTX PRO 6000 Blackwell cardsat TP=2, using the host's system memory to win back the KV room the weights take, without a major speed loss.
Why VRAM is the limit.
gets what the KV pool leaves: under 1 GiB, enough to resume conversations up to ~30K tokens.
The plan, as separate PRs. Each one is one change with its own receipt. Later steps are listed for context, not
for review here.
--vision-offloaddoes for other families. It frees~1.05 GiB on rank 0, the rank that bounds both ranks' room.
indexer's top 2,048 rows per query.
roughly 25 MB a decode token per rank across PCIe.
KV pool: host tier for the core pool (5/8) #1501/EXL3 Flash Next: host-resident K/V on the tier (6/8) #1522 rather than add a second one, and we'd like maintainer guidance on that direction before starting.
Receipt
Environment.
main94b90c9 with and without this commit, built with Zig 0.17.0 and nvcc 13.4.92 (-Dsm=120).NCCL 2.32.3, cuBLASLt 13.4, driver 615.71.09, Linux 7.3.
Mia-AiLab/GLM-5.3-Flash-EXL3-4bpw-TensorFold@ 76c0b517.--context 327680 --kv-cache bf16 --parallel 2 --vision,TENSORFOLD_MEMORY_RESERVE_GIB=2.6. Candidate:TF_GLM_HOST_CACHE=1 --prompt-cache-gib 24. GPU cap 400 W forevery speed number.
Exactness.
tools/bench_concurrent.py --levels 1,2 --tokens 256 --temperatures 0 --alone --serial, code and chat. Baselineand candidate: alone 3/3 and 6/6 equal, serial 1/1 equal in every cell; 0 unequal, 0 failed.
re-prefills every turn (
cached_tokens0). The candidate restores turns 2-4 from host memory (cached_tokens57,344). All 4 replies are identical to the baseline's, byte for byte.
TF_GLM_HOST_CACHE=1 --prompt-cache-gib 0. The startup line reads "no prompt cache", no hostmemory is pinned, and
cached_tokensis 0 on every turn.Decode speed (
tools/bench_openai.py --tokens 256 --reps 3 --temperatures 0), median tok/s; identicaltoken_shain every cell.bench_concurrent.pyaggregate at 2 streams: code 382.2 vs 381.1, chat 243.6 vs 242.8.Prompt speed (
tools/bench_cache.py --require-cold --tokens 64), fixed token arrays from the repository's owndocs, fresh server each run, alternating baseline/candidate. Cold first-request
ttft_s:Same
token_sha,cached_tokens0 on every first request.What it buys. Same server, same settings:
Pinned host memory measured ~57 GB/s each way on this machine.
Tests run.
zig build test --test-timeout 10m: 5,752 passed, 27 skipped, 0 failed.test-kernel-contract: 141/141.test-golden: pass.test-server-security test-pull-security: 26/26.fuzz-cortheon: 17/17.test-glm-snapshots-host: 20/20, with the new host-arena round trip inzig/glm_snapshot_host_ram.zig, which fails before this change.test-glm-pages-host: pass.zig build: pass.build_options_test.py: pass.git diff --check: clean.lean_new.pyagainstmain: 424 problems on the base, 424 on the head, 0 new.Not run, and why.
either way, so the setting gains nothing there.
--learn-conversations: disk images go through the same snapshot plan, but were not exercised with the host arena.TF_GLM_KV_SHARE) combined with this setting: checked on glm cuda: TF_GLM_KV_SHARE keeps prompts as the pool's pages in prompt_radix's store #1732's head with this commit on top.TF_GLM_KV_SHARE=8.glm cuda: TF_GLM_KV_SHARE keeps prompts as the pool's pages in prompt_radix's store #1732 alone.
Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.main(cold 32K/64K above).