01 · 长历史很多,查询却只有一个
普通单请求Decode的一层Attention通常只有一个新查询Q,却要读取许多历史K/V。若主要按batch、head与查询行分配任务,小batch的查询任务数可能不足;历史再长,也可能只是让少数任务做更久。
Split-KV沿历史长度再划分独立任务:不同任务计算同一个查询对不同K/V片段的贡献,再合并。历史没有被删减,每个应可见位置仍被考虑;重点是增加可并行工作,而不是改变注意力窗口。
依据:Stanford CRFM · Flash-Decoding原作者讲解 ↗ · TensorRT-LLM · 多块Decode Attention与选择条件 ↗
02 · 一个查询分给三个工作块
Q保持同一个查询
历史KV:[片段0] [片段1] [片段2]
↓ ↓ ↓
各片段:QKᵀ → 局部稳定Softmax统计 → 对V的局部贡献
└──── 合并统计与贡献 ────┘
↓
完整Attention输出每块把自己的得分和V汇总为小状态,不把所有片段的得分拼成大矩阵后重做Softmax。部分结果通常需要临时缓冲和额外合并阶段;这笔成本在短上下文时可能抵消并行收益。
它与FlashAttention可组合:片段内部仍使用分块与在线归一化,片段之间再做归约。与分页KV也可组合:分片按逻辑历史范围定义,读取时通过块表找到实际存储。
依据:Stanford CRFM · Flash-Decoding原作者讲解 ↗ · FlashInfer 0.7.1 · Attention计划、Split-KV与归约约束 ↗ · vLLM · Paged Attention 内核设计 ↗
03 · 为什么不能直接平均局部输出
自设单标量例子:得分s=[0,ln2,ln3,ln4],所以未归一化权重比例为[1,2,3,4];V=[1,2,4,8]。完整输出为(1×1+2×2+3×4+4×8)/(1+2+3+4)=49/10=4.9。
前两位置一块,后两位置一块。块A局部输出5/3≈1.667,块B为44/7≈6.286。直接平均得到约3.976,与4.9不同,因为两块在完整Softmax中的权重质量分别为3与7,不能各占一半。
| 块 | 局部输出 | 占全局权重 | 全局贡献 |
|---|---|---|---|
| A:位置0/1 | 5/3 | 3/10 | 0.5 |
| B:位置2/3 | 44/7 | 7/10 | 4.4 |
| 合并 | 不是简单平均 | 总权重1 | 0.5+4.4=4.9 |
04 · 不存完整分数,怎样得到正确权重
块i保存三个状态:最大得分mᵢ、指数和ℓᵢ=Σexp(s−mᵢ)、未归一化向量贡献uᵢ=Σexp(s−mᵢ)V。局部输出是uᵢ/ℓᵢ。各块使用不同最大值作基准,合并前先换到同一个基准m=max mᵢ。
alpha_i = exp(m_i - m)
ell = sum(alpha_i * ell_i)
u = sum(alpha_i * u_i)
O = u / ell
# 若保存局部O_i,则u_i = ell_i * O_i。
# 也可用log-sum-exp保存归一化信息;不同后端状态格式不同。本例A:m=ln2、ℓ=1.5、u=2.5;B:m=ln4、ℓ=1.75、u=11。全局基准ln4,A乘0.5、B乘1,得到ℓ=2.5、u=12.25,输出4.9。只传局部输出而丢掉归一化统计,就无法正确恢复这些权重。
同样四个位置,怎样合并局部输出?
得分[0,ln2,ln3,ln4]、V=[1,2,4,8];完整输出4.9。比例由各块m/ℓ换到共同基准后计算,不是按块长度加权。只演示数值合并,不执行设备并行。这是数学等价的重组;浮点执行的加法顺序变化仍会产生舍入差异。不能将“考虑相同历史”描述成所有硬件位级结果必然相同。
依据:Stanford CRFM · Flash-Decoding原作者讲解 ↗ · FlashInfer 0.7.1 · Attention计划、Split-KV与归约约束 ↗
05 · 拆几块不是越多越好
例如batch=1、查询头32,教学单块路径每head一个任务,共32个任务;每head拆8段可有256个局部任务,再加合并任务。实际GQA分组、内核调度和硬件会改变任务组织,不能把这个计数直接当活跃计算单元数。
| 拆分更多的收益 | 同时增加的代价 |
|---|---|
| 单任务历史更短,更多独立工作 | 更多临时输出、统计、地址计算及合并。 |
| 小batch更有机会利用设备 | Q可能被重复读取,任务调度固定成本增加。 |
| 降低某个长任务的独占负担 | 片段太小后计算不足,局部利用率下降。 |
短历史、较大batch或已有足够查询并行时,单块路径可能更好。读取全部历史KV的必要字节并未因拆分消失;它常改善带宽利用,而不是压缩缓存。TensorRT-LLM使用条件和启发式选择多块路径,也说明不是一开就无条件更快。
06 · mask、位置与空块要正确
逻辑片段不能重置position或因果边界。多query、分块输入或投机验证时,每个query允许看的历史可能不同;需要逐query保留可见性,不能套用“都看完整历史”的单query简化。
一个片段对某query全部被mask,可用零指数和/零贡献表示并跳过该块;避免计算exp(−∞−(−∞))导致NaN。整行没有可见位置时,应采用与基线后端相同的输出约定,不能自行混用。
量化KV需同样尺度解释;GQA的head映射、页表、padding与实际有效长度要一致。跨卡Context Parallel的片段归约还包含设备通信,本篇的同设备Split-KV不自动引入网络。
依据:FlashInfer 0.7.1 · Attention计划、Split-KV与归约约束 ↗ · vLLM · Paged Attention 内核设计 ↗
07 · CPU先验证合并,设备再验证速度
下载脚本比较完整稳定Attention与不同分片数的合并,使用向量V、不同Q、非整齐长度、局部全mask和大得分,确认归约稳定;另用错误平均作为反例。没有设备并行执行,不据此报告加速比。
为当前batch/head/有效长度选择split计划
各任务读取自己负责的逻辑KV范围
计算并保存局部输出及归一化统计
等全部必要片段就绪
按共同基准合并 → 写完整输出
# 计划、临时缓冲、mask与图执行条件都要配套。实际阅读入口可用Flash-Decoding原作者讲解、TensorRT-LLM多块Attention,以及FlashInfer的split-kv计划参数。某些参数以page为单位、仅对特定后端支持;应按版本核对,不提供跨引擎通用split值。
依据:Stanford CRFM · Flash-Decoding原作者讲解 ↗ · TensorRT-LLM · 多块Decode Attention与选择条件 ↗ · FlashInfer 0.7.1 · Attention计划、Split-KV与归约约束 ↗
08 · 验收时把合并开销计进去
- 正确性:输出对照、最大/平均误差;覆盖mask、GQA、分页边界、量化和极端得分。
- 性能:局部Attention与合并总耗时、临时内存、实际KV读取和任务利用。
- 负载:batch、head、上下文长度、dtype形成组合,不只测最长序列。
- 系统:结合连续批处理和图重放,确认计划变化没有额外编译/捕获/缓冲问题。
FlashInfer文档提示某些split策略会影响归约确定性及CUDA图兼容;这些约束取决于具体路径,不意味着所有Split-KV都不兼容图执行。
09 · 跨平台读法与练习
拆历史并归约是执行思想,CUDA和昇腾内核的工作块、片上存储及临时统计格式不同。这里提供的NVIDIA/FlashInfer入口不是已验证的NPU开关;昇腾需核对所用Attention算子对增量形状、分核及KV布局的支持。
依据:vLLM Ascend · 支持功能矩阵(main) ↗
- 两个等长片段,为什么局部Attention输出不能等权平均?
- 拆8段后,原历史KV字节是否减少了8倍?
- 一个片段全部被mask,为什么不能直接做−∞减−∞?
流程位置与关联方法
这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。
资料与核查范围
原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。
- Stanford CRFM · Flash-Decoding原作者讲解 ↗
- TensorRT-LLM · 多块Decode Attention与选择条件 ↗
- FlashInfer 0.7.1 · Attention计划、Split-KV与归约约束 ↗
- vLLM · Paged Attention 内核设计 ↗
- vLLM Ascend · 支持功能矩阵(main) ↗
代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。