From 6842cd06663ee0c2926dc61bcd82b9468b974dcd Mon Sep 17 00:00:00 2001 From: losewayy <104015127+losewayy@users.noreply.github.com> Date: Sat, 10 Oct 2026 13:21:28 +0800 Subject: [PATCH 1/2] fix: demote resident params to disk residency when reclamation fails --- src/model_manager.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/model_manager.cpp b/src/model_manager.cpp index e719825f7..9f2922ffb 100644 --- a/src/model_manager.cpp +++ b/src/model_manager.cpp @@ -1904,6 +1904,47 @@ bool ModelManager::ensure_compute_backend_capacity( } } + // Params resident on the compute device have no reloadable backing copy, so + // nothing above could reclaim them. As a last resort, demote file-reloadable + // states to disk residency; demotion only unlocks evictability; the same + // machinery still decides what is actually released. Required states are + // skipped: they are counted by fits(), so releasing them can never help. + std::unordered_set required_set(required_states.begin(), required_states.end()); + std::vector demoted_states; + auto revert_demotions = [&]() { + // Keep disk residency only for states that were actually evicted; states + // still holding memory revert so the flag cannot outlive its purpose. + for (TensorState* state : demoted_states) { + if (state->loaded_to_params_backend) { + state->residency_mode = ResidencyMode::ParamBackend; + } + } + }; + auto can_demote_to_disk = [&](TensorState* state) { + return state != nullptr && state->tensor != nullptr && state->tensor->view_src == nullptr && + state->residency_mode == ResidencyMode::ParamBackend && + state->params_backend != nullptr && state->params_backend == state->compute_backend && + state->compute_backend == compute_backend && !sd_backend_is_cpu(state->params_backend) && + state->pin_count == 0 && !state->staged_to_compute_backend && state->loaded_to_params_backend && + protected_states.find(state) == protected_states.end() && + required_set.find(state) == required_set.end() && + !state->sources.empty() && state->applied_lora_epoch == UINT64_MAX && + state->split_buffer_type == nullptr; + }; + for (TensorState* state : global_candidates) { + if (!can_demote_to_disk(state)) { + continue; + } + state->residency_mode = ResidencyMode::Disk; + demoted_states.push_back(state); + add_evictable_state(state); + if (release_eviction_states()) { + revert_demotions(); + return true; + } + } + revert_demotions(); + const auto capacity = check_capacity(request, required_states, true); const std::string available_device = capacity.available_device_bytes == SIZE_MAX ? "unknown" From cd4c7971812114950e1c7fca3688f31578a329c3 Mon Sep 17 00:00:00 2001 From: leejet Date: Sat, 10 Oct 2026 22:55:33 +0800 Subject: [PATCH 2/2] fix: exclude mmap params from disk residency demotion --- src/model_manager.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/model_manager.cpp b/src/model_manager.cpp index 9f2922ffb..2815e168b 100644 --- a/src/model_manager.cpp +++ b/src/model_manager.cpp @@ -1904,16 +1904,17 @@ bool ModelManager::ensure_compute_backend_capacity( } } - // Params resident on the compute device have no reloadable backing copy, so - // nothing above could reclaim them. As a last resort, demote file-reloadable - // states to disk residency; demotion only unlocks evictability; the same - // machinery still decides what is actually released. Required states are - // skipped: they are counted by fits(), so releasing them can never help. + // The loader retains mmap buffers after storage blocks are released, so + // demoting mapped states would only force duplicate allocations on reload. + std::unordered_set mapped_states; + for (const auto& block : params_storage_blocks_) { + if (!block->mmap_tensor_stores.empty()) { + mapped_states.insert(block->states.begin(), block->states.end()); + } + } std::unordered_set required_set(required_states.begin(), required_states.end()); std::vector demoted_states; auto revert_demotions = [&]() { - // Keep disk residency only for states that were actually evicted; states - // still holding memory revert so the flag cannot outlive its purpose. for (TensorState* state : demoted_states) { if (state->loaded_to_params_backend) { state->residency_mode = ResidencyMode::ParamBackend; @@ -1928,6 +1929,7 @@ bool ModelManager::ensure_compute_backend_capacity( state->pin_count == 0 && !state->staged_to_compute_backend && state->loaded_to_params_backend && protected_states.find(state) == protected_states.end() && required_set.find(state) == required_set.end() && + mapped_states.find(state) == mapped_states.end() && !state->sources.empty() && state->applied_lora_epoch == UINT64_MAX && state->split_buffer_type == nullptr; };