Skip to content

fit: also take into account n_streams - #27496

Open
ngxson wants to merge 3 commits into
masterfrom
xsn/server_fit_no_kvu
Open

fit: also take into account n_streams#27496
ngxson wants to merge 3 commits into
masterfrom
xsn/server_fit_no_kvu

Conversation

@ngxson

@ngxson ngxson commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR fixes this particular setup on llama-server: --fit -no-kvu -np 4

If the machine has plenty of RAM, the max context size will be capped to model's trained context size. This is OK in kv-unified because one single request can still use the full trained context window

However, with no-kvu and for example -np 4, the slot ctx size will be model's trained context divided by 4, which is not something we want. That means we cannot use the full model trained context even if we have plenty of RAM to store 4*n_ctx_trained

Example: testing with tinygemma3:

  • Before this PR: --fit -no-kvu -np 4 sets n_ctx = 131072, and so each slot only get 32768 tokens
  • After this PR: --fit -no-kvu -np 4 sets n_ctx = 131072*4 = 524288, and so each slot get 131072

Note: one edge case that I couldn't test: what if we require -np 4 but physical RAM can only hold -np 3. Logically this will be handled, but just haven't tested

Requirements

@ngxson
ngxson requested a review from a team August 21, 2026 11:41
@ngxson

ngxson commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@ServeurpersoCom thanks for testing! feel free to push your fixes directly here

With a non-unified KV cache the target context now holds n_ctx_train
tokens per sequence, while the draft context was still created with
n_ctx = 0 and fell back to n_ctx_train / n_streams per sequence. A slot
filled beyond that point makes the draft batch fail to decode, and the
server answers 500 on the request.

The draft context now takes its size from the target context, so both
hold the same number of tokens per sequence. Contexts that share their
cells with the target no longer need the kv_size override.

The memory reserved for the draft model before fitting is measured at
the largest context the target can take, since the draft context grows
with the target and a fixed byte margin cannot express that.
@ServeurpersoCom
ServeurpersoCom requested a review from a team as a code owner August 21, 2026 20:55
@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Follow-up on the reservation side. The draft memory is currently folded into fit_params_target as a fixed byte margin. That is right for the mmproj, whose size does not depend on the context, but not for the draft context, which now scales with the target n_ctx. My commit works around it by probing the target n_ctx_train and measuring the draft at the upper bound, so it over-reserves whenever the fit ends up reducing the context.

Would you rather have common_fit_params take an optional draft model and measure both at each candidate context? That drops the probe and the whole reservation block in server-context.cpp, and makes the reduce path exact instead of conservative, at the cost of one more parameter in the common API.

Illustrates the alternative discussed on the draft context fix. The
memory of a draft or MTP context is currently handed to the fit as a
fixed byte margin, which cannot express a memory that grows with the
context the fit is still deciding on.

common_fit_params now takes an optional second model that shares the
devices of the main one. Its context follows the main context and its
memory is measured again whenever that context changes, so the reduce
path stays exact instead of conservative. A model that cannot be
measured on its own, such as a shared cell MTP context, is skipped with
a warning and the main model is fitted alone.

This drops the reservation block in the server, which no longer has to
probe the trained context size of the target to guess an upper bound.
@ServeurpersoCom

Copy link
Copy Markdown
Contributor

The second commit is the refactor, re-tested:

1  44372 token prompt, draft-simple   44372 evaluated, 128 generated, correct answer
2  context alignment                  target and draft at 131072, fit at 12011 MiB, successfully fit
3  MTP not measurable                 warning, then fit on the main model alone, contexts aligned
4  no speculation                     no extra measurement, fit back to 0.63 s
5  forced reduction (-fitt 90000)     draft measured at 131072 then 4096, reduced to 22016 per slot
6  functional under reduced context   16800 tokens pass, 7559 MiB of VRAM, target margin held
7  fit-params and llama-bench         unchanged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants