【免费下载链接】turboquant
TurboQuant: Near-optimal KV cache quantization for LLM inference (3-bit keys, 2-bit values) with Triton kernels + vLLM integration
TurboQuant 是一种面向 LLM 推理的 KV Cache 量化方案,核心思想是随机正交旋转 + Lloyd-Max 标量量化:把 Key 压缩到 3-bit、Value 压缩到 2-bit,再配合 Triton 融合内核与 vLLM 集成,在实测中做到 Key 压缩余弦相似度 1.000000(几乎无损)、显存容量直接翻倍。本篇从原理出发,讲清楚"为什么一个随机旋转矩阵,就能让低比特量化不毁模型"。
📦 先看清问题:KV Cache 为什么是显存瓶颈
LLM 推理的每个 token 在自注意力层都会产生一对 Key/Value 向量,它们必须一直留在显存里供后续解码反复读取。上下文越长,KV Cache 占用越大——它常是长上下文、高并发场景下的第一显存杀手。
最直觉的压缩办法是量化:把每个 bf16 的数存成 3-bit 甚至更少的索引。但量化必然带来误差,对模型输出质量是否"几乎无损",完全取决于误差长什么样、能不能被控制。TurboQuant 的答案分三步:先旋转,再查表,最后补一个符号位。
对应的压缩存储设计见 store.py。
🚫 为什么朴素的"逐坐标量化"会翻车
一个 head_dim=128 的 Key 向量,逐坐标量化时会遇到两个经典麻烦:
- 离群值撑爆量级:只要某一维数值特别大,scale 就被拉宽,其余小数值全被挤进极窄区间,精度归零;
- 能量集中在少数坐标:高维随机向量的模长天然倾向于"扎堆"在个别维度上,直接量化这些大坐标,一个坐标的舍入误差就足以毁掉整个向量的方向。
于是量化误差变成"数据相关、不可预测"的东西——你无法保证它对注意力分数无害。
🔑 核心原理:随机正交旋转把"数据问题"变成"统计问题"
TurboQuant 的第一步,是对归一化后的向量做一次随机正交旋转:
x_unit = x / ‖x‖₂ y = Π · x_unit其中 Π 是一个 d×d 的正交矩阵(旋转不改变长度,只改变方向)。妙处在于:
Π 乘上一个单位向量,等价于把这个点随机地"撒"到单位超球面上。
这样一来,旋转后每一个坐标 y_j 的取值分布,与数据本身完全无关,只取决于维度 d,并且是严格已知的——一个定义在 [-1, 1] 上的缩放 Beta 分布(codebook.py 头部注释给出了精确形式):
- 高维下它高度集中在 0 附近,近似 N(0, 1/d);
- 每个坐标的方差恒等于 1/d,没有离群值可乘之机;
- 量化误差由此变成一个可积分、可证明的统计量,论文定理 1-3 的误差界都建立在这个性质上。
随机性不是"加在数据上的抖动",而是加在坐标基上的预处理:分布被钉死之后,量化器就拥有了确定性。
实现上,旋转矩阵用固定种子的 QR 分解生成(rotation.py):
- 取 d×d 高斯随机矩阵 G,做 QR 分解得正交阵 Q;
- 用 R 对角线符号修正,保证 det = +1(纯旋转而非反射);
- 前向旋转
y = x·Πᵀ、反向旋转x = y·Π(rotation.py)。
开销方面完全可忽略:d=128 时矩阵只有 64 KB(float32),每层生成一次、由固定种子决定,同层所有注意力头共享。追求更快的话,注释里还提到了 O(d log d) 的随机 Hadamard 变换近似方案(rotation.py)。
📖 分布已知之后:Lloyd-Max 最优码本
旋转把分布钉死后,标量量化就退化成一道"最优 1D k-means"作业:在 [-1, 1] 上对 Beta 分布跑 Lloyd-Max 迭代,找到每个比特宽度的最优质心与判决边界(实现见 codebook.py)。
项目预生成了各维度/比特数的码本(codebooks/ 目录),例如 codebook_d128_b3.json(d=128、3-bit)的 8 个质心:
-0.1884, -0.1181, -0.0666, -0.0216, 0.0216, 0.0666, 0.1181, 0.1884注意两个自动出现的特征:
- 质心关于 0 对称——因为分布是对称的;
- 中间密、边缘疏——概率密度大的区域分配了更细的格子。
这就是"最优"的含义:同样的比特数下,MSE 比均匀分格更小。以该码本为例(codebook_d128_b3.json):
mse_per_coord ≈ 2.65e-4 mse_total ≈ 3.40e-2(对单位向量)换算成单位向量的相对误差约 5.8%,方向余弦相似度约 0.98——这正是后面 Key 压缩"几乎无损"的数学来源:误差被摊薄到了全部 128 个维度上,没有哪一维能单独捣乱。
🎯 最后 1 bit 的巧思:QJL 残差符号位让估计"无偏"
注意力真正关心的是内积 ⟨query, key⟩(打分),而不是 Key 能否被逐值还原。TurboQuant 把 3-bit 预算拆成2-bit 主码本 + 1-bit 残差符号(quantizer.py):
- 用 2-bit Lloyd-Max 码本量化旋转后的向量,得到近似 x̃;
- 取残差 r = x − x̃,乘一个随机高斯矩阵 S,只保留每个投影坐标的符号sign(S·r)——每维 1 bit,8 个符号打包进 1 字节(quantizer.py);
- 同时存下 ‖r‖ 用于还原量级。
反量化时的内积估计器为:
⟨y, x̃⟩ + ‖r‖·(√(π/2)/d) · ⟨Sᵀy, signs⟩第二项是 QJL 残差校正。它的美妙之处在于:对随机 S 取期望,sign 项的期望恰好为 0,因此
E[估计值] = ⟨y, x⟩ —— 整个估计器无偏无偏意味着量化误差没有系统性方向:2-bit 直接量化往往会整体压低打分、扭曲 softmax 权重,而这里误差是围绕真值的对称噪声,注意力排序保持稳定。项目实测验证了这一点:相对偏差 < 0.1%(README "Paper Validation" 一节)。
🧩 完整流水线与实测效果
串起来,TurboQuant 的量化管线是:
| 步骤 | 作用 | 比特开销(每维) | 源码 |
|---|---|---|---|
| 归一化 | 分离模长与方向,模长单独精确保存 | ≈0(每向量 1 个浮点) | quantizer.py |
| 随机正交旋转 Π | 坐标分布 → 已知 Beta 分布 | 0(矩阵离线共享) | rotation.py |
| Lloyd-Max 码本查表 | 找最近质心 → 位索引 | b−1(Key 为 2) | codebook.py |
| QJL 残差符号 | 无偏校正内积 | 1 | quantizer.py |
| 位打包存储 | 2-bit 每字节 4 个值 | — | quantizer.py |
Value 侧则采用更朴素的 2-bit 分组量化(逐组 scale/zero + 位打包,kv_cache.py),最近若干 token 以 bf16 精度留在环形缓冲中保质量(capture.py),读取时压缩段与精确段合并做注意力(score.py),解码路径还有 3 个融合 Triton 内核直接从打包数据算分(triton_kernels.py),vLLM 集成入口在 integration/vllm.py。
实测数字(README "Benchmark Results"):
| 组件 | 余弦相似度 | 备注 |
|---|---|---|
| 3-bit Key 压缩 | 1.000000 | 几乎无损 |
| 2-bit Value 量化 | 0.940 | 质量瓶颈,敏感场景可换 4-bit(0.997) |
| 3b Key + 2b Value 组合 | 0.940 | 退化主要来自 Value 侧 |
| 指标(Qwen3.5-27B,4 卡) | 基线 bf16 | TurboQuant |
|---|---|---|
| KV Cache 释放 | — | 30.0 GB |
| 最大 token 容量 | 457,072 | 914,144(2.0x) |
| 长上下文 Prefill | 1,804 tok/s | 1,907 tok/s(+5.7%) |
纯 dense 注意力模型上整体压缩比可达 4.4x。本地可运行pip install -e .后执行 proof.py 做 A/B 基准对比复现。
✅ 小结
TurboQuant "上篇"的原理可以浓缩成一条链:
随机正交旋转→ 坐标分布与数据无关(Beta)→Lloyd-Max 码本按分布最优分配比特 →QJL 符号位消除系统性偏差 → 量化误差变成可证明、无偏的对称噪声→ 注意力打分几乎无损。
一句话:它不是"更小心地量化数据",而是先随机化坐标基,把不可控的数据问题变成可解的统计问题——旋转的那一点随机性,就是"几乎无损"的全部秘密。
核心模块索引:
| 模块 | 职责 |
|---|---|
| turboquant/rotation.py | 随机正交旋转矩阵(QR)与 QJL 投影矩阵 |
| turboquant/codebook.py | Lloyd-Max 最优码本求解 |
| turboquant/quantizer.py | TurboQuantMSE / TurboQuantProd 两种量化器 |
| turboquant/codebooks/ | 预生成码本(d=64/128/576,1–4 bit) |
| turboquant/store.py | 压缩 KV 存储(分块 + 惰性展平) |
| turboquant/score.py | 压缩历史 + 精确缓冲的混合注意力 |
| turboquant/triton_kernels.py | 解码注意力 3 个融合 Triton 内核 |
| turboquant/integration/vllm.py | vLLM 适配器(monkey-patch,多模式开关) |
| proof.py | 基线 vs TurboQuant A/B 基准脚本 |
【免费下载链接】turboquant
TurboQuant: Near-optimal KV cache quantization for LLM inference (3-bit keys, 2-bit values) with Triton kernels + vLLM integration
相关推荐
LMDeploy KV Cache 量化实战:INT4/INT8 在线量化与 TurboQuant 原理、配置与性能分析
LMDeploy KV Cache 量化实战:INT4/INT8 在线量化与 TurboQuant 原理、配置与性能分析 KV Cache 量化是降低 LLM
人工智能大模型模型推理服务推理引擎本地部署模型量化TurboQuant+ 实战指南:基于 PolarQuant 与 Walsh-Hadamard 旋转的 KV Cache 压缩原理、配置与落地
TurboQuant+ 实战指南:基于 PolarQuant 与 Walsh Hadamard 旋转的 KV Cache 压缩原理、配置与落地 本文以仓库根目录
LMDeploy KV Cache 量化实战:INT4/INT8 在线量化与 TurboQuant 深入解析
LMDeploy KV Cache 量化实战:INT4/INT8 在线量化与 TurboQuant 深入解析 本篇技术指南以 LMDeploy 的 KV Cac
人工智能大模型模型推理服务推理引擎本地部署模型量化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考