深度解读 📅 2026-10-28 ✍️ MagicNetWorld 编辑部

8 卡 TP 下的 KV 缓存里只有 12.5% 是唯一数据:UlaCache 用一张逻辑地址表,把稀疏读取、TP 复制与 GPU/CPU 分层收进同一个地址空间(arXiv 2610.29820 精读)

稀疏注意力把每步要读的 KV 从「全长」降到「几千条」,但没有降低必须留下的历史量;容量又直接决定能同时解码多少请求。Scitix.AI 的 UlaCache(arXiv 2610.29820v1,2026-10-21 提交,cs.DC)给出的办法是给每个 KV 条目发一个稳定的逻辑地址,让数据在 GPU 池、同组其它卡与 CPU 池之间随便搬而引用不变。论文自己给的三个动机数字是:8 卡 TP 下历史分配只有 12.5% 是唯一数据(论文 Figure 2a,MLA 复制)、HiSparse 方案 53.3M 个物理槽只装 30.0M 个唯一历史位置(论文 Figure 2b)、固定每请求配额的影响是:8×B300、DP、开投机解码、BS1 时,HiSparse 的 TPOT 比 GPU 常驻的 SGLang 高 23.5%(论文 §2.2.2)。开启投机解码、GPU 与 CPU 预算对齐时,论文报告峰值解码吞吐相对 HiSparse 为 1.16 倍(DP)与 1.70 倍(TP)于 8×H200,1.73 倍(DP)与 2.51 倍(TP)于 8×B300。本文没有复现实验,所有性能数字都是论文口径的转述,机制推导与容量换算为本文自行推导。

KV 缓存稀疏注意力长上下文推理SGLangMLA显存容量规划

除另行标注外,本文引用的外部事实与页面核验均以 2026-10-28(北京时间)为时点。文中凡出自论文、官方文档或论文所引一手材料的数字,一律标出编号 [1]…[8];凡本文按公式自己算出来的数字,一律标「本文自行推导」并写清假设与中间值。本文没有任何端到端实测:没有 8 卡机器,也没有跑 GLM-5.3。所有关于吞吐、显存与并发的数字都是论文报告的数值转述,或按公开常量复算的量级,不是我在某张卡上量出来的。

一、先给直觉:稀疏注意力省的是「读」,不是「存」

一句话版本:稀疏注意力把「每次要看多少历史」砍下来了,但没有把「必须留多少历史」砍下来。 推理系统真正的瓶颈由此从算力换成了容量——而容量决定了你同时能让多少条请求一起解码,并发又决定了吞吐。

不严谨地打个比方。一个图书馆管理员每次回答提问只需要翻 3 本书(稀疏注意力:读取量小),但为了随时可能被问到,他必须把 6 万本书全部保留在馆里(存储量不变)。更糟的是:如果他手里有 8 个分馆,每个分馆都备了同一套书(并行复制),那 8 个分馆的书架上其实有 7/8 是重复的;如果他还把一部分书同时放在地下库和阅览室(GPU/CPU 副本),那地库的那份和阅览室的那份也是同一本书的两份拷贝;最后如果规定「每位管理员只能占用 200 个书架位」(固定每请求配额),那么即使阅览室空着大半,他也用不上。

UlaCache 要解决的就是后面三件事。它做的动作听起来很朴素:给每本书编一个永久书号(逻辑地址),书搬到哪个馆、哪个书架都不改书号,只改一张「书号→书架」的登记表。 论文把这个叫统一逻辑地址空间(unified logical address space)[1]。

二、算一笔账:读取量、常驻量与两者的脱节

设某个 token 在某一层的 KV 占用为 skvs_{kv} 字节,一层里索引器(indexer,每步对历史位置打分、取 top-k 送进注意力算子的轻量选择模块)在本步选中的历史位置数为 kk,历史长度为 LL。那么同一步里,「读多少」和「必须留多少」是两个量:

Rstep≈k⋅skv,Chist≈L⋅skv+CidxR_{step} \approx k \cdot s_{kv}, \qquad C_{hist} \approx L \cdot s_{kv} + C_{idx}

其中 CidxC_{idx} 是索引器自己那份选择状态的开销,论文把它与 KV 记录分开存放 [1]。

两者的比例就是稀疏度:

ρread=kL\rho_{read} = \frac{k}{L}

论文的负载是 64K–128K 输入 token 的长上下文请求 [1];HiSparse 论文里说每一步只读「几千条」选中的 KV [2]。取 k≈2000k \approx 2000 到 40004000、L=65536L = 65536 到 131072131072,本文自行推导出 ρread\rho_{read} 大约落在 1.53% 到 6.1% 之间。

也就是说:算力侧的读取量因此减少了约 93.9% 到 98.5%(本文自行推导:用 1−k/L1 - k/L 在 k=2000–4000、L=65536–131072 两端取值),而存储侧的常驻量一点没动。 这不是 UlaCache 论文的发明,是稀疏注意力这条技术路线本来的处境;UlaCache 的贡献在于承认「存储量不变」之后,去问「那这份不变的存储能不能被更省地摆」。

为什么存储量重要到值得专门做一套系统?因为并发。一份粗略的容量约束是:

Nmax≈⌊Mgpu−Mweights−MwsL⋅skv+Cidx⌋N_{max} \approx \left\lfloor \frac{M_{gpu} - M_{weights} - M_{ws}}{L \cdot s_{kv} + C_{idx}} \right\rfloor

MgpuM_{gpu} 是单卡显存,MweightsM_{weights} 是权重占用(与 batch 无关),MwsM_{ws} 是 workspace。分子被权重吃掉一大块之后,剩下的每一条并发请求要按「全历史」付费。这条式子解释了为什么长上下文推理的吞吐问题,本质上是容量问题而不是算力问题。

三、三笔容量浪费:复制、副本、配额

UlaCache 论文的动机章节(§2.2)实际上列了三笔彼此独立的浪费。我把它们放在一张表里对照,这样后面讲机制时能一一对上。

浪费来源论文给的证据具体损失UlaCache 的对应机制
TP 下的 MLA 复制8 卡 TP 时,SGLang 与 HiSparse 的历史分配只有 12.5% 存的是唯一历史,其余 87.5% 是副本 [1]8 卡合计的可用历史容量被压到理论值的 1/8逻辑地址把历史切片分布到各卡,计算卡只把「选中的那份」取进本地 buffer
GPU 与 CPU 的同一份历史双存HiSparse 分配 30.0M 个 CPU 槽 + 23.3M 个 GPU 槽 = 53.3M 个物理槽,但只装了 30.0M 个唯一历史位置 [1]有效唯一容量只占物理槽的 56.29%(本文自行推导:30.0 / 53.3)GPU 池与 CPU 池进同一个地址空间,GPU 槽存的是「另一段历史」而不是「同一段的拷贝」
固定每请求缓存配额8×B300 DP + 投机解码、BS1 时 GPU 容量其实装得下全部活跃历史,但配额仍然只留一部分,导致 TPOT 比 GPU 常驻的 SGLang 高 23.5% [1]空闲显存不可被活跃请求使用,低并发时反而更慢GPU 池由所有请求共享,PB-LRU 按最近使用程度调度,配额随活跃请求数自然伸缩

第一笔值得展开,因为它是 MLA 的结构性后果,而不是实现缺陷。

Multi-head Latent Attention(MLA)把 KV 压缩成一份跨头共享的潜向量表示 [3]。普通多头注意力的 TP 是按头切分的:第 r 张卡算第 r 组头,K/V 按头切分,本来就切得开。但 MLA 的那份共享表征不随头切分——每张参与 TP 的卡都要拿到完整的那一份,才能算自己那组 query 头 [1][8]。于是复制率是:

ηreplica=P−1P\eta_{replica} = \frac{P-1}{P}

P=8P=8 时就是 87.5%,剩下 12.5% 才是唯一数据——这正是论文 Figure 2(a) 的数字 [1]。这部分浪费与稀疏注意力无关,是「用 MLA + 头切分 TP」这个组合自带的账单。

第二笔的形态更微妙:HiSparse 的设计是「完整历史放 CPU,GPU 只留一份固定大小的缓存副本」[2]。它的优点是能服务超出显存容量的上下文,但 GPU 里那 23.3M 个槽存的是 CPU 那份历史的拷贝,不增加唯一历史容量。有效容量占比是:

μunique=CuG+Cu\mu_{unique} = \frac{C_u}{G + C_u}

Cu=30.0C_u = 30.0M、G=23.3G = 23.3M 时,μunique=56.29%\mu_{unique} = 56.29\%(本文自行推导)。这也是论文 §2.2.1 的核心论点:加 CPU 前缀缓存能提高复用率,但不减少活跃历史占用的 GPU 槽;加 GPU 缓存能减少搬运,但不增加唯一历史位置。

第三笔是纯策略问题。给每个请求一个固定配额,好处是把显存占用锁死、把风险隔离;代价是低并发时闲置显存用不上。论文的实测口径很硬:在 8×B300、DP、开启投机解码的条件下,BS1 时全部活跃历史其实装得进 GPU,但 HiSparse 的每请求 buffer 仍只保留配额,结果是 TPOT 比 GPU 常驻的 SGLang 高 23.5% [1]。也就是说,容量明明够,却因为「谁都不许动别人的份额」而多跑了一趟 CPU→GPU。

为了不让三笔浪费混在一起看,先给一张因果图。它们的共同出口都是「有效唯一容量」,而有效唯一容量决定准入并发,准入并发决定峰值吞吐。

flowchart LR
  W1["TP 与 MLA 复制:8 卡只有 12.5% 唯一"] --> CE["唯一历史容量"]
  W2["GPU 与 CPU 双存:53.3M 槽装 30.0M 唯一"] --> CE
  CE --> AD["可准入的并发请求数"]
  AD --> TP2["峰值解码吞吐"]
  W3["固定每请求配额:空闲显存不可借用"] --> HP["GPU 池命中率下降"]
  HP --> TR["每步搬运量上升"]
  TR --> LT["TPOT 上升"]
  LT --> TP2
  SP["稀疏注意力只降低每步读取量"] -.->|"不改变"| CE

这张图想说明的是两条不同的路径:复制与双存走「唯一历史容量 → 准入并发」,固定配额走「GPU 池命中率 → 每步搬运量 → TPOT → 吞吐」。论文把前者放在 §2.2.1(唯一历史容量)、后者放在 §2.2.2(固定配额导致额外传输)分别论证,我在上面那张表里并排只是为了对照,它们不是同一个口径:一个决定能同时装下多少条请求,一个决定每条请求每步要搬多少。稀疏注意力那条虚线指向的是「每步读多少」,它也不进入容量这一列。

为什么不能靠「加大 batch 摊薄」绕过这一列。 权重占用 MweightsM_{weights} 与 batch 无关,所以直觉上 batch 越大越划算;但每加一条请求就要多留一份全历史,∂Nmax/∂(Lskv)<0\partial N_{max} / \partial (L s_{kv}) < 0。当单价(L⋅skvL \cdot s_{kv})很大时,能摊薄的东西没变多,能被摊薄的基数却涨得很快——这就是为什么长上下文服务的成本曲线对容量特别敏感,而对算力不那么敏感。

一个容易犯的误读:「读取量省了九成」不等于「成本省了九成」

这是本文最想提前拆掉的一个误解。把一次 decode 步的成本粗分成三块:

Tstep≈Tattn⏟∝ k+Tio⏟∝ (1−heff) k skv/Bfetch+Tfixed⏟权重访存、通信、调度T_{step} \approx \underbrace{T_{attn}}_{\propto \, k} + \underbrace{T_{io}}_{\propto \, (1-h_{eff})\, k\, s_{kv} / B_{fetch}} + \underbrace{T_{fixed}}_{\text{权重访存、通信、调度}}

式中记号就地定死:kk 是每步选中的历史位置数,skvs_{kv} 是单 token 单层的 KV 字节数,heffh_{eff} 是「取数时已在本地命中、不必再搬的比例」(本文记号;§四 会把它拆成本地 buffer 与共享池两层),BfetchB_{fetch} 是取数带宽(本卡 GPU、组内 peer GPU、CPU 三种来源带宽不同,这里统一记一个符号)。稀疏注意力压的是第一块(kk 而不是 LL),UlaCache 压的是第二块(把 heffh_{eff} 抬高),而第三块(每步都要把权重从 HBM 搬到计算单元、跨卡 all-reduce 的通信、调度开销)与长度几乎无关、也不随稀疏度下降。

  • 当 LL 很大而 kk 很小时,第一块本来就小,TfixedT_{fixed} 占比升上来——这时候继续优化注意力读数的边际收益很低,容量(能不能多装请求)才是吞吐的关键变量。
  • 当 LL 不大时,全历史本来就装得下,稀疏注意力与分层缓存都赚不到什么,直接用 GPU 常驻最省事。

换句话说,「省了读取量」直接影响的是单步延迟,「省了容量」直接影响的是并发;而峰值吞吐 = 单步效率 × 并发,多数长上下文服务里后者是主导项。这也解释了论文为什么把评估重心放在准入并发与峰值吞吐,而不是每步延迟。

四、符号与术语约定

后面到处要用这些记号,先把它们钉死。

记号含义论文出处
PPTP 参与卡数(本文例子取 8)§4.1
GrG_r第 r 个存储 rank 的 GPU KV 池槽数;一个槽装一个 token 的一份完整 KV 表征(MLA 下含压缩潜向量,论文 §4.1 原文为 each slot stores the complete KV representation for a token)§4.1
CrC_r第 r 个存储 rank 的可选 CPU KV 池槽数§4.1
tt逻辑 KV 地址,标识「哪个 token 的历史」,与物理位置无关§4.1
SS一次稀疏选择返回的逻辑地址集合,大小记为 kk§4.3
BbufB_{buf}TP 计算卡上的本地 GPU buffer(缓存的副本;DP 模式没有这一层)§4.3
hbufh_{buf}本地 buffer 命中率,∣S∩Bbuf∣/k\lvert S \cap B_{buf} \rvert / k本文定义
hpoolh_{pool}共享 GPU 池的命中率,即选中地址里有多大比例驻留在 GPU 池而不是 CPU 池本文定义
skvs_{kv}单个 token 单层的 KV 字节数本文定义
PB-LRUParallel Bucketed LRU,按「最近被访问的轮次」分桶的近似 LRU§5.1
nbn_bPB-LRU 每个层组的 recent 桶个数(论文记为 B,本文改记 nbn_b,以免与本地 buffer 的 BbufB_{buf} 和带宽 BfetchB_{fetch} 混用)§5.1
桶 / cold 桶记录最近 nbn_b 轮访问成员的位图;cold 桶装「最近窗口内未被访问」的槽§5.1

三个术语需要一句话定义,避免后文歧义:

  • DP(data parallel)注意力:每张卡处理不同请求,各自在本地存自己那些请求的历史;容量按请求分派,其余卡的空闲槽对这条请求不可用 [1]。
  • TP(tensor parallel)注意力:多张卡共同算同一条请求的注意力,历史被切分到不同卡上;MLA 下共享表征会被复制(见 §三)。
  • 提升(promotion):把一条选中的、目前驻留 CPU 池的 KV,搬进该 rank 的 GPU 池,再从 GPU 池读给注意力算子 [1]。

五、统一逻辑地址空间:把「门牌号」和「住址」分开

这是全文的核心抽象,也是论文标题的由来。做法本身只有三句话:

  1. 推理引擎只使用逻辑地址分配 KV、标记 token、发起稀疏选择;
  2. UlaCache 维护「逻辑地址 → 当前物理位置(哪张卡、哪个槽、GPU 还是 CPU)」的映射;
  3. KV 位置变化时只改映射,逻辑地址不变 [1]。

听起来像一层簿记,但它带来的直接后果是:迁移、淘汰、跨卡取数全都变成「改表」,而不是「改引用」。 推理引擎的 request-to-token 映射、索引器的选择结果、注意力算子拿到的地址,全程不需要跟着数据搬家而重写。

5.1 DP:地址空间就是本卡的池

DP 模式下每张卡自建一个地址空间,覆盖自己的 GPU 池与(可选的)CPU 池,容量是:

CapDP=Gr+CrCap_{DP} = G_r + C_r

请求在负责它注意力计算的那张卡上分配历史 [1]。此时地址解析很直白:命中 GPU 就直接读,落在 CPU 就先提升进 GPU 池再读。

5.2 TP:把各卡池子聚成一个地址空间

TP 模式下,P 张卡的池子合成一个对组内所有计算卡可见的分布式地址空间。聚合后的 GPU 容量是:

CapTP=∑r=0P−1GrCap_{TP} = \sum_{r=0}^{P-1} G_r

论文给的分布规则很干净:对 MLA 这种「每 token 一份完整共享表征」的布局,逻辑地址 tt 落到

rank(t)=t mod P,ℓ(t)=⌊tP⌋rank(t) = t \bmod P, \qquad \ell(t) = \left\lfloor \frac{t}{P} \right\rfloor

也就是第 t mod P 张卡上的第 ⌊t/P⌋ 个本地逻辑位置 [1]。不开 CPU 存储时,这条规则直接决定 GPU 槽位;开了 CPU 存储,映射再把「本地逻辑位置」解析到当前的 GPU 槽或 CPU 槽,迁移时只更新映射。

这三行公式是整篇论文里最省纸、也最值钱的地方。 它把「TP 下的历史必须复制 P 份」变成了「历史切成 P 份,计算卡按需取自己缺的那份」。前面那 87.5% 的副本浪费,就是在这里被消掉的来源——当然,代价是计算卡要跨卡取数。

flowchart LR
  L["逻辑地址 t 稳定不变"] --> M["地址映射表"]
  M --> G0["GPU 0 池第 k 槽"]
  M --> G1["GPU 1 池第 k 槽"]
  M --> C0["CPU 池第 k 槽"]
  G0 --> A["计算卡本地 buffer"]
  G1 --> A
  C0 --> P["先提升进该 rank 的 GPU 池"]
  P --> A
  A --> ATT["注意力算子读取"]

这张图想说明的是:逻辑地址是唯一的「名字」,它下面挂着三个可能的位置;数据搬家只改名字到位置的连线,读数据的那一侧(buffer 与注意力算子)看到的接口不变。

5.3 为什么这层抽象能顺带省掉管理开销

论文提到一个不明显的好处:在 TP 模式下,计算卡会把「之前取过、且这次仍被选中」的 KV 缓存在本地 GPU buffer 里,只搬缺的那些;对共享同一份稀疏选择结果的多个层,UlaCache 把「地址查找、去重、槽位分配」做一次、复用整组层,只让每层各自搬自己的数据 [1]。

这两条都把「每步的管理操作数」从「与选中数 × 层数成正比」压到「与选中数成正比」。第 78 层的注意力不必重新做一遍第 3 层已经做过的地址解析——它只需要按同一份计划搬自己的那份字节。

六、访问路径:一次稀疏选择要走的三道门

6.1 DP 一条直线

DP 模式最短:稀疏选择返回逻辑地址 → 解析到本卡物理槽 → CPU 上的先提升进 GPU 池 → 注意力直接读 GPU 池 [1]。没有跨卡,也没有 buffer 这一层(论文明确说 DP 模式直接读 GPU 池、不分配这个 buffer)。

6.2 TP 三道门:命中、本地取、跨卡取

TP 模式下每次选择都要过三道门,次序固定:

  1. buffer 命中:本地 buffer 里已有这个逻辑地址的拷贝 → 直接用,不产生任何传输;
  2. 本地取:数据在本卡 GPU 池 → 搬进 buffer;
  3. peer 取:数据在组内其它卡的 GPU 池 → 通过 CUDA IPC 搬进 buffer [1]。

论文 Figure 4 给了一个 2 卡的小例子:GPU 0 选中逻辑地址 {2, 4, 5},其中 2 是 buffer 命中、4 从自己的池取、5 从 GPU 1 的池取。这个例子小到可以手算,但把三种情形一次讲完了。

buffer 的关键性质是:它的容量与保留历史长度无关,且换掉 buffer 里的副本不影响存储池里的那份历史 [1]。所以 buffer 是纯加速层——它只影响「搬多少」,不影响「能留多少」。

6.3 计划复用与预取

对多层共享选择结果的模型,论文把访问计划(哪些地址缺、各自去哪个槽)做一次、整组层复用,每层只按计划搬自己的 KV;同时用一个独立的 CUDA stream 预取,让搬运与计算重叠,并用 stream 依赖与 CUDA event 保证「源写完成 → 预取 → 注意力读」的次序,以及 buffer 槽在注意力读完之前不被复用 [1]。

6.4 传输量公式,以及它为什么是这套设计的天花板

把一次选择要搬的字节数写出来:

Vstep=(k−∣S∩Bbuf∣)⋅skv=(1−hbuf)⋅k⋅skvV_{step} = \left( k - \lvert S \cap B_{buf} \rvert \right) \cdot s_{kv} = (1 - h_{buf}) \cdot k \cdot s_{kv}

搬这些字节的时间(BfetchB_{fetch} 为对应的取数带宽——来源可能是本卡 GPU 池、组内 peer GPU 池或 CPU 池,三者带宽不同,这里统一记一个符号)是:

Tio=VstepBfetch=(1−hbuf)⋅k⋅skvBfetchT_{io} = \frac{V_{step}}{B_{fetch}} = \frac{(1-h_{buf}) \cdot k \cdot s_{kv}}{B_{fetch}}

这里必须把两层命中率分清,否则很容易把两件事混成一件:

  • hbufh_{buf} 是计算卡本地 buffer的命中率,只出现在 TP 模式(论文 §4.3 明确 DP 不分配这个 buffer);
  • hpoolh_{pool} 是共享 GPU 池的命中率,由池容量与替换策略(PB-LRU)决定,DP/TP 都有。

两者共同决定一次选择要搬多少:hbufh_{buf} 决定「哪些还得取」,hpoolh_{pool} 决定「取的时候是不是还得从 CPU 捞」。论文的 Figure 10 报的是后者(8×H200、DP 下的 GPU 命中率),不能拿去解释前者的行为。

一个好实现的全部努力,都在这个式子的三个变量上:降 kk(模型侧稀疏度,系统动不了)、把 1−hbuf1-h_{buf} 与 1−hpool1-h_{pool} 压低(缓存策略与容量,PB-LRU 干这个)、把 TioT_{io} 藏进计算(预取与 stream 重叠)。论文的 HiSparse 对照里说得很直接:地址解析(resolution)机制本身不带来可测的每 token 开销,host-device IO 是有界驻留的唯一代价 [2]。

也就是说,这类系统的加速比本质上受「每步计算时间 vs 每步 IO 时间」的比例约束。共享 GPU 池把 h 抬高,是因为它让活跃请求能用上别的请求暂时不用的槽——这是 UlaCache 相对固定配额方案最实质的差别。

6.5 一个可以手算的传输量例子

为了让上面的式子不只是符号,做一个数量级推演。假设(以下全部为本文自行推导的假设值,不是论文给的配置):

  • 历史长度 L=65536L = 65536,稀疏选择 ∣S∣=2048|S| = 2048;
  • 单 token 单层 KV skv=80s_{kv} = 80 KiB(这是一个「量级合理」的假设,真实值与模型层数、头数、精度绑定,本文不去拟合任何具体模型);
  • 假设每步只涉及一层(只是为了让数字可读,真实一层一层的量按层数线性累加);
  • H2D 有效带宽按 24 GiB/s 取(同样只是数量级假设)。

那么一次全 miss 的传输量是:

Vmiss=2048×80 KiB=160 MiBV_{miss} = 2048 \times 80\ \text{KiB} = 160\ \text{MiB}

对应时间约 160/1024/24≈0.00651160 / 1024 / 24 \approx 0.00651 秒,即约 6.51 毫秒。而命中率从 0 抬到 0.9 时:

V0.9=(1−0.9)×160 MiB=16 MiB,T0.9≈0.65 msV_{0.9} = (1 - 0.9) \times 160\ \text{MiB} = 16\ \text{MiB}, \qquad T_{0.9} \approx 0.65\ \text{ms}

结论只有一个:h 从 0 到 0.9 就是 10 倍的时间差,而 h 主要由「能留多少 KV」决定。 这正好解释了为什么论文把「共享池 + PB-LRU 的命中率」放在评估的中心位置(Figure 10),也解释了为什么它反复强调自己的赢面在「更大准入并发」而不是「同 batch 下每步更快」。

反过来说,如果 H2D 带宽足够大、或者每步计算时间远大于 TioT_{io},那么这套机制的收益会被预取与重叠吃掉——论文用独立 CUDA stream 做预取,本质就是把这个比值往「被隐藏」那一侧压 [1]。

七、PB-LRU:把 LRU 做成位图并行

7.1 结构与更新

PB-LRU 用「按最近被访问的轮次分桶」来近似 LRU:每个层组维护 nbn_b 个 recent 桶加一个 cold 桶,当前桶每个调度轮前进一步;桶被复用作当前桶之前,它剩下的成员整体挪进 cold 桶 [1]。注意这一步只改元数据:这些槽里的 KV 仍然留在 GPU 上。

每个桶用一张位图表示,一个 GPU 物理槽一位;每个槽还记着自己的桶号,所以一次访问可以清掉它原来的位、再在当前桶里置位——访问只碰被引用的那几个槽,不扫描整个 GPU 池 [1]。这跟朴素 LRU 每次都要在全池里找最久未用的那一项,是两种量级的做法。

flowchart TD
  NEW["新请求的 KV 到达 GPU 池"] --> FREE{"有空闲槽"}
  FREE -->|有| USE["直接用空闲槽"]
  FREE -->|无| COLD{"cold 桶有位"}
  COLD -->|有| EV1["从 cold 桶选淘汰槽"]
  COLD -->|无| OLD["从最旧 recent 桶往前选"]
  OLD --> EV2["跳过当前桶"]
  EV1 --> X["被替换数据回写源 CPU 槽"]
  EV2 --> X
  X --> MAP["数据搬完后更新地址映射"]
  USE --> MAP

这张图想说明的是淘汰的优先次序:空闲槽 → cold 桶 → 从最旧到最新的 recent 桶,当前桶永远排除在外,因为当前桶装着这次访问正在用的数据。

7.2 为什么「当前桶不参与淘汰」是必要条件

当前桶里的成员正是这一轮刚被选中的槽。如果允许从当前桶淘汰,就可能把「这次注意力正要读的 KV」当成受害者换出去,然后在同一步里又把它取回来——一次自造的抖动。论文把「保护当前注意力计算所需的条目」写成了设计的显式约束 [1]。

7.3 复杂度与实测

朴素实现的代价要分两种操作说清:访问本身只是更新被引用槽的时间戳,不是全池扫描;需要替换且没有空闲槽时,它才通过 pool-wide scan 选出受害槽,单次受害槽选择是 O(G)O(G)(论文 §6.5 的原话是 “under replacement pressure … naive LRU’s pool-wide scan”)[1]。PB-LRU 把访问侧压到只碰被引用的槽(O(k)O(k)),把替换侧交给位图与分桶,额外代价在桶轮转:轮转要处理过期桶的成员,最坏情况可以覆盖整个池 [1]。摊到 nbn_b 轮上,平均每轮约 O(G/nb)O(G/n_b):

Tnaivevictim∼O(G)(仅在需要替换时),Tpb∼O(k) 每次访问+O(G/nb) 每轮摊还T_{naive}^{victim} \sim O(G) \text{(仅在需要替换时)}, \qquad T_{pb} \sim O(k) \text{ 每次访问} + O(G/n_b) \text{ 每轮摊还}

实测上论文报了三个数:替换压力大、batch 较大时,PB-LRU 的调度时间比朴素 LRU 快 1.5 到 2.3 倍;替换压力小时朴素 LRU 反而更快,因为 PB-LRU 仍要维护桶元数据;两者命中率相差 小于 0.10 个百分点,说明这种近似没有牺牲复用 [1]。

我特意把「小压力下反而更慢」放在这里,因为这是所有近似结构共有的代价:你用常数开销换掉了与规模成正比的扫描。 规模不够大时,常数就是净亏。

7.4 三种替换策略的对照

把论文里出现过的三种做法并排放,差异一眼能看清(其中「固定配额」是 HiSparse 的做法,另外两种是论文的对照组):

维度朴素 LRU(全池扫描)固定每请求配额PB-LRU(论文方案)
谁能用哪些槽全池共享每个请求只能用自己的配额全池共享,按最近访问决定
每次访问的管理开销需要找出最久未用项,约 O(G)几乎为零(配额固定)只碰被引用的槽,O(|S|)
额外的周期性开销无无桶轮转,最坏 O(G),摊到 nbn_b 轮约 O(G/nbn_b)
命中率精确维护 LRU 顺序;命中率不保证全局最优(离线最优是 OPT/Belady)受配额上限压制,低并发时白丢闲置容量与朴素 LRU 差小于 0.10 个百分点 [1]
大 batch 下调度时间基线—快 1.5–2.3 倍 [1]
小替换压力下更快(时间戳更新最便宜)论文未测调度时间,机制上无需做替换决策更慢(仍要维护桶元数据)[1]
主要失败模式替换压力大时受害槽选择的全池扫描吃掉解码时间低并发时空闲显存用不上极端轮转下管理开销上升,论文未给实测调度时间上界

这张表想说明的是三者不是「谁更先进」的关系,而是三种不同的取舍点:一个精确但贵,一个便宜但僵,一个近似且弹性。论文选第三个,是因为它的目标负载(长上下文、大并发)恰好落在「规模大到扫描成为瓶颈、又不希望配额僵化」的那一段。

八、迁移顺序:为什么必须「先搬数据、后改映射」

论文 §5.2 有一句容易被读过去、但决定正确性的话:UlaCache 先搬数据,再更新地址映射,映射更新完之后才发完成信号,注意力与 buffer 取数都等这个信号 [1]。

反过来做会怎样?如果先把映射改成「目标 GPU 槽」,那么在这段窗口里到达的任何访问都会解析到一个数据还在路上的位置——读到的是槽里的旧内容。这不是崩溃,是静默的错误结果,比崩溃难查得多。

同一个细节设计里还有两个点:

  • 被替换的数据回写到源 CPU 槽:GPU 槽被新数据占用时,原来那份 KV 搬进「新数据刚空出来的那个」CPU 槽,从而不需要为被替换数据额外分配 CPU 空间 [1]。这相当于把交换做成原地互换,CPU 侧不涨。
  • 只有空目标才做单程拷贝:目标 GPU 槽本来就空,那就只做一次 CPU→GPU 拷贝,源 CPU 槽在映射更新后释放 [1]。

对做系统实现的读者,这三条合起来是一句工程经验:「映射」是这套系统的单一真相源,所以它必须最后写。 谁先写它,谁就把「数据未就绪」这个窗口暴露给了所有读者。

九、实测:那四个倍数是在什么条件下测的

论文把 UlaCache 实现在 SGLang 里,用 GLM-5.3、FP8 权重与 KV、BF16 激活,在 8×H200 与 8×B300 上评 DP 与 TP 两种注意力并行,各配「开/不开投机解码」[1]。设置如下:

项目设置(论文 §6.1)
模型GLM-5.3;FP8 权重与 KV 缓存,BF16 激活
平台8×H200、8×B300
CPU 预算每 GPU 128 GB(H200)、192 GB(B300)
GPU 常驻预算B300 每 GPU 272 GB 的模型与缓存预算
负载Multi-LexSum 请求(法律文书多文档摘要有监督数据集,Shen et al. 2022),输入 64K–128K token
请求数H200 用 256 条(平均输入 98,125 token);B300 扩到各配置可准入的并发,最多 578 条
生成每请求 2048 token,贪心解码
投机解码多 token 预测(MTP),2 个 draft 步
基线SGLang(GPU 常驻 KV)与 HiSparse(CPU 承载 KV)

峰值解码吞吐相对 HiSparse 的加速比如下(GPU 与 CPU 预算对齐、开启投机解码;数值逐项取自论文 §6.3 与摘要 [1]):

平台DPTP
8×H2001.16×1.70×
8×B3001.73×2.51×

另外两个数字同样重要,因为它们限定了这四个倍数的适用范围:

  • 不开投机解码时,8×B300 的 TP 峰值吞吐是 SGLang 峰值的 3.51 倍 [1];
  • BS1 低并发时,UlaCache 在全部八个配置里都快于 HiSparse、但慢于 SGLang(GPU 常驻)[1]。

第二点值得停一下。它说明这不是「每步更快」的故事,而是「能同时装下更多请求」的故事。论文的吞吐比较口径也印证了这一点:每种方法取自己在可跑 batch 范围内的观测峰值,不按同一 batch 对齐 [1]。换句话说,UlaCache 赢的是「它能跑到更大的 batch,而对手在更小的 batch 上就撞容量墙」(各配置的具体上限见论文 Figure 7 各子图,此处不逐点列举),不是「同一个 batch 下每步更快」。

用本文自算的两个比值可以把关系说得更准:TP 的加速比是 DP 的 1.45–1.47 倍(H200 1.70/1.16 = 1.47;B300 2.51/1.73 = 1.45);B300 上相对 HiSparse 的加速比,是 H200 上对应加速比的 1.48–1.49 倍(1.73/1.16 = 1.49、2.51/1.70 = 1.48)。后一个说法要特别小心:这里相除的是两个「相对 HiSparse 的加速比」,不是 B300 对 H200 的绝对吞吐比——论文没给两种平台的原始吞吐,绝对比算不出来。至于这两个比值为什么呈现这样的关系,论文没有做分解实验,本文也不能据此归因。

可以单独算一个量级,但不能拿它去和 Figure 2 对账:H200 那组是 256 条请求 × 平均 98,125 输入 token ≈ 25.12M 输入 token(本文自行推导,仅此一步)。为什么不往下比:Figure 2 是 8×B300、Spec. off 下的 KV 分配容量(槽位),而 25.12M 是 H200 的输入 token 总数;平台、口径(容量 vs 占用量)、是否含生成 token 三处都不同,相除得到的「每 token 几个槽」没有解释力。这一步是本稿前一版写错的地方,已撤掉。

怎么读那几条低并发 TPOT 曲线

论文的低并发延迟图(Figure 6)在八个配置(2 个平台 × {DP, TP} × {开/不开投机解码})里给出了同一个形状,值得单独说,因为它最容易被误读成「UlaCache 更慢」。

  • BS1 这一段(论文明确只说了 BS1):SGLang 的 TPOT 最低(KV 全在 GPU、零搬运),UlaCache 居中,HiSparse 最高 [1]。论文的说法是「额外的查找、调度与 TP 通信开销与该小幅差距一致」,但没有逐项量化各占多少;而且这笔开销的构成在两种模式下不同——TP 模式多了跨卡取数与本地 buffer 管理,DP 模式根本没有 buffer 这一层(论文 §4.3)。所以只能说「与多出来的这层管理开销方向一致」,不能断言「差额就是簿记成本」。论文没有逐 batch 报低并发段的排序,中间几个 batch 点的相对次序是本文的推断,不是论文数据。
  • 越过大 batch 后:SGLang 在超出容量的配置上被标成「超出容量」(它装不下就得拒收),因此没有对应数据点;HiSparse 因为固定配额,命中率上不去,TPOT 抬升;UlaCache 靠共享池把命中率维持住 [1]。
  • 两条曲线的交点就是「这套机制开始划算」的并发门槛。论文没有显式标这个点;把 Figure 6 与 Figure 7 并读,交点大致落在 SGLang 的准入上限附近(本文推断)——也就是说不存在「既保住 SGLang 的低并发延迟、又拿到大并发吞吐」的配置,这是一个明确的取舍,而不是可以两全的优化。

这也是我在 §十 里把「先确认你的瓶颈在容量」放在第一条的原因:如果你的服务长期只跑几条请求(低并发),这套系统的账面收益可能为负。

十、工程含义:这套设计什么时候值得上

把前面的机制收成几条可操作的判断。

第一,收益来源是「容量」,所以要先确认你的瓶颈在容量。 如果你的服务是短上下文、高并发已能满足、GPU 剩余显存充足,那 UlaCache 这类设计给你的是额外的一层地址解析与 buffer 管理,净收益接近零,甚至为负(论文自己就报了 BS1 时慢于 GPU 常驻方案)。反过来,如果你的场景是 64K 以上长上下文、请求数远大于「全历史装进显存」所能支撑的并发,那么收益随容量比放大。

第二,它依赖「有稀疏选择」这个前提。 逻辑地址本身对稠密注意力也成立,但整套机制的收益——按选择搬运、按最近访问缓存、跨层复用访问计划——都建立在「每步只读几千条、且选择会变」之上。论文的实测模型是 GLM-5.3(属 GLM-5 系 [1]);同类工作里 DeepSeek-V4.1-Flash 也是把 KV 压缩与稀疏读取当作长上下文的经济解 [4]。稠密注意力下这套东西仍然能当分层缓存用,但那是另一个收益模型。

第三,TP 与 DP 的收益结构不同,但别把差异归因成单一原因。 四个观测值里,TP 的相对加速比更高(是 DP 的 1.45–1.47 倍)。两种模式的机制与开销确实不同:TP 模式多了一层 MLA 跨卡复制的消除潜力,同时也多了跨卡取数与本地 buffer 管理;DP 模式没有跨卡成本,消掉的是 GPU/CPU 双存与固定配额。但现有实验不能把加速比差异归因于「消除复制」这一项——论文只给端到端数字,没做 TP/DP 的收益分解。

第四,你需要为「CPU 容量」做真实预算。 论文的对照组预算给到每 GPU 128 GB(H200)/192 GB(B300)的 CPU 内存,且 B300 每卡 272 GB 用于模型与缓存 [1]。这是很重的机器配置假设:这套方案不是「省显存」,而是「用 CPU 内存与 PCIe/NVLink 带宽换显存」。评估时必须把这些列进成本,而不是只比显存占用。

在自己的引擎里落地要动哪几处

从论文描述的实现切口(落在 SGLang 上)看,抽象只替换了少数几个接缝,但每一个都必须换:

接缝原本做什么改造后做什么风险点
KV 分配接口分配「这个请求在第 r 张卡的若干物理槽」分配逻辑地址,由 UlaCache 绑定物理存储分配失败语义要重定义(逻辑地址成功 ≠ 物理已就绪)
稀疏选择后的取数直接按物理位置读本地池先查本地 buffer,再解析地址,必要时提升或跨卡取路径变长,必须等完成信号才能读
索引器(indexer)每 rank 存并算自己的 keyTP 下按逻辑地址同样切分,只算本地 key,再 all-gather 分数做 TopK分数 all-gather 在低并发时是净开销 [1]
缓存淘汰每请求自己的 LRU全池共享,PB-LRU 分桶 + 位图选受害槽当前桶必须排除,否则自造抖动
分层后端前缀缓存按前缀命中恢复活跃请求历史按「逻辑地址」常驻 CPU 池,选中即提升需要与既有前缀缓存共存,论文未评估组合

这张表想说明的是:这套设计不是「加一个 LRU 库」那种局部改动,它把「KV 的引用方式」换掉了,所以凡是直接持有物理槽号的地方都要跟着改。这也是为什么论文要专门强调「common allocation and sparse-access interfaces」——它必须是一个对 DP/TP 都成立的公共接口,否则两套并行方式会各写一遍。

十一、边界与未解

诚实列出这篇论文没有回答、以及我读完后仍不确定的地方。

  • 没有做归因分解。 四个加速比是端到端数字,论文没有报告「其中多少来自消除复制、多少来自共享池、多少来自 PB-LRU 的调度加速」。本文 §九 里把端到端加速比相除得到的两个比值,只是相除关系,不构成归因结论。
  • 没有报告 CPU 侧带宽与端的压力。 论文给了 CPU 容量预算与 TPOT 曲线,但没有给出 CPU 内存带宽占用、跨 socket/NUMA 的影响、以及 H2D 链路的饱和度。对一个「用带宽换容量」的设计,这是最需要的数据之一。
  • 范围是单机 8 卡组。 地址空间覆盖的是同一组内各卡的池;跨节点的分离式 KV 池(论文 §7 提到的 Mooncake 那一路)不在本文讨论的范围内 [1]。
  • 与前缀缓存的组合未评估。 HiCache/LMCache 那一路解决的是「跨请求复用已算过的前缀」(HiCache 是 SGLang 的分层前缀缓存,与本文基线 HiSparse 不是同一个系统)[6][7],UlaCache 解决的是「活跃请求的历史怎么摆」。两者理论上互补(前者省 prefill,后者增 decode 并发),但论文没有测组合场景。
  • PB-LRU 的近似在极端访问模式下未做压力测试。 论文报了命中率差小于 0.10 个百分点,但那是特定配置(8×H200、DP,且同时覆盖不开投机解码与开投机解码两种,后者用 2 个 draft 步)在 Multi-LexSum 负载下的结果;对访问模式剧烈变化的负载(例如多租户混跑)欠一轮验证。
  • 可复现性依赖较多外部条件。 实现落在 SGLang 上、模型是 GLM-5.3、还要 FP8 与 MTP 配置;第三方要完整复现,需要同时满足这些条件。
  • 一个我读不出答案的地方:论文写「桶轮转最坏情况可覆盖整个池」,但没有给出这种情况下调度时间的实测上界。若某个负载恰好周期性触发全池轮转,PB-LRU 的管理开销会不会吃掉它省下来的扫描时间,论文没有数据。
  • 没有对照组之外的第三方复现。论文是 v1(2026-10-21),本轮检索到的相关系统(HiSparse、OasisKV 等)都出自同一时期的不同团队,尚无独立第三方在同一平台上交叉验证 UlaCache 的四个加速比。
  • 没有说明「跨卡取数」在 NVLink 拓扑不对称时的表现。8 卡组内 peer 访问的代价依赖拓扑(同 NVSwitch 与跨 NUMA 不同),论文的评估是整机 8 卡,没有给拓扑敏感性的数据。

十二、小结

回到开头那个图书管理员的比喻:UlaCache 没有让图书馆变小,也没有让每次借书变快,它做的是把「书号」和「书架」解绑——于是同一套书不必在 8 个分馆各放一份,阅览室也可以和地下库共用同一份历史,空闲书架能被任何一位管理员临时借用。三个机制一一对应三笔浪费:逻辑地址消掉跨卡复制,统一池消掉同一份历史的双存,共享槽位加 PB-LRU 消掉固定配额的僵化。

代价同样清楚:多一层地址解析、多一条跨卡取数路径、多一份 CPU 带宽账单,以及低并发时会输给最朴素的 GPU 常驻方案。它是一套为「长上下文 + 大并发」优化的系统,而不是通用加速器。

一句话回顾:稀疏注意力解决了「读得太多」,UlaCache 解决的是「存得太散」。

📋 来源与核验记录

本文引用的全部外部事实都来自下列一手材料,均在本轮(2026-10-28 北京时间)实际打开核读。

  1. UlaCache 论文(主源):Isaac Zhu, Alan Cao, Hugh Yin, Rocky Wang, Orion Wang, Hscos Zhang, Jack Li, Jason Zhao(Scitix.AI,作者顺序依 arXiv 摘要页),《UlaCache: Unified Logical Addressing for Sparse LLM Serving》,arXiv:2610.29820v1 [cs.DC],2026-10-21 提交(PDF 280 KB)。本轮核读:摘要、§1 引言的三项贡献、§2.1–§2.2 动机、§3 系统总览、§4 统一地址空间与本地 buffer、§5.1–§5.2 PB-LRU 与交换顺序、§6 评估设置与结果、§7 相关工作、§8 结论。链接:https://arxiv.org/abs/2610.29820
  2. HiSparse 论文(主基线):Zhiqiang Xie, Zhangheng Huang, Tingwei Huang, Ziyi Xu, Ruiyang Ma, Christos Kozyrakis,《HiSparse: Scaling Sparse-Attention Decoding with Hierarchical KV Cache Management》,arXiv:2608.07009,2026-08-07 提交。本轮核读摘要(「每步只读几千条选中 KV」「完整历史放 host、GPU 只留固定小缓存」「host-device IO 是有界驻留的唯一代价」「up to 4.7x」)。链接:https://arxiv.org/abs/2608.07009
  3. MLA 的出处:DeepSeek-AI,《DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model》,arXiv:2405.04434(KV 压缩为跨头共享潜向量的原始设计)。链接:https://arxiv.org/abs/2405.04434
  4. 稀疏注意力的模型侧出处(DeepSeek 系):DeepSeek-V4.1-Flash 技术报告,arXiv:2609.19969,2026-09-17 提交(UlaCache 论文 §1 与 §2.1.1 引作 index-based 稀疏注意力的实例)。链接:https://arxiv.org/abs/2609.19969
  5. PagedAttention / 逻辑块到物理块的映射先例:W. Kwon 等,《Efficient Memory Management for Large Language Model Serving with PagedAttention》,arXiv:2309.06180(UlaCache §7 引为「逻辑 KV 块 → 物理 GPU 块」的先行工作)。链接:https://arxiv.org/abs/2309.06180
  6. 分层前缀缓存一路:Y. Liu 等,《LMCache: An Efficient KV Cache Layer for Enterprise-Scale LLM Inference》,arXiv:2510.09665,v1 2025-10-08、v2 2025-12-05。链接:https://arxiv.org/abs/2510.09665
  7. SGLang HiCache 官方博客:Z. Xie,《SGLang HiCache: Fast Hierarchical KV Caching with Your Favorite Storage Backends》,LMSYS Org,2025-09-10。链接:https://www.lmsys.org/blog/2025-09-10-sglang-hicache/
  8. TP 切分与 MLA 复制的对照工作:N. Bhatia 等,《Helix Parallelism: Rethinking Sharding Strategies for Interactive Multi-Million-Token LLM Decoding》,arXiv:2507.07120,2025-07-07 提交。链接:https://arxiv.org/abs/2507.07120

补充旁证(本轮同样打开核读了摘要,仅用于确认相关系统定位,未从中取任何性能数字):OasisKV(arXiv:2608.08097,v1 2026-08-08、v2 2026-10-25,本轮核读为 v2;完整历史在 CPU/远端、GPU buffer 只存拷贝)https://arxiv.org/abs/2608.08097

本文自行推导的数字(与上面的一手数字分列):

  • 稀疏读取比例 ρread\rho_{read} 的 1.53%–6.1%:假设 kk = 2000–4000(依据 HiSparse 摘要「a few thousand」)、LL = 65536–131072(论文负载区间),按 k/Lk/L 计算。
  • 有效唯一容量占比 56.29%:30.0M ÷ (30.0M + 23.3M),槽数取自论文 Figure 2(b)。
  • 复制率 87.5% 与唯一率 12.5%:按 (P−1)/P(P-1)/P 与 1/P1/P 在 P=8P=8 时计算,与论文 Figure 2(a) 数字一致。
  • 25.12M 输入 token:256 × 98,125,两项取自论文 §6.1 的请求数与平均长度;只算到这一步,不与 Figure 2(b) 的槽位容量相除(平台与口径都不同)。
  • 1.45–1.47 与 1.48–1.49 两个比值:由论文报告的四个加速比相除得出;前者是「TP 加速比 ÷ DP 加速比」,后者是「B300 上的加速比 ÷ H200 上对应的加速比」,都不是绝对吞吐比,也不构成归因结论。

数字口径核验表(正文关键数字 → 出处位置;§6.5 的假设导出值单列最后一行):

数字出处口径说明
12.5% / 87.5%[1] Figure 2(a) 与 §2.2.18 卡 TP 下历史分配中「唯一历史」与「副本」的占比
30.0M / 23.3M / 53.3M 槽[1] Figure 2(b)HiSparse 的 CPU 槽、GPU 缓存槽与两者之和
56.29%本文自行推导30.0 ÷ 53.3,唯一历史占物理槽比
23.5%[1] §2.2.28×B300 DP + 投机解码、BS1 时 HiSparse 相对 GPU 常驻 SGLang 的 TPOT 高出比例
1.53%–6.1%本文自行推导k/L,取 k=2000–4000、L=65536–131072
93.9%–98.5%本文自行推导1 − k/L 在 k=2000–4000、L=65536–131072 两端的取值
1.16× / 1.70×[1] §6.3 与摘要8×H200,DP / TP,开启投机解码,相对 HiSparse
1.73× / 2.51×[1] §6.3 与摘要8×B300,DP / TP,同上条件
3.51×[1] §6.38×B300 TP、不开投机解码,UlaCache 峰值吞吐相对 SGLang 峰值
1.5–2.3×[1] §6.5PB-LRU 相对朴素 LRU 的调度时间优势(替换压力大、batch 大时)
0.10 个百分点[1] §6.5 与 Figure 10PB-LRU 与朴素 LRU 的命中率差上界
1.45–1.47 / 1.48–1.49本文自行推导由上面四个加速比相除得出,属归因推断
25.12M 输入 token本文自行推导256 × 98,125,仅表示 H200 组的输入 token 总量;不与 Figure 2(b) 相除
64K–128K、256 条、98,125、578 条、2048 token[1] §6.1负载设置(输入长度区间、请求数、平均输入长度、最大请求数、生成长度)
128 GB[1] §6.1H200 每 GPU 的 CPU 内存预算
192 GB[1] §6.1B300 每 GPU 的 CPU 内存预算
272 GB[1] §6.1B300 每 GPU 的模型与缓存预算
280 KBarXiv 元数据论文 PDF 体积
80 KiB、24 GiB/s、160 MiB、6.51 ms、16 MiB、0.65 ms本文自行推导(假设值)§6.5 手算例;80 KiB 与 24 GiB/s 是本文假设,不是论文配置

核验记录:论文 PDF 与 arXiv 摘要页的实际采集日期为 2026-10-28 约 02:50(北京时间);PDF 正文 781 行、75,596 字节文本;论文元数据(提交日 2026-10-21、分类 cs.DC、v1、280 KB、八位作者、通讯作者 Jason Zhao)取自 arXiv 摘要页。上述 8 条来源与 1 条旁证(OasisKV)的 URL 在抓取时均返回正常页面并带对应标题。