- 大模型
- 人工智能
- 缓存
【免费下载链接】unified-cache-management
Unified Cache Manager(推理记忆数据管理器),是一款以KV Cache为中心的推理加速套件,其融合了多类型缓存加速算法工具,分级管理并持久化推理过程中产生的KV Cache记忆数据,扩大推理上下文窗口,以实现高吞吐、低时延的推理体验,降低每Token推理成本。
推理引擎通常把进行中请求的 KV Cache 保存在设备显存中,设备容量与进程生命周期共同限制了缓存留存:进程退出前算好的前缀,可能在下一个进程里被重新计算。unified-cache-management(UCM,Unified Cache Manager)通过引擎集成获得 block 标识符与缓冲区布局,将已完成的 KV block 保存到外部存储,并在后续请求中加载兼容 block 以实现跨进程、跨实例的 KV Cache 复用。本文基于仓库中 architecture.md 展开,结合 ucm_connector.py、ucmstore_v1.py、pipeline 连接器 等源码,讲清楚四件事:组件之间如何分工协作、vLLM 中复用发生在哪个环节、Store 接口与 Pipeline 流水线如何工作、以及不同推理引擎的集成入口有何差异。读完本文,你将能读懂 UCM 的 KV Cache 复用调用链,并据此选择、配置或扩展存储后端。
一、整体架构:为什么要把 KV Cache 搬出设备显存
推理时,模型需要为每个新 token 计算 Key/Value,这个过程重复出现于共享前缀请求中。设备显存有两个天然限制:
- 容量限制:显存是稀缺资源,只能容纳有限数量的活跃请求 KV Cache;
- 进程生命周期限制:进程退出后设备内存被回收,此前计算出的前缀 KV 全部丢失,重启后同一前缀必须从头重算。
UCM 的思路是:在引擎集成层获取 block 标识符(block identifier)和缓冲区布局(buffer layout),把计算完成的 KV block 保存到外部存储(文件系统、3FS、Mooncake 等),再在后续请求中加载兼容 block 供引擎直接使用。引擎无需自行推断模型结构——Store 接收的是 block 标识符与传输描述,而不是模型拓扑。这一设计使 KV Cache 的“记忆”从设备内存扩展到持久化存储,为扩大上下文窗口、降低 Prefill 重复计算成本提供了基础。
二、组件协作:谁拥有什么信息,谁做什么事
在 KV Cache 复用路径上,引擎集成把调度信息翻译为存储操作。UCM 在 架构文档 中给出了沿复用路径的组件职责表,各组件“拥有的信息”与“承担的职责”如下:
| 组件 | 拥有的信息 | 职责 |
|---|---|---|
| 推理引擎 | 请求、批次、模型与设备 KV Cache | 调度计算与缓冲区,执行 Attention,管理请求生命周期 |
| 引擎集成 / Connector | 钩子、布局、block 标识符与设备地址 | 发现可复用 block,构建传输元数据,执行 load/save 并处理完成事件 |
| Store 接口与工厂 | Store 名称、配置与任务接口 | 构造后端;暴露 lookup、prefetch、transfer 与完成检查 |
| Pipeline | 已注册的阶段组合与原生 Store 对象 | 串联存储阶段与可选的健康检查包装层 |
| 存储阶段 | 主机缓冲区或后端资源 | 在设备、主机内存、文件系统与远端存储之间搬运数据 |
下图为 UCM 连接器与存储架构图:vLLM 连接器通过 UCM 的存储接口访问后端,每个 Store 连接到各自的存储资源(虚线框保留早期规划中的扩展标记,当前 Store 接口与引擎入口以文末“引擎特定入口点”为准)。
从源码结构看,这条职责划分被严格贯彻到了类层次中:连接器类负责“翻译调度信息”,Store 类负责“搬运数据”。vLLM 集成侧的UCMConnectorMetadata(ucm_connector.py#L1307-L1309)与UCMWorkerMetadata(ucm_connector.py#L1328-L1360)就是引擎集成“构建传输元数据”的直接载体:前者携带请求级 load/save 记录,后者把 Worker 侧 load 失败、缺失 block、dump 成功等信息回传给 Scheduler。
三、复用发生在哪里:vLLM 中的 Scheduler/Worker 协作
在 vLLM 中,KV Cache 复用分为 Scheduler 侧与 Worker 侧两个环节:
- Scheduler 侧 Connector 查询外部 block:引擎先检查自身缓存,再调用
get_num_new_matched_tokens()(ucm_connector.py#L1794)。Connector 生成 UCM block 标识符、查询已计算部分之后的外部 block、记录请求匹配情况,返回额外可复用的 token 数。 - 引擎分配目标 KV block 后,Connector 依据调度结果建立映射:
build_connector_meta()(ucm_connector.py#L2064)读取已调度的新增/缓存请求与引擎 block ID,构造UCMConnectorMetadata。load/save 记录把 UCM 标识符映射到引擎 block 位置,Worker 再把这些位置解析为设备地址。 - Worker 收到元数据后加载数据:
start_load_kv()(ucm_connector.py#L2149)利用元数据与已注册布局提交 load;对应的 load 必须在 Attention 使用数据之前完成。 - 引擎计算未匹配部分,Connector 提交完整 block 进行保存:
wait_for_save()(ucm_connector.py#L2350)在直接(direct)路径中主要提交整块保存。
一个关键语义是:lookup、计算与存储拥有相互独立的完成条件。找到一个 block、完成它的 load、完成它的 save,是三个不同的事件;“查询命中”不代表“数据已在设备上可用”。因此 Worker 在消费前必须等待传输完成,load 失败也会通过 invalid-block 报告与 Worker 元数据反馈给引擎和 Scheduler,而不是把命中当作可用设备数据。
下图为一次“成功复用 + 保存”的生命周期示意:Scheduler 完成 lookup 并交接元数据后,Worker 依次进行 load、计算,save 完成反馈再触发资源释放。
在实现上,直接路径与逐层(layerwise)路径的编排不同:
UCMDirectConnector(ucm_connector.py#L1363)语义为同步的load → forward → save:start_load_kv()内等待本步 load,wait_for_layer_load()是空操作;UCMLayerWiseConnector(ucm_connector.py#L2570)语义为流水线重叠:load l0 → forward l0 → save l0 / load l1 → forward l1 → save l1 / ...,start_load_kv()只提交第一层,每个 Attention 层之前wait_for_layer_load()等待本层并提交下一层,使下一层传输与当前层计算重叠;逐层保存则在save_kv_layer()(ucm_connector.py#L2806)中提交。
每个请求的 load/save 范围在调度之后才确定,而register_kv_caches()(ucm_connector.py#L1692)注册的 tensor 布局与设备地址可供多个请求复用。完整的逐步、逐层顺序见 request lifecycle。
请求结束与异步任务回收
当 Scheduler 调用request_finished()(ucm_connector.py#L2489)时,Connector 会检查该请求是否涉及异步保存:返回True即请求引擎推迟释放对应 KV block;Worker 随后在get_finished()(ucm_connector.py#L2543)中等待相关 pending save 并上报请求 ID,引擎才能继续资源回收。注意:“允许释放缓冲区”并不等于“缓存写入成功”,失败任务同样需要完整的资源生命周期;要确保持久化成立,应参考 verify-cache 的验证流程。
四、Store 接口与工厂:引擎集成面对的统一视图
引擎集成不直接操作具体后端,而是面向UcmKVStoreBaseV1这一 Python 抽象接口(ucmstore_v1.py#L41)。接口方法构成了 Store 与连接器之间的完整契约:
| 方法 | 契约 |
|---|---|
cc_store() | 返回底层原生 Store 指针(整型);原生调用方需要有效兼容对象 |
lookup(block_ids) | 按输入顺序返回每个 block 是否存在 |
lookup_on_prefix(block_ids) | 返回最后一个连续命中的下标;首块未命中时返回-1(注意:不是命中块数) |
lookup_on_reverse(block_ids) | 从后向前扫描,返回第一个存在的 block 下标;全部缺失返回-1 |
prefetch(block_ids) | 发起预取 |
load(...)/dump(...) | 提交“张量描述”的传输,返回不透明Task |
load_data(...)/dump_data(...) | 提交“地址描述”的传输;dump_data含同步参数prerequisite_handle=0 |
check(task)/wait(task) | 轮询完成或阻塞等待;向调用方保留实现错误 |
lookup_on_prefix与lookup_on_reverse在 ucmstore_v1.py#L80-L119 有完整注释:前缀语义“停在第一个缺失块”,反向语义“停在第一个存在块”。反向查找的典型场景是混合注意力模型——全注意力块用lookup_on_prefix,Mamba 类块用lookup_on_reverse以最大化复用窗口。
Store 的构造由工厂统一完成。UcmConnectorFactoryV1(factory_v1.py#L34)以“名称 + 模块路径 + 类名”注册懒加载连接器,V1 工厂当前注册了两个公开名称(factory_v1.py#L65-L70):
UcmPipelineStore→ucm.store.pipeline.connector中的UcmPipelineStore;UcmNfsStore→ucm.store.pcstore.pcstore_connector_v1中的UcmPcStoreV1。
也就是说,公开名称UcmNfsStore解析到的是UcmPcStoreV1包装类(pcstore_connector_v1.py#L40),后者把引擎侧几何信息映射为原生PcStore.Config并调用Setup(pcstore_connector_v1.py#L43-L77),其参数键映射(io_direct→transferIoDirect、timeout_ms→transferTimeoutMs、use_gdr→transferUseGdr等)可在 pcstore_connector_v1.py#L55-L69 中查阅。与原生侧对应,ucm/store/ucmstore_v1.h中的UC::StoreV1定义了Setup、Readme、Lookup、LookupOnPrefix、LookupOnReverse、Prefetch、Load、Dump、Check、Wait等原生接口,且要求所有公开方法支持并发调用。
五、Pipeline:分级存储的组装方式
Pipeline 本身是 Store 的一种实现,而不是每个后端都必须叠加的额外层。以最常用的Cache|Posix为例:Cache拥有主机缓冲区与设备/主机传输,Posix拥有主机/文件系统 I/O——Cache负责从就绪的主机缓冲区加载,或让Posix先填充缓冲区再从文件搬到设备;保存时先等待设备计算同步,再把设备数据搬入主机缓冲区并提交文件系统写。
阶段组合不能任意拼装名称,必须使用已注册的组合。UcmPipelineStoreBuilder在 connector.py#L393-L409 中注册了下列阶段组合:
| 注册名称 | 构成 | 说明 |
|---|---|---|
Cache|Posix | Cache + Posix | 主机缓存 + 本地/挂载文件系统,推荐新部署起点 |
Cache|Ds3fs | Cache + Ds3fs | 通过 3FS 客户端做后端 I/O |
Cache|Compress|Posix | Cache + Compress + Posix | 存储前压缩(如 Tunstall 有损编码)以减小占用 |
Mooncake/Mooncake|Posix | Mooncake(+ Posix) | 共享内存池,可选文件持久化 |
Cache|Fake/Fake | Cache + Fake | 无持久化的接口验证 |
Empty/Cache|Empty | Empty(+ Cache) | 仅验证接口形态 |
Posix | Posix | 直接文件系统后端(SGLang 适配器选此路径) |
ASU、Delegator、YuanRong、YuanRong|Posix、Dram | 各自后端 | 平台/厂商专属后端 |
每个 builder 通过pipeline.Stack(stage_name, lib_path, config)依次压栈,例如Cache|Posix会先Stack("Posix", .../libposixstore.so)再Stack("Cache", .../libcachestore.so)(connector.py#L212-L221),数据传输方向由栈序决定。
健康包装层
健康包装(health wrapper)可以阻止不健康的阶段接受新操作。UCM 的 Pipeline 健康检查默认开启:10 秒间隔、3 秒超时、8 样本窗口、失败阈值 2;Posix 实现写/读/对比/删除探针(见 posix_store.cc#L129)。探针成功只代表文件系统健康;只有请求级命中和完成的 load 才能确立 KV 复用成立。引擎集成仍然负责处理 miss、传输失败与请求完成,包装层不会重试推理请求。
完整配置示例
以 vLLM 接入Cache|Posix为例,参考 pipeline.md,创建可写目录并挂载到每个需要访问的进程后,保存如下 UCM YAML:
ucm_connectors: - ucm_connector_name: "UcmPipelineStore" ucm_connector_config: store_pipeline: "Cache|Posix" store_health: enabled: true storage_backends: "/mnt/ucm-cache" io_direct: false # cache_buffer_capacity_gb: 256 # posix_capacity_gb: 1024 use_gdr: false enable_event_sync: true use_layerwise: true enable_record_traces: false use_lite: false persist_token_threshold: 0要点说明(依据 config-parameters.md):
store_pipeline仅对UcmPipelineStore生效;SGLang 在其适配器中直接选择Posix阶段,不应原样套用 vLLM YAML。storage_backends为必填,多个挂载点用冒号分隔;vLLM Connector 会在创建 Store 时按冒号切分为路径列表(ucm_connector.py#L1607-L1609)。io_direct原生 Cache/Posix 默认true(绕过页缓存);示例保留false以免覆盖 I/O 引擎。仅在io_direct: true且文件系统支持对齐 I/O 时,才可切换posix_io_engine: aio(默认psync)。timeout_ms需放在ucm_connector_config内,是 Store 任务超时(默认 30000 ms),不是 HTTP 请求超时。use_layerwise默认true,启用逐层 load/save 重叠;DeepSeek V4 系列建议false。persist_token_threshold默认0:请求长度低于该阈值时 UCM 不处理该请求。enable_event_sync默认true:把设备同步事件传给 dump 传输,确保传输只读取依赖计算完成后的数据;关闭时退化为device.synchronize()(ucm_connector.py#L2251-L2259)。
通过kv_connector_extra_config.UCM_CONFIG_FILE指向该 YAML 即可接入 vLLM。配置中的设备 ID、block 大小、tensor 布局由 Connector 在_create_store()(ucm_connector.py#L1590)中注入,不要从其他模型的 Store 测试中复制这些数值。共享实例要求模型、tokenizer、KV 布局与执行设置兼容,不兼容的配置应隔离到独立的存储命名空间。
主机内存与存储容量预算
容量字段默认注释掉时使用运行时默认值,示例中的注释值 256 并非所有模型的生效容量。从 cache_store.cc#L154-L159 看,share_buffer_enable: false会把默认容量除以 8,显式cache_buffer_capacity_gb则按<< 30覆盖默认值;初始化时还要求缓冲区数量不小于max(1024, 2 * cache_load_exclusive_buffer_number),默认独占缓冲数为 1024(cache_store.cc#L211-L219),容量过小会报出所需的最小 GiB。
| 未显式配置容量时的分配路径 | 生效默认 |
|---|---|
| 共享缓冲的原生 Cache | 256 GiB |
share_buffer_enable: false的原生 Cache | 每 Worker 32 GiB |
| 启用共享缓冲的当前 vLLM Connector | 128 GiB |
vLLM Connector 默认把share_buffer_enable设为“模型是否 MLA”;共享缓冲需要足够的/dev/shm,非共享 Worker 各自分配,主机预算需乘以本机 Worker 数。模型权重、设备 KV Cache 与其他主机分配是额外开销。
存储容量方面:posix_capacity_gb: 0表示关闭容量驱动的 GC;正值只提供容量预算,并不预留文件系统空间。vLLM Connector 把 Posix GC 交给 DP0 Scheduler(ucm_connector.py#L1660-L1672),多实例共享同一目录时应合并计算数据量并保留 Posix 协调设置。相关 GC 参数(posix_gc_trigger_threshold_ratio默认 0.7、posix_gc_recycle_percent默认 0.1、posix_gc_check_interval_sec默认 30 等)见 config-parameters.md。
启动与请求命令参考
保存上述 YAML 为/etc/ucm/ucm.yaml后,可用原 Qwen2.5-14B-Instruct 服务参数启动(--no-enable-prefix-caching为原始存储测试保留,常规部署同时使用原生前缀缓存时应移除):
export ENABLE_UCM_PATCH=1 vllm serve Qwen/Qwen2.5-14B-Instruct \ --max-model-len 20000 \ --tensor-parallel-size 2 \ --gpu_memory_utilization 0.87 \ --block_size 128 \ --trust-remote-code \ --port 7800 \ --enforce-eager \ --no-enable-prefix-caching \ --kv-transfer-config \ '{ "kv_connector": "UCMConnector", "kv_role": "kv_both", "kv_connector_module_path": "ucm.integration.vllm.ucm_connector", "kv_connector_extra_config": {"UCM_CONFIG_FILE": "/etc/ucm/ucm.yaml"} }'就绪后在另一终端运行请求负载(仅为工作负载输入示例,不代表已复现的性能结果):
vllm bench serve \ --backend vllm \ --model Qwen/Qwen2.5-14B-Instruct \ --host 127.0.0.1 \ --port 7800 \ --dataset-name random \ --num-prompts 12 \ --random-input-len 16000 \ --random-output-len 2 \ --request-rate inf \ --seed 123456 \ --percentile-metrics "ttft,tpot,itl,e2el" \ --metric-percentiles "90,99" \ --ignore-eos写入/读取验证应使用 verify-cache 的共享流程:先保存、重启、再重放;观察ucm:ucm_hit_tokens_total增长、load 任务完成无对应错误、Posix 任务活动与文件系统读取、输出与基线一致。若主机缓存已满足 load,诊断性运行可设cache_load_backend_only: true直查后端路径。收益度量应分别对比无缓存 Prefill、存储重放、热内存重放,记录外部命中 token、Posix 读字节、主机内存、TTFT 与吞吐。
六、引擎特定入口点
共同的 Store 接口并不等于各引擎有相同的钩子或配置格式。不同引擎的集成入口与关键差异如下:
| 引擎 | 入口点 | 重要差异 |
|---|---|---|
| vLLM / vLLM-Ascend | ucm/integration/vllm/ucm_connector.py | Scheduler/Worker 双角色;按布局选择直接、逐层或模型专属 Connector |
| SGLang | ucm/integration/sglang/unifiedcache_store.py | HiCache 自管主机缓存;存储适配器直接使用 Posix 阶段 |
- vLLM 侧:
UCMConnector(ucm_connector.py#L3215)读取配置并按 KV 布局、并行执行方式与use_layerwise选择UCMDirectConnector或UCMLayerWiseConnector;MLA、CP 与混合注意力等布局还涉及 rank 一致性、分片布局与模型专属保存规则,use_layerwise单独不足以确定完整路径。 - SGLang 侧:
UnifiedCacheStore实现 SGLang 的HiCacheStorage接口(unifiedcache_store.py#L19-L20),要求--hicache-mem-layout page_first,通过SglangUcmConnector.from_hicache()建立连接器与 Store(unifiedcache_store.py#L46-L70);主机缓存归属 HiCache,因此存储层直接走Posix,参见 SGLang 快速上手。
选型原则:后端扩展拥有存储资源;引擎或缓存布局扩展属于集成层。若要扩展新后端,可在 Python V1 Store(实现UcmKVStoreBaseV1并经 V1 工厂注册)、原生 Pipeline 阶段(实现UC::StoreV1并导出工厂)或“Python 包装原生库”三条路线中选择,详见 extending-store。
七、继续深入
- how caching works(缓存工作原理):block 标识符如何编码前缀上下文、lookup 预算与 load 供数、分层存储如何搬运 KV、何时值得读缓存;
- request lifecycle(请求生命周期):从启动准备到请求结束的逐步、逐层顺序;
- cache-configuration(缓存配置):NFS、3FS、Mooncake、压缩与 Pipeline 后端的选择与配置;
- extending-store(Store 扩展):Python V1 接口脚手架、原生 Pipeline 阶段与 Python 包装路径;
- config-parameters(配置参数参考):全部可选参数的默认值与约束;
- verify-cache(验证外部复用) 与 health metrics:持久化成立与后端健康的确立方式。
阅读源码时可沿此路线:从 ucm_connector.py 的UCMConnector出发,依次看UCMDirectConnector、UCMLayerWiseConnector与所选模型的专属 Connector;再读 ucmstore_v1.py 的 lookup/task 契约、pipeline 连接器 的阶段组装与 Python/原生边界,最后落到 cache_store.cc(主机缓冲等待)与ucm/store/posix/(后端 I/O)验证底层实现。
- 大模型
- 人工智能
- 缓存
【免费下载链接】unified-cache-management
Unified Cache Manager(推理记忆数据管理器),是一款以KV Cache为中心的推理加速套件,其融合了多类型缓存加速算法工具,分级管理并持久化推理过程中产生的KV Cache记忆数据,扩大推理上下文窗口,以实现高吞吐、低时延的推理体验,降低每Token推理成本。
相关推荐
UCM(Unified Cache Manager)统一 KV Cache 管理:架构解析与快速上手
UCM(Unified Cache Manager)统一 KV Cache 管理:架构解析与快速上手 Unified Cache Manager(UCM)是位于
大模型人工智能缓存Unified Cache Manager(UCM)KV Cache 统一缓存管理技术详解与实战指南
Unified Cache Manager(UCM)KV Cache 统一缓存管理技术详解与实战指南 Unified Cache Manager(统一缓存管理,
大模型人工智能缓存终极指南:Motion Canvas 字体加载策略——彻底解决 FOIT 与 FOUT 问题
终极指南:Motion Canvas 字体加载策略——彻底解决 FOIT 与 FOUT 问题 Motion Canvas 作为一款强大的代码可视化工具,让开发者
模型推理服务推理引擎人工智能大模型本地部署多模态
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考