Skip to content

LMCache 的设计

5.9.1 分层KV Cache存储

LMCache是伯克利大学SkyComputing实验室开发的开源KV Cache管理系统。

LMCache架构

LMCache 存储后端:

后端类型实现适用场景
GPUCUDA内存池活跃请求
CPU共享内存近期请求
DiskLMDB/SQLite持久化存储
RemoteRedis/Memcached分布式共享
CloudS3/GCS长期归档

5.9.2 与vLLM集成

LMCache 可以无缝集成到vLLM中

python
# LMCache  与vLLM集成示例
from lmcache.integration.vllm import LMCacheWrapper
from vllm import LLM


#   初始化vLLM
llm = LLM(model="meta-llama/Llama-2-7b-hf")


#   包装vLLM以使用LMCache
lmcache_config = {
    "chunk_size": 256,
    "local_cpu": True,
    "local_disk": "/tmp/lmcache",
    "remote_url": "redis://localhost:6379",
    "compression": "fp8",
}


llm_with_cache = LMCacheWrapper(llm, config=lmcache_config)


# 使用缓存的推理
# 第一次请求会计算并缓存KV
output1 = llm_with_cache.generate("Explain quantum computing")


#   第二次请求会复用缓存的KV
output2 = llm_with_cache.generate("Explain quantum computing in detail")

5.9.3 性能优化

LMCache 的性能优化策略:

Chunk-based存储

python
class ChunkedKVCache:
    """基于chunk的KV Cache存储"""
    def __init__(self, chunk_size: int = 256):
          self.chunk_size = chunk_size
          self.chunk_cache = {}


    def store(self, key: str, kv_cache: torch.Tensor):
          """将KV Cache分块存储"""          
          seq_len = kv_cache.shape[0]
          num_chunks = (seq_len + self.chunk_size - 1) // self.chunk_size

          for i in range(num_chunks):
                start = i * self.chunk_size
                end = min((i + 1) * self.chunk_size, seq_len)
                chunk = kv_cache[start:end]

                chunk_key = f"{key}_chunk_{i}"
                self.chunk_cache[chunk_key] = chunk


        def retrieve(self, key: str, start_chunk: int = 0) -> torch.Tensor:
             """ 检索KV Cache,支持部分检索"""              
              chunks = []
              i = start_chunk

              while True:
                    chunk_key = f"{key}_chunk_{i}"
                    if chunk_key not in self.chunk_cache:
                       break
                    chunks.append(self.chunk_cache[chunk_key])
                    i += 1

              return torch.cat(chunks, dim=0) if chunks else None

异步预取

python
class AsyncPrefetcher:
   """    异步预取KV Cache"""
   def __init__(self, cache: ChunkedKVCache):
          self.cache = cache
          self.prefetch_queue = asyncio.Queue()
          self.prefetch_task = asyncio.create_task(self._prefetch_loop())


   async def schedule_prefetch(self, key: str, chunk_idx: int):
          """调度预取请求"""
          await self.prefetch_queue.put((key, chunk_idx))


   async def _prefetch_loop(self):
          """预取循环"""
          while True:
                key, chunk_idx = await self.prefetch_queue.get()
                chunk_key = f"{key}_chunk_{chunk_idx}"

                #   异步加载到GPU
                if chunk_key in self.cache.chunk_cache:
                     chunk = self.cache.chunk_cache[chunk_key]
                     #   预加载到GPU pinned memory
                     chunk.pin_memory()

LMCache 性能数据:

工作负载无缓存LMCache加速
长文档QA1.2s0.3s4x
多轮对话0.8s0.2s4x
批量推理45 req/s120 req/s2.7x

用心记录,持续成长