s03状态与内存18 分钟阅读

Remember with KV

用缓存连接请求的执行状态

从 CacheEngine 与请求生命周期理解历史状态如何保留、定位和释放。

请求状态、已处理位置与缓存所有权必须一起维护。

01缓存把历史计算变成请求状态

后续位置需要读取已经处理过的上下文。框架不仅要保留模型所需的历史状态,还要记录它属于哪条请求、覆盖哪些位置。CacheEngine 管理具体存储,序列与块管理器维护定位和生命周期;不能只按已返回文本长度推断缓存长度。

s03_kv_cache.py
# Framework pseudocode for request-owned cache state.
state = sequence_table[request_id]
blocks = block_manager.resolve(state.block_table)
metadata = build_input_metadata(
    query_tokens=planned_tokens,
    cached_positions=state.computed_positions,
    cache_blocks=blocks,
)
worker.execute_model_step(metadata, cache_engine.cache)

# Execution consumes input positions and updates cache state.
# A selected token becomes input only if the request continues.
# Reclaim blocks only when their references are no longer needed.

02输入位置与选择结果分开记账

前向处理的是本轮输入,采样结果在之后才产生。新选出的 token 只有继续作为下一轮输入时,才会贡献对应缓存状态。draft 验证还会引入接受长度与回退位置。读框架时分别追踪计划位置、已计算位置、已接受输出和已发布结果,避免把它们合成一个计数器。

03缓存格式由模型与运行时共同约定

上游 CacheEngine 包含模型专用布局与状态管理,块管理器还要处理分配、共享和回收。不能把普通 K/V 数组的形状直接套在全部上游路径上。此处伪代码用于定位框架职责;具体格式、引用关系和有效位置应沿 cache_engine.py 与调用处核对。

TRY IT YOURSELF

动手想一想

某请求已处理一段输入、选出一个输出但尚未进入下一轮。分别标出已计算位置、已选输出和缓存覆盖范围,再加入一次 draft 拒绝。

把这个机制,加入你的工具箱。