逐层 KV 传输#
在逐层粒度上存储和加载 KV Cache 是一个关键优化,它允许前向传播在计算过程中“错开”,因为每一层的 KV Cache 在接收后就可以开始,而不必等到整个加载完成后才开始。
CacheBlend 是在逐层代码路径之上实现的,目的是将重计算和加载进行流水线处理,以掩盖加载 KV Cache 的延迟。
架构概述#
- CacheEngine
主要协调器,包含两个主要生成器:
检索生成器 (N + 2 生成): 处理逐层 KV Cache 加载,按需分配内存
存储生成器 (N + 1 yields): 管理逐层 KV Cache 保存,并提前分配 CPU 内存
- LayerwiseGPUConnector
管理使用专用 CUDA 流的 GPU-CPU 内存传输:
加载 GPU 缓冲区:用于 CPU→GPU 传输的临时显存(
use_gpu: true)存储 GPU 缓冲区:用于 GPU→CPU 传输的临时显存(
use_gpu: true)嵌套生成器:
batched_to_gpu()和batched_from_gpu()处理实际的内存操作
- 存储管理器
处理持久存储操作:
layerwise_batched_get(): 使用.result()进行请求级并发的异步检索batched_put(): 将内存对象存储到持久后端
执行流程#
逐层管道遵循编号的执行顺序:
- 1. start_load_kv()
通过
lmcache_engine.retrieve_layer()初始化检索生成器执行设置(第一次
next())并加载第 0 层(第二次next())创建
layerwise_retrievers列表以进行持续的层处理
- 2. wait_for_layer_load() (对每一层重复执行)
通过
next()使检索生成器向前推进以处理第 i 层触发
StorageManager.layerwise_batched_get()进行异步缓存查找调用 GPU Load Generator 的
batched_to_gpu()将内存对象传输到 GPU批处理中的最后请求:同步
current_stream.wait_stream(load_stream)
- **3. save_kv_layer()**(对每一层重复执行)
首次调用仅:创建具有预先分配 CPU 内存的存储生成器
通过
next()进展存储生成器以处理第 i 层调用 GPU 存储生成器的
batched_from_gpu()将 GPU 数据传输到 CPU批处理中的第一个请求:同步
store_stream.wait_stream(current_stream)
- 4. wait_for_save()
通过最后一次
next()调用来完成存储生成器完成所有
StorageManager.batched_put()操作执行 GPU 存储生成器清理
关键优化#
- 流水线内存操作
系统将第 N+1 层的计算与第 N 层的存储重叠。
- 流同步
三个 CUDA 流协调操作:
current_stream: vLLM 的前向传播计算load_stream: KV Cache 加载操作store_stream: KV Cache 存储操作
- 批量级协调
多个请求一起处理,并使用专门的同步机制:
第一次请求:提供存储流同步以防止 GPU 缓冲区损坏
最后请求:提供加载流同步以确保 KV Cache 可用性
- 内存分配策略
检索:逐层分配
存储:为所有层的预先分配
- 缓存键管理
多层缓存引擎密钥使用
split_layers(N)来创建每层的 kubernetes_deployment
配置#
通过设置启用逐层缓存:
use_layerwise: true
系统会根据配置自动选择适当的逐层显卡连接器:
VLLMPagedMemLayerwiseGPUConnector: 用于标准逐层操作VLLMBufferLayerwiseGPUConnector: 当启用混合时