内容提要
DeepSeek-V4模型采用混合压缩注意力(mHC),将KV缓存分为状态缓存和分页缓存,分别管理滑窗KV与压缩条目。上下文并行通过点对点通信和all-gather处理跨rank压缩窗口。磁盘前缀缓存中,压缩条目易存,滑窗KV需重算或周期检查点。mHC通过融合内核、重算和DualPipe优化,将访存开销压至6.7%。
延伸解读
KV缓存拆分:状态与分页的边界
V4将KV缓存分为状态缓存和分页缓存,前者大小固定,类似SSM状态,后者随序列增长。这种拆分源于不同层条目粒度不同(CSA每4 token一条,HCA每128 token一条),且滑窗KV与压缩条目共存。块大小取lcm(4,128)=128的整数倍,使两种层共用页表。理解这一设计有助于把握V4在长上下文下的内存管理逻辑。
上下文并行的两阶段通信
压缩窗口可能跨rank边界,且各rank压缩条目数不等,因此CP采用先点对点传递末尾未压缩KV,再all-gather收齐压缩条目的两阶段方案。相比Kimi K3的KDA需处理状态不可加性,V4的难点在窗口对齐。这种通信方式比传统softmax注意力传整段KV更省带宽,是长序列训练的关键优化。
磁盘前缀缓存:压缩条目与滑窗KV的取舍
压缩条目存储便宜(每4 token约704字节),可直接全存;滑窗KV体积约为压缩条目的8倍,需在存储与重算间权衡。论文给出全存、周期checkpoint、不存三种策略,其中不存时仅需重算最后128·L个token,因为滑窗依赖范围有限。这为共享前缀场景提供了灵活的缓存方案。
mHC开销压至6.7%的三板斧
mHC的访存开销通过融合kernel、重算和DualPipe优化。融合kernel将读写次数从多次降为一次,重算丢弃中间结果并在反向时重跑,DualPipe则重叠通信与计算。三者结合使墙钟开销仅占1F1B阶段的6.7%。这体现了系统设计对模型结构的适配,而非单纯堆算力。
Q&A
DeepSeek-V4的KV缓存为什么被分成状态缓存和分页缓存?
因为混合压缩注意力(mHC)中不同层的KV条目粒度不同,且同一层有滑窗KV和压缩条目两类,滑窗KV大小固定、随位置变化,而压缩条目随序列增长。因此将滑窗KV和未满块的尾token放入固定大小的状态缓存,压缩条目放入可分页的经典缓存。
DeepSeek-V4中上下文并行如何处理跨rank的压缩窗口?
采用两阶段通信:先点对点,每个rank将最后m条未压缩KV发给下一个rank,后者压缩得到固定长度条目;再all-gather收齐所有rank的压缩条目,用select-and-pad算子将有效条目排在前面、padding放尾部,得到完整压缩序列。
DeepSeek-V4的磁盘前缀缓存中,滑窗KV有哪些存储策略?
三种策略:全存所有token的滑窗KV,命中时零重算但写多读少;周期checkpoint,每p个token存一次最近128条,命中时读最近checkpoint并重算尾token;不存,命中时重算最后128*L个token(L为层数)。
DeepSeek-V4中mHC的6.7%访存开销是如何压低的?
通过三个手段:融合kernel,将系数计算、读、写+混+残差合并为专用kernel,减少访存次数;重算,前向丢弃中间结果,反向时重跑mHC;DualPipe,将mHC的通信和重算与相邻计算重叠。三者结合将墙钟开销压至6.7%。
DeepSeek-V4中为什么滑窗KV不存时只需重算最后128*L个token?
因为第l层某个token的滑窗KV只依赖第l-1层最近128个token的输出,而第l-1层的输出又只依赖再往前128个,如此类推,L层后依赖范围是128*L个token。有了落盘的压缩条目,这些token的注意力可正常计算,无需更早数据。
DeepSeek-V4的KV缓存块大小为什么是128的倍数?
因为CSA的压缩粒度m=4,HCA的m'=128,要让两种层共用一套页表,块覆盖的原token数必须同时是4和128的倍数,即lcm(4,128)=128的整数倍。
DeepSeek-V4中状态缓存和分页缓存分别管理哪些内容?
状态缓存管理滑窗KV(最近128个token的未压缩KV)和未满块的尾token(CSA尾段≤3个、HCA尾段≤127个)及其压缩权重,大小固定;分页缓存管理随长度增长的压缩条目,按块分页。