0.8MB 跑通 Qwen|第 8-3 篇:推理引擎的 KV 缓存结构——按 token 还是按头存

简介: 本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,适配Qwen3-VL多模态模型,在RK3588上实测。本文精析KV缓存的token-major布局设计原理,揭示其如何兼顾prefill与decode访存效率,直击带宽瓶颈。(239字)

系列:《0.8MB 跑通 Qwen:从零实现 ARM 零依赖纯 C 推理引擎》(30 天 × 90 篇) | 适配模型:Qwen3-VL-8B-Instruct(千问3_VL_8B_Instruct)· Qwen3-VL-2B-Instruct · Qwen3-30B-A3B | 测试设备:RK3588(4×Cortex-A76 + 4×Cortex-A55,aarch64)

系列总纲:《0.8MB 跑通 Qwen》30 天 90 篇 · 总纲(阿里云社区)

上一篇:8-2《在线 softmax:为什么不能先算完 e^x 再除》 | 下一篇:第 9 天《q8 KV 与单查询路径》

源码精读篇:本文为源码/方法论精读,无独立实测;文中数字均引述仓库 docs 的板端实测记录

一句话导读:推理引擎的 KV 缓存结构:token-major 与 head-major 两种排法的地址公式与访存差异,读引擎 token 优先加按块分配的下标代码,讲清按 token 还是按头为何是带宽问题。

关键词:手搓 Qwen 推理引擎、千问大模型推理、Qwen3-VL、零依赖纯 C、KV cache、token-major、head-major、decode、带宽

导语:打分要回看前面所有 token 的 K、V,而这些缓存"怎么排"大有讲究:排错一个维度,访存就从顺序流变成跳着读。手搓 Qwen 推理引擎选的是 token-major 布局,因为它要同时服务 prefill 的整行乘与 decode 的单 token 整块扫。这篇从一行地址公式里读出布局真相。

打分要"回看"前面所有 token 的 K、V。这些 K/V 不是散落各处的,它们住在一个叫 KV cache 的连续内存里——但"怎么排"大有讲究:排错一个维度,访存就从顺序流变成跳着读。今天把生产引擎的真实 KV 布局拆给你看。

1. 知识点:两种正交的排法

一个 token 的 K/V 是 [n_kv_heads × head_dim] 的矩阵。这么多 token 的缓存,排法有两个极端:

  • token-major(token 连续):先按 token 排,每个 token 里再按 [head][dim] 排——cache[t][h*dim + d]。第 t 个 token 的整个 K 行是连续的一段 kv_dim = n_kv_heads*head_dim 字节;
  • head-major(头连续):先按头排,每个头里再按 token 排——cache[h][t*dim + d]。第 h 个头在所有 token 上的同一维是连续的。

选谁取决于主访存模式:

  • prefill(一批 token 同时算):要对每个 token 的整行 K 做矩阵乘(Q@K^T),token-major 让"一次取一行"变成顺序读;
  • decode(单 token 逐词生成):每个新 token 只产生一行 Q,要扫遍历史所有 token 的 K——两种排法都要跨 token 跳着读,但 token-major 下每跳读的是"连续的一整块头"(SIMD 友好)。

引擎选的是 token-major(8-1 那段代码已经露过脸),因为它同时服务 prefill 的整行乘与 decode 的单 token 整块扫。

2. 对应代码:一行代码里的布局真相

证据在 8-1 引用的参考实现里(vllm_transformer.c 第 101–102 行与 122–123 行):

const float *kh = k_cache + t * kv_dim + h * head_dim;   /* K:第 t token、第 h 头 */
const float *vh = v_cache + t * kv_dim + h * head_dim;   /* V:同式 */

下标 t * kv_dim 说明 token 在最外层(t 每加一,地址跳 kv_dim),h * head_dim 是内层头偏移——这就是 token-major + head 内联 dim 的布局。kv_dim = n_kv_heads * head_dim(一个 token 的 K 总长)。

生产 q8 内核(vllm_safetensors.c 第 6633–6636 行)也完全同构,只是多了一层"按块":

const int8_t *kt = k_cache_q8[t / kv_bs] + (size_t)(t % kv_bs) * kv_dim + kh_off;
float ks = kscale[(size_t)t * nkv] * KVQ_INV;   /* 每个 (token, head) 一个 scale */

t / kv_bs 定位块、t % kv_bs 定位块内 token——块外 token 连续、块内也是 token 连续,本质还是 token-major,只是加了分块以便随 token 数增长按需分配(每 token 每层只存一份,9-3 会讲块内布局)。

3. 改动后果:把布局改成 head-major,decode 会发生什么

想象把缓存改成 head-major:k_cache + h * seq_cap * head_dim + t * head_dim。功能上完全等价(8-1 的参考代码改一行下标照样算对),但代价藏在访存里:

  1. decode 单 token 扫全历史:对每个头 h,要按 t 步进读取 t*head_dim 跳一块——从"连续块跳读"退化成"每 head_dim 个元素跨一大段",TLB/cache line 命中率下降;
  2. prefill 的整行乘:一次要 gather 跨 head 的数据,SIMD 连续加载退化成低效的逐段取;
  3. q8 版本更惨:q8 KV 的 scale 是"每 token 每头"独立存的(kscale[t*nkv]),head-major 会让"同一 token 的 nkv 个 scale"彼此远离,随机访问加倍。

结论:布局不改数学、只改访存,但访存决定吞吐——"按 token 还是按头"不是风格问题,是 bandwidth 问题(5-1 的尺子再次适用:同样的字节,排法不同,有效带宽差几倍)。

画图任务预告:这个布局光看代码记不住,动手画一遍(任务 A 给了 2 头 × 4 token 的模板)。

4. 学员调试任务

  • A 档(画图 + 读码):以引擎真实参数为例(n_kv_heads=8、head_dim=128,kv_dim=1024)手画 2 头 × 4 token 的 token-major KV 布局:
    1. 标出每个 (t, h) 的起始地址公式 t*1024 + h*128;
    2. 用不同颜色标 decode 时"对 head 0 扫 4 个 token"的访存顺序,数数它跳了几次;
    3. 再画一遍 head-major 版,对比跳转次数。
  • B 档(纯读源码):在 vllm_transformer.c 与 vllm_safetensors.c 各找一处 KV 读取下标,用"外层是什么、内层是什么"一句话描述其布局,并回答:kv_bs(块大小)为什么也要乘进去。

预期输出:你能不看代码画出 token-major 的 KV 地址公式,并解释"decode 扫历史时两种布局的访存差异"为什么影响吞吐。

收尾

  • 本篇源码点名:vllm_transformer.c(KV 下标第 101–102/122–123 行)、vllm_safetensors.c(q8 KV 分块读取第 6633–6636 行)。
  • 开源仓库:Kestrel-LLM (Gitee)(AGPL-3.0-or-later 或商业许可,二选一)
  • 下篇预告:KV 存在内存里,可它太肥了——f16 存 8K 上下文要 ~560MB,板上伤不起。第 9 天把 KV 也量化成 q8:带宽省一半以上,还顺带把 decode 的单查询路径一起讲了。
相关文章
|
1月前
|
人工智能 自然语言处理 文字识别
盘点阿里云自研模型|Qwen、通义万相、HappyHorse 等AI模型清单
阿里云自研AI模型涵盖文本、图像、视频、语音及全模态,以通义千问Qwen系列为核心,包括Qwen3.8-Max、Qwen-VL-Plus、通义万相、CosyVoice等数十款专业模型,统一通过百炼平台提供API服务。(239字)
342 1
|
1月前
|
人工智能 数据可视化 API
百炼是什么?阿里云AI模型服务平台免费千万Tokens、AI模型、支持功能、模型费用、计费方式及问题解答FAQ
阿里云百炼是面向企业与开发者的AI模型服务平台,集成通义千问及DeepSeek、Kimi等主流第三方大模型,提供模型调用、应用构建、知识库、定制训练等全链路能力;新用户免费领超7000万Tokens。
|
1月前
|
人工智能 图形学
婚庆建模500元变2元,她靠AI年入200万:AI婚庆培训OPC案例深度拆解
本文为「OPC一人公司通关手册」第24篇,深度拆解96年婚庆从业者如何用AI重构行业:将高端方案从3-7天压缩至1.5小时,建模成本从千元降至2元,进而转型AI培训,一年营收200万+。核心启示:一人公司成败不在工具,而在“专业底盘+AI放大”,卖认知差远比卖时间更可持续。(239字)
|
1月前
|
弹性计算 编解码 人工智能
阿里云服务器ECS实例架构:X86计算和Arm计算有什么区别?GPU、裸金属和高性能计算区别对比?
阿里云ECS支持五大计算架构:X86(稳定通用,适配Intel/AMD)、Arm(倚天/Altra,高能效独享核心)、GPU(AI训练/图形加速)、弹性裸金属(神龙架构,物理机性能+虚拟机弹性)、高性能计算(HPC优化,超大规格)。按场景灵活选型。阿里云服务器ECS官网:https://t.aliyun.com/U/AZBUsA
150 0
|
1月前
|
应用服务中间件
阿里云轻量应用服务器最新费用:2核2G、2核4G、4核8G、4核16G都有活动,秒杀38元1年起
阿里云轻量应用服务器2026年最新报价:新用户专享,2核2G仅38元/年(秒杀)、2核4G 379元、4核8G 1159元、4核16G 1599元;全系标配200M峰值带宽+不限流量,性价比突出。(239字)
207 0
|
1月前
|
人工智能 Linux Windows
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
千问办公(QwenWork)是阿里云推出的AI智能办公平台,支持网页端直接使用及Windows/Mac/Linux客户端下载。提供PPT生成、财报分析、网页搭建等AI功能,个人版免费,企业版198元/席/月。详情见官网qwenwork.cn或阿里云产品页。
2402 0
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
|
并行计算 编译器 调度
0.8MB 跑通 Qwen|第 1-2 篇:推理引擎的 ARM 工具链第一课——原生编译 vs 交叉编译,以及一个真实的 -march 翻车现场
本文深入解析ARM交叉开发三大核心:原生vs交叉编译的本质区别、`-march`/`-mcpu`的语义差异,以及`dotprod`扩展为何不可或缺;并通过真实编译报错复现,揭示编译器如何在编译期主动拦截潜在运行时崩溃——不是刁难,而是保护。
143 0
 0.8MB 跑通 Qwen|第 1-2 篇:推理引擎的 ARM 工具链第一课——原生编译 vs 交叉编译,以及一个真实的 -march 翻车现场
|
1月前
|
NoSQL Cloud Native 关系型数据库
【云原生架构实战】基于 ThinkPHP 与 Uniapp 重构企业级赛事中台:分布式锁与复杂状态机设计
本文深度解析高并发体育赛事报名系统的架构设计,涵盖跨端Uniapp开发、私有化物理隔离部署、DDD领域建模、Redis分布式锁防重、InnoDB强一致性事务,以及GD库动态证书渲染等核心技术,体现工程化落地能力。(239字)
123 5
|
1月前
|
缓存 C语言 C++
0.8MB 跑通 Qwen|第 9-3 篇:推理引擎的 q8 KV 精度对照——量化进注意力,输出差多少
本系列《0.8MB跑通Qwen》手搓零依赖纯C推理引擎,适配Qwen3-VL多尺寸模型,在RK3588上实测q8 KV量化:输出误差仅≈0.01,端到端PPL损失<1%,带宽降为52%,精度与效率达成教科书级平衡。(239字)
167 1
|
1月前
|
缓存 人工智能 索引
0.8MB 跑通 Qwen|第 12-1 篇:LLM 推理的跨进程恢复——服务重启了,会话不能断
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,实现在RK3588上部署Qwen3-VL等多尺寸模型。本文详解`--disk-kv`机制:将KV Cache落盘持久化,支持进程重启后按前缀精准恢复,实现“会话不断连”,2K上下文prefill加速达23.6×,真正打通边缘AI服务可用性最后一环。(239字)
137 1

热门文章

最新文章