Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions python/sglang/srt/managers/cache_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,6 @@ def __init__(
]:
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] = []
Expand Down
40 changes: 29 additions & 11 deletions python/sglang/srt/mem_cache/hiradix_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
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

Expand Down Expand Up @@ -1087,7 +1087,7 @@ def _evict_write_through(self, num_tokens: int) -> int:
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:
Expand All @@ -1103,26 +1103,38 @@ def _evict_write_back(self, num_tokens: int) -> int:
"""
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
Expand All @@ -1132,6 +1144,12 @@ def _evict_backuped(self, node: TreeNode):
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=}"
Expand Down Expand Up @@ -1190,7 +1208,7 @@ def evict_host(self, num_tokens: int):

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
Expand Down
Loading