大模型应用
LLM 推理 KV cache 内存不足时,用…
在 PyTorch 中实现 TurboQuant,对 LLM 的 KV cache 做 3-bit 压缩,通过随机旋转 + Lloyd-Max + QJL 残差校正保持内积/注意力估计准确。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
LLM 推理 KV cache 内存不足特定
解决思路
- 克隆仓库并安装依赖:`git clone https://github.com/tonbistudio/turboquant-pytorch`,`cd turboquant-pytorch`,`pip install -r requirements.txt`;如需 CUDA PyTorch,运行 `pip install torch --index-url https://download.pytorch.org/whl/cu128`。
- 运行合成算法验证:`python -m turboquant.test_turboquant`(无需 GPU,GPU 可做速度基准)。
- 运行真实模型验证:`python -m turboquant.validate`(需 CUDA GPU ≥6GB VRAM,首次下载约 2GB Qwen2.5-3B-Instruct 模型)。
- 构建 Lloyd-Max 码本:调用 `build_lloyd_max_codebook(dim=128, bits=3)`,返回 `(boundaries, centroids)`。
- 阶段 1 MSE 量化:初始化 `TurboQuantMSE(dim=128, bits=3)`;对形状 `(batch, dim)` 的 keys 调用 `quantize(keys)` 得到整数编码;调用 `dequantize(codes)` 得到近似重建。
- 阶段 2 无偏内积估计:初始化 `TurboQuantProd(dim=128, bits=3, proj_dim=64)`;调用 `compress(keys)` 得到包含 `'codes'`、`'signs'`、`'residual_norms'` 的字典;调用 `inner_product(query, compressed)` 得到无偏内积估计。
- 使用 KV cache 包装器:初始化 `TurboQuantKVCache(dim=128, bits=3, proj_dim=64)`;用 `append_key(new_key)` 和 `append_value(new_val)` 逐 token 添加;用 `attention_scores(query)` 计算无偏注意力分数;用 `get_values()` 获取 MSE 重建的 values。
- 使用生产压缩器压缩 keys:初始化 `TurboQuantCompressorV2(dim=128, bits=3, proj_dim=64)`;对形状 `(num_heads, seq_len, head_dim)` 的层 keys 调用 `compress(layer_keys)`;用 `asymmetric_attention_scores(query, compressed_keys)` 直接从压缩 keys 计算注意力分数,无需解压。
- 使用生产压缩器压缩 values:初始化 `TurboQuantCompressorMSE(dim=128, bits=3)`;调用 `compress(layer_values)` 压缩;调用 `decompress(compressed_vals)` 重建 values。
- 压缩整个模型的 KV cache:定义函数遍历每层 `(layer_keys, layer_vals)`,用 `key_comp.compress` 和 `val_comp.compress` 分别压缩,返回压缩后的列表和压缩器实例。
- 用压缩 cache 运行注意力:用 `key_comp.asymmetric_attention_scores(query, compressed_keys)` 得到分数;对最后一维做 `torch.softmax`;用 `val_comp.decompress(compressed_vals)` 得到 values;用 `torch.einsum('hs,hsd->hd', attn_weights, values)` 计算加权输出。
- 验证注意力保真度:对每个 query,计算真实 `(keys @ q)` 的 softmax 与 TurboQuant `inner_product(q, compressed)` 的 softmax;用 `F.cosine_similarity` 比较两个注意力分布,并记录 top-1 是否匹配;返回平均 cosine 相似度和 top-1 准确率。
- 运行 needle-in-haystack 检索测试:构建随机单位向量 haystack,在随机位置插入与 query 相似的 needle,压缩后分别用真实 `haystack @ query` 和 `inner_product(query, compressed)` 找最近邻,返回两者是否一致;多次试验统计检索准确率。
- 估算内存节省:按公式计算 FP16 基线大小、Stage 1 codes 字节数 `(num_layers*2*num_kv_heads*seq_len*head_dim*bits)//8`、Stage 2 signs 字节数 `(num_layers*num_kv_heads*seq_len*proj_dim)//8`、residual norms 字节数 `num_layers*num_kv_heads*seq_len*2`,求和得到压缩大小并计算压缩比。
- 选择 QJL 投影维度 `proj_dim`:默认 `proj_dim = head_dim // 2`(如 `head_dim=128` → `proj_dim=64`,`head_dim=64` → `proj_dim=32`,`head_dim=256` → `proj_dim=128`);增大可降低内积估计方差但增加内存。
- 选择位宽:4-bit 用于质量关键任务(3.8x,cosine 0.999,top-1 87%);3-bit 推荐默认(5.0x,cosine 0.995,top-1 82%);2-bit 用于极端内存压力(7.3x,cosine 0.988,top-1 66%)。
- 实现算法核心:对输入向量应用随机正交旋转 `R`,使坐标近似独立且服从 `N(0,1/d)`;然后对每个坐标使用 Lloyd-Max 最优标量量化。
- 对 keys 应用 QJL 残差校正:使用 1-bit 符号投影使内积估计无偏;values 不做 QJL,只用 Stage 1 MSE 重建,因为 softmax 后逐向量 MSE 误差会平均掉。
- 确保输入向量 L2 归一化:压缩前用 `F.normalize(x, dim=-1)`;`compressors.py` 内部处理归一化,`TurboQuantProd` 期望单位向量。
- 故障排除:`scipy` 导入错误时运行 `pip install scipy`;CUDA OOM 时减少 `seq_len` 或换更小模型;内积估计方差高时增大 `proj_dim` 或检查归一化;码本构建慢时用 `pickle` 缓存 `(boundaries, centroids)` 到如 `codebook_128_3bit.pkl`;注意力保真度低时确保向量已 L2 归一化。
适用边界 · 注意事项
- 不适用于需要高保真逐向量重建的场景;TurboQuant 保内积而非向量保真,单独向量可能差异较大。
- 不适用于 values 需要高保真 MSE 的场景;values 仅用 Stage 1 量化,没有 QJL 残差校正。
- 不适用于没有 PyTorch/scipy 环境或无法安装 turboquant-pytorch 仓库、且不能运行 CUDA 验证的情况。