From f19246e59ada26566da59d5602aa1880bf3c76b1 Mon Sep 17 00:00:00 2001 From: Zhiqiang Xie Date: Thu, 2 Jul 2026 12:16:03 -0700 Subject: [PATCH] [HiCache] write_back policy refinement (#29817) --- .../sglang/srt/managers/cache_controller.py | 5 --- python/sglang/srt/mem_cache/hiradix_cache.py | 40 ++++++++++++++----- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/python/sglang/srt/managers/cache_controller.py b/python/sglang/srt/managers/cache_controller.py index ab1347c0b..29f497c54 100644 --- a/python/sglang/srt/managers/cache_controller.py +++ b/python/sglang/srt/managers/cache_controller.py @@ -273,11 +273,6 @@ class HiCacheController: ]: raise ValueError(f"Invalid write policy: {write_policy}") - if write_policy == "write_back": - logger.warning( - "write_back policy will be deprecated in future releases; please migrate to write_through_selective with appropriate configuration for better performance and reliability." - ) - # self.write_queue = PriorityQueue[CacheOperation]() self.load_queue: List[CacheOperation] = [] self.write_queue: List[CacheOperation] = [] diff --git a/python/sglang/srt/mem_cache/hiradix_cache.py b/python/sglang/srt/mem_cache/hiradix_cache.py index 99d11e1b3..c6ce33af3 100644 --- a/python/sglang/srt/mem_cache/hiradix_cache.py +++ b/python/sglang/srt/mem_cache/hiradix_cache.py @@ -8,7 +8,7 @@ import os import threading import time from queue import Empty -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING, Dict, List, Optional, Tuple import torch @@ -1087,7 +1087,7 @@ class HiRadixCache(RadixCache): heap = self._make_eviction_heap() num_evicted = 0 while num_evicted < num_tokens and heap: - _priority, x = heapq.heappop(heap) + _, x = heapq.heappop(heap) if x.lock_ref > 0: continue if x.backuped: @@ -1103,26 +1103,38 @@ class HiRadixCache(RadixCache): """ heap = self._make_eviction_heap() num_evicted = 0 + staged: List[Tuple[TreeNode, torch.Tensor]] = [] + + def flush_staged() -> None: + if not staged: + return + self.writing_check(write_back=True) + for node, device_indices in staged: + self.cache_controller.evict_device(device_indices) + node.release_host() + staged.clear() + while num_evicted < num_tokens and heap: - _priority, x = heapq.heappop(heap) + _, x = heapq.heappop(heap) if x.lock_ref > 0: continue if x.backuped: num_evicted += self._evict_backuped(x) elif self.write_backup(x, write_back=True) > 0: - self.writing_check(write_back=True) - num_evicted += self._evict_backuped(x) + x.protect_host() + staged.append((x, x.value)) + num_evicted += self._detach_backuped(x) else: + flush_staged() num_evicted += self._drop_subtree_no_host(x) self._promote_parent(x, heap) + flush_staged() return num_evicted - def _evict_backuped(self, node: TreeNode): - # GPU -> CPU demotion: block moves from device to host. - # Emit remove(GPU) so downstream indexers stop scoring it as device-local. - # The matching store(CPU) was emitted when write_backup() copied to host. + def _detach_backuped(self, node: TreeNode) -> int: + # detach nodes from tree while keeping device slots, for write-back eviction self._record_remove_event(node, medium=StorageMedium.GPU) - num_evicted = self.cache_controller.evict_device(node.value) + num_evicted = len(node.value) assert num_evicted > 0 self.evictable_size_ -= num_evicted node.value = None @@ -1132,6 +1144,12 @@ class HiRadixCache(RadixCache): self._update_leaf_status(node.parent) return num_evicted + def _evict_backuped(self, node: TreeNode): + device_indices = node.value + num_evicted = self._detach_backuped(node) + self.cache_controller.evict_device(device_indices) + return num_evicted + def _evict_regular(self, node: TreeNode): # evict a node not initiated write to host -- emit BlockRemoved assert len(node.children) == 0, f"non-leaf, {node.id=}" @@ -1190,7 +1208,7 @@ class HiRadixCache(RadixCache): num_evicted = 0 while num_evicted < num_tokens and len(eviction_heap): - _priority, x = heapq.heappop(eviction_heap) + _, x = heapq.heappop(eviction_heap) if x == self.root_node: break # only evict the host value of evicted nodes