Skip to content

Commit 1acb0da

Browse files
authored
gemma4_31b (MLX): don't allocate a second KV-cache copy for single-session runs (#20560)
Since #20473, the MLX engine always enables the multi-session mutable-state path, so create_session() allocates a per-session KV-cache copy on top of the program's default buffers — which rebind never uses again once a session exists — leaving single-session runs holding two full KV caches. This gates the MLX mutable_state creation on config.max_sessions > 1, so the single-session CLI runner (max_sessions = 1) executes against the default buffers (one KV cache, as before #20473) while the multi-session worker is unchanged. Result: lower peak memory and recovered prefill tok/s for single-session runs (significant at long context); decode is unaffected. Test: make gemma4_31b-mlx then run the runner — peak memory drops and prefill recovers, multi-session isolation still works. Follow-up: This only fixes the single-session case. Under multi-session the program's default mutable buffers are still allocated but go unused once any session is created, so the worker pays one extra dead KV-cache copy (N+1 for N sessions). A follow-up could release or donate the default buffers to the first session under multi-session, with a check that the init chain only zero-initializes KV state (per-session buffers are freshly zeroed and don't replay it).
1 parent 2af5638 commit 1acb0da

1 file changed

Lines changed: 9 additions & 1 deletion

File tree

examples/models/gemma4_31b/gemma4_31b_engine.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,15 @@ Result<std::unique_ptr<Gemma4_31BEngine>> Gemma4_31BEngine::create(
684684
}
685685
}
686686
#elif defined(EXECUTORCH_BUILD_MLX)
687-
mutable_state = std::make_unique<GemmaMutableStateContextOwner>();
687+
// Only enable the per-session mutable-buffer path when actually serving more
688+
// than one session. For a single session (the CLI runner) the rebind would
689+
// allocate a second copy of the KV-cache buffers on top of the program's
690+
// default buffers — doubling KV-cache memory and adding a one-time
691+
// session-buffer allocation during the first prefill — for no isolation
692+
// benefit. Leaving mutable_state null keeps the program's default buffers.
693+
if (config.max_sessions > 1) {
694+
mutable_state = std::make_unique<GemmaMutableStateContextOwner>();
695+
}
688696
#endif
689697

690698
auto module_res = mutable_state != nullptr

0 commit comments

Comments
 (0)