[HiCache] write_back policy refinement (#29817)
This commit is contained in:
@@ -273,11 +273,6 @@ class HiCacheController:
|
|||||||
]:
|
]:
|
||||||
raise ValueError(f"Invalid write policy: {write_policy}")
|
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.write_queue = PriorityQueue[CacheOperation]()
|
||||||
self.load_queue: List[CacheOperation] = []
|
self.load_queue: List[CacheOperation] = []
|
||||||
self.write_queue: List[CacheOperation] = []
|
self.write_queue: List[CacheOperation] = []
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import os
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from queue import Empty
|
from queue import Empty
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional
|
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
@@ -1087,7 +1087,7 @@ class HiRadixCache(RadixCache):
|
|||||||
heap = self._make_eviction_heap()
|
heap = self._make_eviction_heap()
|
||||||
num_evicted = 0
|
num_evicted = 0
|
||||||
while num_evicted < num_tokens and heap:
|
while num_evicted < num_tokens and heap:
|
||||||
_priority, x = heapq.heappop(heap)
|
_, x = heapq.heappop(heap)
|
||||||
if x.lock_ref > 0:
|
if x.lock_ref > 0:
|
||||||
continue
|
continue
|
||||||
if x.backuped:
|
if x.backuped:
|
||||||
@@ -1103,26 +1103,38 @@ class HiRadixCache(RadixCache):
|
|||||||
"""
|
"""
|
||||||
heap = self._make_eviction_heap()
|
heap = self._make_eviction_heap()
|
||||||
num_evicted = 0
|
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:
|
while num_evicted < num_tokens and heap:
|
||||||
_priority, x = heapq.heappop(heap)
|
_, x = heapq.heappop(heap)
|
||||||
if x.lock_ref > 0:
|
if x.lock_ref > 0:
|
||||||
continue
|
continue
|
||||||
if x.backuped:
|
if x.backuped:
|
||||||
num_evicted += self._evict_backuped(x)
|
num_evicted += self._evict_backuped(x)
|
||||||
elif self.write_backup(x, write_back=True) > 0:
|
elif self.write_backup(x, write_back=True) > 0:
|
||||||
self.writing_check(write_back=True)
|
x.protect_host()
|
||||||
num_evicted += self._evict_backuped(x)
|
staged.append((x, x.value))
|
||||||
|
num_evicted += self._detach_backuped(x)
|
||||||
else:
|
else:
|
||||||
|
flush_staged()
|
||||||
num_evicted += self._drop_subtree_no_host(x)
|
num_evicted += self._drop_subtree_no_host(x)
|
||||||
self._promote_parent(x, heap)
|
self._promote_parent(x, heap)
|
||||||
|
flush_staged()
|
||||||
return num_evicted
|
return num_evicted
|
||||||
|
|
||||||
def _evict_backuped(self, node: TreeNode):
|
def _detach_backuped(self, node: TreeNode) -> int:
|
||||||
# GPU -> CPU demotion: block moves from device to host.
|
# detach nodes from tree while keeping device slots, for write-back eviction
|
||||||
# Emit remove(GPU) so downstream indexers stop scoring it as device-local.
|
|
||||||
# The matching store(CPU) was emitted when write_backup() copied to host.
|
|
||||||
self._record_remove_event(node, medium=StorageMedium.GPU)
|
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
|
assert num_evicted > 0
|
||||||
self.evictable_size_ -= num_evicted
|
self.evictable_size_ -= num_evicted
|
||||||
node.value = None
|
node.value = None
|
||||||
@@ -1132,6 +1144,12 @@ class HiRadixCache(RadixCache):
|
|||||||
self._update_leaf_status(node.parent)
|
self._update_leaf_status(node.parent)
|
||||||
return num_evicted
|
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):
|
def _evict_regular(self, node: TreeNode):
|
||||||
# evict a node not initiated write to host -- emit BlockRemoved
|
# evict a node not initiated write to host -- emit BlockRemoved
|
||||||
assert len(node.children) == 0, f"non-leaf, {node.id=}"
|
assert len(node.children) == 0, f"non-leaf, {node.id=}"
|
||||||
@@ -1190,7 +1208,7 @@ class HiRadixCache(RadixCache):
|
|||||||
|
|
||||||
num_evicted = 0
|
num_evicted = 0
|
||||||
while num_evicted < num_tokens and len(eviction_heap):
|
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:
|
if x == self.root_node:
|
||||||
break
|
break
|
||||||
# only evict the host value of evicted nodes
|
# only evict the host value of evicted nodes
|
||||||
|
|||||||
Reference in New Issue
Block a user