实现 TurboQuant (第5部分)
这是一个将 Google Research 的 TurboQuant (arXiv:2504.19874) 论文用 PyTorch 实现的项目。
在 LLM 推理时,最主要的内存瓶颈是 KV Cache,它在不增加量化开销的情况下被压缩。
TurboQuant = PolarQuant (b-1 bit) + QJL (1 bit)
主信号压缩 残差校正 (无偏)
| 项目 | 传统方法 (KIVI 等) | TurboQuant |
|---|---|---|
| 量化常数开销 | +1 ~ +2 bit | 0 bit |
| 3-bit 压缩时实际位数 | 4 ~ 5 bit | 3 bit |
| 内积估计偏差 | 存在 | 不存在 |
| KV Cache 压缩率 | ~4x | ~6x |
需求
硬件
| 项目 | 最低 | 推荐 |
|---|---|---|
| GPU | 支持 CUDA 的 NVIDIA GPU | RTX 3090 24GB |
| RAM | 16GB | 32GB |
| 磁盘 | 20GB(模型缓存) | 50GB |
软件
| 项目 | 版本 |
|---|---|
| OS | Ubuntu 20.04+(包括 WSL2) |
| Python | 3.10 ~ 3.12 |
| NVIDIA 驱动 | 595+ |
| CUDA | 13.0+(驱动 13.2 向下兼容) |
| PyTorch | 2.10+(cu130) |
| Transformers | 4.40+ |
| vLLM | 0.8+(serve_vllm.py 专用,可选) |
| gcc | 必需(用于 Unsloth/Triton 构建) |
在 Windows 上通过 WSL2 Ubuntu 运行。 PyTorch 自带 CUDA 运行时,因此不需要单独安装 CUDA Toolkit。 WSL 必需:使用 Unsloth 时需要 C 编译器:
sudo apt update && sudo apt install -y gcc
DeepSeek 模型指南 (RTX 3090 24GB)
| 模型 | 参数 | VRAM | 24GB 可用 |
|---|---|---|---|
DeepSeek-R1-Distill-Qwen-1.5B |
1.5B | ~3GB | O |
DeepSeek-R1-Distill-Qwen-7B |
7B | ~14GB | O (默认) |
DeepSeek-R1-Distill-Qwen-14B |
14B | ~9GB(4-bit) | O (--load-in-4bit) |
DeepSeek-R1-Distill-Llama-70B |
70B | ~35GB+ | X |
项目结构
[Github] https://github.com/javafa/turboquant
turboquant/
├── requirements.txt # Python 依赖
│
├── turboquant.py # 核心库 (PolarQuant + QJL + TurboQuant)
├── compare.py # 原始 vs TurboQuant 比较(质量 + 时间 + 内存)
├── benchmark.py # 综合基准测试(6种组合 x 内存/速度比较)
├── demo.py # HuggingFace 模型 KV cache 提取 + 压缩演示
├── serve_vllm.py # vLLM OpenAI-compatible 服务器 + 分析
│
└── scripts/
├── setup_wsl.sh # WSL Ubuntu 环境设置
└── setup_conda.bat # Windows Conda 环境设置
文件说明
| 文件 | 角色 |
|---|---|
turboquant.py |
PolarQuant, QJL, TurboQuant, TurboQuantKVCache 类实现。支持批处理。 |
compare.py |
主脚本。 模型推理后比较原始 KV cache 与 TurboQuant 压缩结果。一次性输出 Attention score 质量、处理时间、内存节省。 |
benchmark.py |
综合基准测试。 Baseline/BnB 4-bit/TurboQuant/Unsloth 等 6种组合的 VRAM,KV cache,速度在短/长提示中比较。 |
demo.py |
从 HuggingFace 模型中提取 KV cache,并测量 TurboQuant 压缩率/准确度。 |
serve_vllm.py |
基于 vLLM 的 OpenAI-compatible API 服务器 + TurboQuant KV cache 分析。 |
2. 综合基准测试(6种组合比较)
比较组合:
| # | 配置 | 权重 | KV Cache |
|---|---|---|---|
| 1 | Baseline (FP16) | FP16 | FP16 |
| 2 | BnB 4-bit | 4-bit | FP16 |
| 3 | TurboQuant 3-bit | FP16 | 3-bit |
| 4 | BnB 4-bit + TurboQuant | 4-bit | 3-bit |
| 5 | Unsloth 4-bit | 4-bit | FP16 |
| 6 | Unsloth 4-bit + TurboQuant | 4-bit | 3-bit |
基准测试结果(DeepSeek-R1-Distill-Qwen-1.5B,RTX 3090 24GB):
短提示(4 个 token 输入 → 64 个 token 生成):
Config | Model VRAM | Peak VRAM | KV Cache | Speed | Time
-----------------------------|------------|------------|------------|------------|----------
Baseline (FP16) | 3022MB | 3396MB | 1.5 MB | 39.4t/s | 1.6s
BnB 4-bit | 1078MB | 1578MB | 1.5 MB | 28.1t/s | 2.3s
TurboQuant 3-bit | 3022MB | 3396MB | 0.9MB(40%↓) | 48.5t/s | 1.3s
BnB 4-bit + TurboQuant | 1078MB | 1578MB | 0.9MB(40%↓) | 27.8t/s | 2.3s
Unsloth 4-bit | 1754MB | 1974MB | 1.5 MB | 23.2t/s | 2.8s
Unsloth 4-bit + TurboQuant | 1754MB | 1974MB | 0.9MB(40%↓) | 37.2t/s | 1.7s
长提示(191 个 token 输入 → 256 个 token 生成):
Config | Model VRAM | Peak VRAM | KV Cache | Speed | Time
-----------------------------|------------|------------|------------|------------|----------
Baseline (FP16) | 3391MB | 3418MB | 12.2 MB | 27.0t/s | 9.5s
BnB 4-bit | 1555MB | 1595MB | 12.2 MB | 17.0t/s | 15.1s
TurboQuant 3-bit | 3399MB | 3418MB | 7.3MB(40%↓) | 28.5t/s | 9.0s
BnB 4-bit + TurboQuant | 1555MB | 1595MB | 7.3MB(40%↓) | 16.6t/s | 15.4s
Unsloth 4-bit | 1754MB | 1979MB | 12.2 MB | 22.3t/s | 11.5s
Unsloth 4-bit + TurboQuant | 1754MB | 1979MB | 7.3MB(40%↓) | 23.6t/s | 10.8s
与基线(FP16)的比较:
| 配置 | 显存 | KV Cache | 速度 (短) | 速度 (长) |
|---|---|---|---|---|
| BnB 4-bit | -53.5% | 相同 | -28.6% | -37.3% |
| TurboQuant 3-bit | 相同 | -39.9% | +23.1% | +5.3% |
| BnB 4-bit + TurboQuant | -53.5% | -39.9% | -29.4% | -38.5% |
| Unsloth 4-bit | -42% | 相同 | -41.1% | -17.5% |
| Unsloth 4-bit + TurboQuant | -42% | -39.9% | -5.5% | -12.7% |
- TurboQuant是唯一比基线更快的配置 (短 +23%, 长 +5%)
- 内存优化: BnB 4-bit + TurboQuant (显存 -53%, KV -40%)
- 平衡: Unsloth + TurboQuant (显存 -42%, KV -40%, 速度小幅下降)
- BnB 4-bit在长序列中由于去量化成本累积导致速度下降严重
- Unsloth短结果包含Triton内核初始编译开销
输出项目:
| 部分 | 内容 |
|---|---|
| 1. 加载模型 | 模型加载时间, 显存使用量 |
| 2. 运行推理 | 原始生成结果, 速度 (tok/s) |
| 3. 注意力得分比较 | 余弦相似度, Top-1/5 匹配, KL散度 (2/3/4-bit) |
| 4. 时间基准 | 原始 vs TurboQuant 每个查询的处理时间 (ms) |
| 5. 生成级别 | 注意力模式 Top-1 一致率 |
| 6. 内存节省 | FP16 vs TurboQuant 内存比较 |
| 7. 缩放预测 | 长上下文(1k~128k)内存预测 |
CLI 选项
benchmark.py
--models all | 1.5b | 7b (默认: all)
--skip-baseline 跳过FP16基线
--short-tokens 短提示生成的令牌数 (默认: 64)
--long-tokens 长提示生成的令牌数 (默认: 256)
--turboquant-bits TurboQuant比特数 (默认: 3)
compare.py
--model 模型ID (默认: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B)
--bits TurboQuant比特数, 2-8 (默认: 3)
--max-new-tokens 生成的令牌数 (默认: 64)
--prompt 输入提示
--dtype float16 | bfloat16 (默认: float16)
--load-in-4bit 4-bit量化加载 (14B模型用)
--load-in-8bit 8-bit量化加载
--layers-to-compare 比较的层数 (默认: 4)
demo.py
--model 模型ID
--bits TurboQuant比特数 (默认: 3)
--max-new-tokens 生成的令牌数 (默认: 64)
--prompt 输入提示
--dtype float16 | bfloat16
--load-in-4bit 4-bit量化加载
--load-in-8bit 8-bit量化加载
serve_vllm.py
--model 模型ID
--host 服务器主机 (默认: 0.0.0.0)
--port 服务器端口 (默认: 8000)
--max-model-len 最大序列长度 (默认: 4096)
--gpu-memory-utilization GPU内存利用率 (默认: 0.90)
--quantization vLLM量化: awq, gptq 等
--analyze-only 仅执行分析,不启动服务器
--turboquant-bits TurboQuant比特数 (默认: 3)
算法概述
[压缩]
k (原始键向量)
├── PolarQuant (b-1 bits): 随机旋转 → 极坐标 → 均匀量化
│ 存储: (r, codes) 开销: ~0.25 bit (一个r)
│
├── 残差: residual = k - decompress(r, codes)
│
└── QJL (1 bit): sign(S @ residual)
存储: sign_bits 开销: 0 bit
[估计 <q, k>]
<q, k> ≈ <q, k_hat> + sqrt(pi/2) * (S@q)^T * sign_bits
PolarQuant QJL 残差修正 (无偏)
参考文献
- TurboQuant: arXiv:2504.19874 — ICLR 2026
- QJL: arXiv:2406.03482 — Quantized Johnson-Lindenstrauss
- PolarQuant: arXiv:2502.02617 — AISTATS 2026
- DeepSeek-R1: deepseek-ai/DeepSeek-R1