Skip to content

--batch: keep system-prompt roots apart from the conversations (--prompt-cache-roots, opt-in) - #2325

Closed
brocktice wants to merge 1 commit into
Niko1221:mainfrom
brocktice:batch-slot-root
Closed

brocktice wants to merge 1 commit into
Niko1221:mainfrom
brocktice:batch-slot-root

Conversation

@brocktice

Copy link
Copy Markdown

Why

We serve an agent client whose every chat opens with the same ~79K-token system prompt and tool list, on parallel: 4 with --batch-mtp and --conversation-cache-mib 8192. Its chats overlap with other traffic all day, and every new chat read the whole opening again (20-35 s) although the engine had read the same tokens minutes before.

The cause is in --batch. The root checkpoint (the end of the system prompt, PR #65) lives in the main session's chain, but:

After a few turns of any chat nothing holds the root any more. Solo traffic does not show it: a request that runs alone stays on the main session and its chain stays whole.

What it does

--prompt-cache-roots N (default 0 = off, every path unchanged) keeps a copy of the last N roots the engine made, apart from any conversation (one per distinct system prompt, ~118 MB of RAM each; least recently made or used leaves first). A root's state depends on its tokens alone, so:

Because the main chain keeps its root again, parked conversations keep it too, so a new chat also mounts through a parked one.

Tests

conv_cache_test covers the store (kept, refreshed, the least recently used one leaves, other images or control-vector mode do not match, clear).

Real engine: v0.1.43 on one RTX PRO 6000 (Blackwell), Qwen3.8-Flash-Next IQ3_S, parallel: 4, --batch-mtp, --conversation-cache-mib 8192. A 42K-token system prompt; chat A three turns, a request with another system prompt, chat B two turns, chat C. Greedy, the same requests with the flag off and on:

flag off flag on
sequential (no overlap) new chats reuse 42,146 tokens the same
two other requests always decoding: new chat B (--prompt-cache-roots 2) 0 reused, 11.6 s 42,146 reused, 0.8 s
parking off (--conversation-cache-mib 0), the root only in an idle slot: new chat B (--prompt-cache-roots 8) 0 reused, 7.9 s 42,146 reused, 0.8 s

Answers were identical between the arms except one 600-token answer decoded beside another request; that one also differs between two runs with the flag off (batched greedy decode is not run-to-run identical).

N matters: in the last scenario with N = 2, a third system prompt pushed the 42K root out before chat B came, so we run 8.

In use: v0.1.43 plus this change has run with --prompt-cache-roots 8 on two RTX PRO 6000s for about 8 hours of mixed agent, chat and tool traffic (about 2,800 requests, no errors); new chats of that client now reuse their shared opening.

Builds: the measurements above are from this change on v0.1.43. Rebased on current main, it builds for CUDA (sm_120) and CTest passes (conv_cache_test included) except ple_parity, which needs a Q2_0 model file I do not have. I could not build HIP or SYCL (no toolchain here). The change is host-only C++ in src/program/generate.cpp and conv_cache.hpp; the SYCL generate.cpp includes the header but does not use the new class (the header also compiles alone with g++ -Wall -Wextra).

Default path: with the flag at 0 the store is empty and every new branch is skipped: seed_root, the slot lookup and keep all test enabled() or prompt_cache_roots first, so no checkpoint, copy or log line differs.

Related: #1529 keeps the root in the disk tier's spilled files. This change is the RAM side under --batch and does not touch the disk tier.

Happy to change the shape (a default other than 0, or keeping the roots inside the conversation cache's budget).

🤖 Generated with Claude Code

…mpt-cache-roots, opt-in)

With --batch the chain a system-prompt root was made in does not stay whole: a slot keeps only its turn
checkpoint, and a request that continues from a slot takes over that checkpoint alone. After a few turns
of any chat the engine holds no root, so the next new chat of the same client reads its whole system
prompt again.

--prompt-cache-roots N keeps a copy of the last N roots (one per distinct system prompt, ~118 MB each).
A new chat mounts through one from the main session, when its cells hold those tokens, or from any idle
slot that holds them. The default (0) leaves every path as it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Niko1221

Copy link
Copy Markdown
Owner

Thanks for the pull request.

We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to review properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected.

To reopen it takes about two minutes:

  1. Rebase on main if it no longer applies, and re-run your checks on 0.2.0-beta.
  2. Start the title with its area: [Engine], [GUI], [TUI], [Benchmark], [Docs] or [Other].
  3. Fill in the pull request template: the problem and result, and the validation (what you ran, on which revision, what you saw).
  4. Comment /reopen. A check runs and either reopens the pull request or lists what is still missing.

The rules are in CONTRIBUTING.md.

@Niko1221 Niko1221 closed this Oct 19, 2026
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