HiCache如何支撑多并行与分布式推理

HiCache如何支撑多并行与分布式推理

在Agentic工作负载中,请求往往会反复携带很长、且大部分不变的历史上下文。Radix cache可以在GPU显存中复用前缀KV,HiCache则把这种复用扩展到主机内存和外部存储。真正进入生产环境后,缓存系统还必须同时适配多种并行与分布式推理机制,包括Context Parallelism、Pipeline Parallelism、Speculative decoding以及prefill-decode disaggregation。

本文梳理HiCache在这些场景中的核心设计:在Context Parallelism下保持统一的逻辑前缀、在Pipeline Parallelism中让各stage做出一致缓存决策、在Speculative decoding中恢复draft模型状态、用统一KV布局跨并行配置共享缓存,并在P/D分离场景中只传输缺失KV。

在生产实践中,科大讯飞Iflytek Astron MaaS团队将Pipeline Parallelism、prefill-decode disaggregation和MTP结合,用于服务GLM-5.1/5.2 CodingPlan工作负载。请求通常包含30K到200K输入token,少数可达100万token。未启用HiCache时,缓存命中率约为30%,用户需要等待较长时间;加入带外部存储的HiCache后,命中率提升到95%,median TTFT降至3秒以内。

Context Parallelism × HiCache:基于页面的KV分片

Context Parallelism会把prefill计算分发到多个rank上,但KV cache如果仍在各rank复制,就会浪费大量显存。HiCache采用基于page的KV sharding,既去除重复副本,又保留每个请求统一的逻辑视图。

统一逻辑Radix tree与页面归属

在CP场景中,每个rank维护同一棵逻辑Radix tree,并使用相同的logical page ID。以两个rank为例,偶数page归rank 0,奇数page归rank 1。这样,即使A/B/C这三个前缀页的KV实际分布在不同GPU上,任意rank命中A/B/C时,都能识别出同一组逻辑缓存页。

对N个shard rank、page大小为p个token、逻辑槽位x,HiCache使用简单算术映射确定KV位置:q = floor(x / p)表示logical cache page ID,r = q mod N表示owner rank,l = floor(q / N) * p + (x mod p)表示owner本地row。该映射不需要逐页查表。

当请求复用A/B/C并继续追加page D时,allocator会延续前缀的owner序列:0、1、0之后为1。树结构会记录这种ownership rotation,避免把不兼容的页面轮转混入同一前缀。

A logical radix tree shared by two CP ranks: logical page IDs map to rank 0 or rank 1 by q mod 2, and extending the A/B/C prefix allocates page D on rank 1.

图1:两个CP rank共享同一逻辑Radix tree,logical page ID决定页面owner,扩展A/B/C前缀时D被分配到rank 1。

逐层读取分片KV:每层一次gather

KV被分片后,单个rank的本地cache只保存完整上下文的一部分。为了让attention读取完整前缀,每个rank会在处理某一层前,把自己拥有的pages贡献给all-gather,并写入该层的临时buffer。

例如rank 0贡献A和C,rank 1贡献B和padding page。gather后的buffer按owner分组,attention通过page-table mapping读取逻辑顺序A、B、C,而不需要物理重排。系统使用两个临时scratch buffer在层间交替:当前层attention计算时,下一层的gather可以并行进行,从而把assembled KV的额外显存控制在两个layer buffer以内。

在支持的配置上,gather使用GPU copy engines而非NCCL SM kernels,减少与模型计算对SM资源的竞争。换言之,前缀命中避免了重复prefill计算,但仍需支付分布式KV gather的成本。

Each rank contributes its owned pages plus padding to a per-layer all-gather; both ranks build the same owner-ordered scratch buffer, and two scratch slots let the next layer's gather overlap with current-layer attention.

图2:每个rank贡献本层所拥有的pages,all-gather生成相同的owner-ordered scratch buffer;双scratch slot让下一层gather与当前层attention重叠。

HiCache集成:先恢复各自shard,再执行gather

HiCache在GPU与host memory之间迁移KV时,也必须保留页面归属关系。否则,恢复后的page可能落在错误rank上,导致下一次gather时无人贡献对应KV。以上述三页为例,rank 0备份并恢复A和C,rank 1备份并恢复B;即便GPU物理地址变化,owner关系也不变。

cache tree和transfer queues仍然使用逻辑索引。真正拷贝时,每个rank选择属于自己的source-destination page pairs,并翻译成本地地址。执行顺序是:先在transfer stream中恢复本地pages,再由gather stream等待该层restore-completion event,最后attention等待gather buffer完成。

Rank 0 backs up and reloads A and C, rank 1 backs up and reloads B; on each rank the transfer, gather, and compute streams run in the order restore, gather, attention.

图3:HiCache备份与恢复时保持页面owner不变;每个rank按restore、gather、attention顺序推进。

生产流量下的性能结果

评测使用GLM-5.2-NVFP4,配置为TP4/CP4、EAGLE MTP、static memory fraction 0.9。每个deployment包含两个prefill engines,每个engine运行在4张NVIDIA GB300 GPU上。对照组在GPU上复制KV,并在host memory中对MLA KV做去重;HiCache组采用CP-sharded KV。两组每个engine的目标host-cache预算均为960GB:baseline为一个去重池,HiCache为4个shard rank各240GB。

在三小时生产流量窗口内,每种配置处理约24.5K个带cache-tier归因的请求;平均输入长度为136K至137K token,总输入量差异仅1.8%。结果显示,CP-sharded HiCache把L1命中率从42.83%提升到83.31%,L2命中率从50.27%降至9.62%,总命中率保持在约93%;同时平均prefill排队时间从14.64秒降至6.42秒,forward时间从3.15秒降至2.16秒。

Token hit rates and prefill-stage means: CP-sharded KV with HiCache raises the L1 hit rate from 42.83% to 83.31%, lowers the L2 hit rate from 50.27% to 9.62%, keeps the combined rate near 93%, and cuts mean prefill queue time from 14.64 s to 6.42 s and forward time from 3.15 s to 2.16 s.

图4:CP-sharded HiCache显著提高GPU侧L1命中率,并降低prefill排队与forward耗时。

Pipeline Parallelism:让各stage保持一致缓存决策

在Pipeline Parallelism中,模型层被切分到不同stage。HiCache的原则是:所有stage遵循同一套逻辑缓存操作序列,但KV tensor只保留在各stage本地。也就是说,请求在不同时间步穿过pipeline时,各stage都执行一致的cache hit、restore、lock、unlock和eviction逻辑,只是对应的KV数据不跨stage迁移。

Four pipeline stages process request 4 at successive time steps t0 to t3, each following the same logical cache operation sequence while keeping KV tensors local to the stage.

图5:四个pipeline stage在连续时间步处理同一请求,各stage执行相同逻辑缓存操作,但KV保持本地。

难点在于异步传输完成时间可能不同。如果PP0只消费A,而PP1消费A和B,各stage的lock状态和eviction资格就会分叉,最终造成缓存一致性问题。HiCache通过pp_sync同步消费长度:例如PP0选择n = 1并通过pp_sync传递,PP1也只消费A,把B继续留在队列中;PP2则等待本地A就绪后再消费。

Failure case: PP0 consumes A while PP1 consumes A and B, so locks and eviction eligibility diverge. Fix: PP0 picks n = 1 and passes it through pp_sync; PP1 consumes A and keeps B queued, and PP2 waits for its local A before consuming it.

图6:如果不同PP stage消费不同前缀,lock与eviction状态会分叉;pp_sync强制各stage消费同一长度。

此外,后台线程会统计各rank的最小hit长度和已完成长度,并发布ACK,例如先发布ACK(4)再发布ACK(6)。PP0消费ACK(4)后停止等待,PP1通过pp_sync跟随PP0消费同一ACK,而将ACK(6)保留在队列中。这样可以在异步restore环境下维持pipeline各stage的缓存状态一致。

Background threads compute the minimum hit and completed lengths across ranks and publish ACK(4) then ACK(6); PP0 consumes ACK(4) and stops waiting, and PP1 follows PP0 through pp_sync, consuming the same ACK(4) and leaving ACK(6) queued.

图7:后台线程发布ACK,PP stage通过pp_sync消费一致的确认长度,避免缓存决策漂移。

Speculative decoding:同时恢复draft模型状态

在Speculative decoding或MTP中,系统不仅需要target model的KV cache,还需要draft model相关状态。HiCache因此要在恢复target cache的同时,恢复draft模型所需的cache state。

实现上有两种布局。第一种是packed integration:把draft layers追加到target KV和indexer host pools之后,形成统一池。第二种是sidecar integration:draft使用独立pool,但继承target KV的索引关系。两种方式都可以把host slots 7、12、19恢复到GPU slots 42、8、27,区别在于draft状态如何组织与寻址。

Two layouts for draft cache state: packed integration appends draft layers to the target KV and indexer host pools, while sidecar integration keeps separate draft pools that inherit indices from target KV; both restore host slots 7, 12, and 19 into GPU slots 42, 8, and 27.

图8:draft cache state可采用packed或sidecar布局,二者都能随target cache一起恢复。

统一KV布局:跨并行配置共享缓存

生产环境中,不同worker可能使用不同TP/PP配置。HiCache通过统一KV layout,把外部存储中的KV组织为可被兼容并行配置读取的对象,减少因部署形态变化造成的cache失效。

例如,一个TP4/PP2 writer会把每个rank的一段KV写成8个共享L3对象;一个TP2/PP1 reader读取时,可以一次组装4个chunk。扩展后的对象把heads 4–5在layers 30–59的K和V组织为连续range,从而让不同并行切分方式在兼容条件下复用同一份存储KV。

A TP4/PP2 writer stores one chunk per rank into eight shared L3 objects, which a TP2/PP1 reader assembles four chunks at a time; the expanded object holds K and V for heads 4–5 across layers 30–59 as one contiguous range.

图9:统一KV layout支持TP4/PP2写入、TP2/PP1读取,在兼容配置间共享外部KV对象。

Prefill-decode disaggregation:只传输缺失KV

在P/D分离架构中,prefill worker负责计算prefill KV,decode worker负责后续生成。如果decode侧已经持有部分前缀,HiCache会优先复用decode本地缓存,包括GPU resident cache和host cache,prefill侧只需要通过P/D链路传输缺失后缀。

以12K-token prompt为例,可拆为三个4K span:A已在decode GPU上,B可从decode host pool恢复,只有缺失的C需要从prefill worker跨P/D链路传输。这样既减少网络传输,也降低prefill到decode的交接延迟。

A 12K-token prompt split into three 4K spans: A is resident on the decode GPU, B is restored from the decode host pool, and only the missing suffix C crosses the P/D link from the prefill worker.

图10:P/D分离下,decode侧优先复用本地前缀,prefill只传输缺失KV后缀。

调试:用rank_consensus_checker定位不一致

多并行系统中,最难排查的问题往往不是单个rank失败,而是不同rank对缓存状态的判断不一致。HiCache提供rank_consensus_checker来定位这类问题,包括hit length不一致、restore完成状态不一致、lock/unlock顺序不一致、eviction资格分叉,以及PP ACK消费不一致等。

总体来看,HiCache把单机Radix cache扩展为面向生产分布式推理的多层缓存系统:在GPU、host memory和外部存储之间迁移KV,同时保持CP、PP、Speculative decoding和P/D分离下的逻辑一致性。对于长上下文Agentic应用,这种能力直接转化为更高命中率、更低TTFT和更稳定的服务成本。

本文来自 LMSYS 博客,赢政天下(winzheng.com)进行了全文翻译。 点击这里查看原文 如果转载中文,请注明出处,谢谢支持!