异步加载#
概述#
本文解释了 LMCache async_loading 功能的原理、优点、与 vLLM PR 19330 的区别以及局限性。它重点介绍了 LMCache v1 与 vLLM 的集成以及内部存储管道。
此功能中组件的主要变化包括:
LMCache 异步查找客户端/服务器(基于 ZMQ)
存储管理器协调后端和并发性
缓存引擎异步 API 入口点
vLLM 适配器集成点
原理与理论#
从高层次来看,async_loading 将调度器端的查找与工作端的预取/检索解耦,允许 I/O 和计算之间的重叠,同时保持基于前缀的正确性。
调度器发送带有令牌块哈希和偏移量的查找请求。
工作端服务器在可用后端上执行分层的
batched_async_contains,并积极启动非阻塞的批量获取操作以处理命中前缀。完成情况通过
EventManager进行跟踪,以安全地将加载的内存对象返回给请求路径。带权信号量与
AsyncSerializer结合使用,通过根据块预算调整并发性来防止分配器死锁。
以下的 Mermaid 序列图展示了端到端的流程:
sequenceDiagram
autonumber
participant S as Scheduler (vLLM)
participant LC as LMCacheAsyncLookupClient
participant WS as LMCacheAsyncLookupServer (Worker)
participant SM as StorageManager
participant BE as Backends (LocalCPU/LocalDisk/FSConnector)
participant EM as EventManager
S->>LC: lookup(token_ids, lookup_id, request_configs)
note right of LC: Hashes + offsets via TokenDatabase
LC->>WS: ZMQ PUSH multipart [lookup_id, hashes, offsets, configs]
WS->>SM: async_lookup_and_prefetch(lookup_id, keys, cum_chunk_lengths)
SM->>BE: batched_async_contains(lookup_id, keys, pin=True)
alt prefix hit across tiers
BE-->>SM: num_hit_chunks (per tier)
SM->>BE: batched_get_non_blocking(lookup_id, hit_prefix)
BE-->>SM: Future[List[MemoryObj]]
SM->>EM: add_event(EventType.LOADING, lookup_id, gather_all)
SM-->>WS: send_response_to_scheduler(lookup_id, retrieved_length)
WS-->>LC: ZMQ PUSH [lookup_id, num_hit_tokens]
else cache miss
SM-->>WS: send_response_to_scheduler(lookup_id, 0)
WS-->>LC: ZMQ PUSH [lookup_id, 0]
end
架构(工作端)#
flowchart LR
subgraph Worker
direction TB
A["LMCacheAsyncLookupServer<br/>ZMQ PULL/PUSH"]
B["StorageManager<br/>Async loop (thread)"]
C["AsyncSerializer<br/>WeightedSemaphore"]
D["EventManager<br/>EventType.LOADING"]
end
subgraph Backends
E["LocalCPUBackend<br/>contains/get"]
F["LocalDiskBackend<br/>async contains/get"]
G["FSConnector<br/>remote FS"]
end
A --> B
B --> C
B --> D
B -.contains/get.-> E
B -.contains/get.-> F
B -.contains/get.-> G
style E fill:#dff,stroke:#333,stroke-width:1px
style F fill:#ffd,stroke:#333,stroke-width:1px
style G fill:#dfd,stroke:#333,stroke-width:1px
好处#
- 性能重叠
I/O–计算重叠:将查找/预取与加载解耦,使得在 vLLM 继续调度/计算的同时可以获取 KV 块。
- 鲁棒性和错误处理
事件驱动同步:
EventManager确保未来对象的安全交接,并避免线程与异步循环之间的竞争条件。背压与死锁避免:
AsyncSerializer使用加权信号量限制并发块检索,基于分配器预算,防止饥饿或分配器锁定。优雅未命中路径:当无法检索到任何内容时,立即响应
None命中令牌;工作线程快速返回,不会阻塞调度器。
与 vLLM 加载失败恢复功能的比较#
VLLM_PR_19330 引入了一个故障恢复机制,用于 vLLM 的 KV 连接器基础设施,能够优雅地处理 KV 缓存加载失败,通过自动检测失败的块加载并仅重新调度受影响的请求,从有效前缀中进行重计算。相比之下,LMCache 的 async_loading 是一个外部缓存层,具有自己的客户端/服务器、存储后端和并发控制。
限制#
仅适用于合并了 VLLM_PR_23620 的 vllm
- 后端支持限制:此功能当前需要实现
batched_async_contains的后端;仅限于少数后端,例如: LocalCpuBackendLocalDiskBackendS3ConnectorFSConnectorRedisConnector/RedisClusterConnector
- 后端支持限制:此功能当前需要实现
未来工作#
引入默认的
batched_async_contains实现,以便所有后端都可以支持async_loading。添加指标和可观察性,以跟踪异步查找请求的数量和占用的
MemoryObj实例的数量。通过传递 vLLM 前缀缓存命中令牌来改进查找框架,以便异步查找可以跳过已在 vLLM 中命中的部分加载。