llama: free backend compute scratch on cold; guard memory_breakdown

On device release with KV eviction, also call ggml_backend_free_scratch()
on each backend so a cold model drops its Vulkan compute preallocations
(reallocated lazily on the next compute via restore).

Also guard llama_context::memory_breakdown() against a freed scheduler:
evict_kv release resets sched to null, so a cold model that is then torn
down (e.g. terminated by the process manager) hit GGML_ASSERT(sched) in
ggml_backend_sched_get_buffer_type. Skip the compute-buffer accounting
when sched is null.

Assisted-by: Claude
This commit is contained in:
2026-07-26 14:56:05 +02:00
parent 994fd757fc
commit c4c97f0595
+9
View File
@@ -742,6 +742,11 @@ void llama_context::release_device(bool evict_kv) {
// model holds essentially no VRAM. Rebuilt lazily by sched_reserve() on restore. // model holds essentially no VRAM. Rebuilt lazily by sched_reserve() on restore.
sched.reset(); sched.reset();
sched_need_reserve = true; sched_need_reserve = true;
// finally, free each backend's own compute-scratch (Vulkan prealloc/staging buffers, which
// are owned by the backend and survive sched.reset()). Reallocated lazily on next compute.
for (auto & backend : backends) {
ggml_backend_free_scratch(backend.get());
}
} }
} }
@@ -3265,6 +3270,9 @@ llama_memory_breakdown llama_context::memory_breakdown() const {
ret[buft].context += size; ret[buft].context += size;
} }
} }
// the scheduler (and its compute buffers) may have been freed while the model is cold
// (on-demand VRAM eviction, see release_device); it contributes no compute VRAM then.
if (sched) {
if (model.hparams.no_alloc) { if (model.hparams.no_alloc) {
for (size_t i = 0; i < backends.size(); ++i) { for (size_t i = 0; i < backends.size(); ++i) {
ggml_backend_t backend = backends[i].get(); ggml_backend_t backend = backends[i].get();
@@ -3278,6 +3286,7 @@ llama_memory_breakdown llama_context::memory_breakdown() const {
ret[buft].compute += ggml_backend_sched_get_buffer_size(sched.get(), backend); ret[buft].compute += ggml_backend_sched_get_buffer_size(sched.get(), backend);
} }
} }
}
return ret; return ret;
} }