ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

TurboQuant存储格式详解:2/4个值如何挤进一个字节完成比特打包

TurboQuant存储格式详解:2/4个值如何挤进一个字节完成比特打包 【免费下载链接】turboquantTurboQuant: Near-optimal KV cache quantization for LLM inference (3-bit keys, 2-bit values) with Triton kernels vLLM integration项目地址https://gitcode.com/gh_mirrors/tu/turboquant点击查看免费下载TurboQuant 是一款面向大模型推理的 KV Cache 量化压缩工具它的核心存储格式正是「比特打包」——把量化后的 2 比特值每 4 个塞进 1 个字节、4 比特值每 2 个塞进 1 个字节从而让 KV 缓存的显存占用直接缩小到原来的几分之一。本文将带你彻底搞懂这个字节内部的排布规则。一、为什么非要挤字节先看看没有打包时的尴尬局面精度每个值占用128 维向量占用float16基线2 字节256 字节4 比特量化1 字节128 字节2 比特量化0.5 字节半个字节64 字节问题在于计算机没有半个字节的存储单元一个 2 比特的量化值无法独立存放。如果直接按 1 字节存一个值就白白浪费了 6 个比特压缩率大打折扣。TurboQuant 的做法非常朴素一个字节装下 4 个 2 比特值或者 2 个 4 比特值。这样 2 比特的 value 缓存实际占用 64 字节256 字节的 1/4配合 README.md 中公布的整体验证数据KV 压缩比最高可达 4.4 倍。二、2 比特打包一个字节的四居室以 TurboQuant 的 value 缓存为例默认 2 比特见 turboquant/kv_cache.py假设一组量化值按顺序是a、b、c、d每个值 2 比特打包后是这样排布的字节8 位内部布局 ┌───────┬───────┬───────┬───────┐ │ bit0 │ bit1 │ bit2 │ bit3 │ └───────┴───────┴───────┴───────┘ 值a 值b 值c 值d 低 2 位次低2位次高2位高 2 位打包过程就是移位 按位或值a放在最低 2 位原封不动值b左移 2 位值c左移 4 位值d左移 6 位四个值按位或起来得到一个字节。对应源码只有短短几行turboquant/kv_cache.py 第 80~85 行v_4 v_q_flat.reshape(*orig_shape[:-1], d // 4, 4) packed v_4[..., 0] | (v_4[..., 1] 2) | (v_4[..., 2] 4) | (v_4[..., 3] 6)怎么拆回来解包用右移 掩码与打包完全对称v0 packed 0x03 # 取最低 2 位 → 值a v1 (packed 2) 0x03 # 右移 2 位再取 2 位 → 值b v2 (packed 4) 0x03 # 值c v3 (packed 6) 0x03 # 值d0x03即二进制00000011作用就是只保留 2 位。整个过程没有浮点运算GPU 上几个周期就能完成。三、4 比特打包一半一个的双居室当量化精度提高到 4 比特追求质量时 value 推荐 4 比特cos_sim 可达 0.997一个字节只装得下 2 个值┌─────────────────┬─────────────────┐ │ 值a低 4 位│ 值b高 4 位│ └─────────────────┴─────────────────┘ a | (b 4)解包同理低 4 位用掩码0x0F高 4 位右移 4 位后再取0x0F。3 比特怎么办这是个有意思的细节3 比特 4 个值需要 12 位塞不进 1 个字节塞 2 个字节又浪费。TurboQuant 选择了工程上的偷懒——把 3 比特索引向上取整为 4 比特存储2 个/字节牺牲 25% 的索引空间换取对齐的简单性这一点在 turboquant/quantizer.py 的_pack_indices函数中有明确注释。四、1 比特极客玩法8 个符号位挤进一个字节TurboQuant 的 key 压缩还有更极限的部分QJL 残差只存正负号每个维度 1 比特。这时一个字节能装下 8 个符号位打包方式是把 8 个符号乘上权重[1,2,4,8,16,32,64,128]再求和——本质上就是一位一比特的二进制数见 turboquant/quantizer.py 的_pack_qjl_signs。以 head_dim128 的 key 为例压缩后的存储账本如下组成部分精度每 token 占用MSE 索引2 比特3-bit key 拆出32 字节QJL 符号1 比特16 字节向量范数float164 字节合计约 52 字节而原始 float16 是 256 字节——单 key 压缩 5 倍这正是2/4 个值挤进一个字节带来的红利。五、打包格式如何服务于 GPU 加速比特打包不只是省内存更是为 GPU 内核量身定做的输入格式。TurboQuant 的 3 个融合 Triton 内核turboquant/triton_kernels.py直接读取打包后的字节在内核里用移位、掩码现拆索引、现查码本、现算注意力分数避免了把整个 d 维向量先解包成浮点张量再参与矩阵乘的中间开销。配套的存储管理层 turboquant/store.py 则以分块chunk方式追加这些打包数据首次读取时惰性展开为扁平视图保证高吞吐追加与低延迟读取两不误。六、小结TurboQuant 的存储格式可以浓缩为一句话用移位和按位或打包、用移位和掩码解包让 2 比特值 4 个一字节、4 比特值 2 个一字节、符号位 8 个一字节把 KV 缓存压到极限。几个值得记住的数字2 比特打包8 位 ÷ 2 4 个值/字节4 比特打包8 位 ÷ 4 2 个值/字节1 比特符号8 位 ÷ 1 8 个符号/字节3 比特向上取整为 4 比特存储换取对齐简单性理解了这套字节级布局你就读懂了 TurboQuant 压缩效率的底层来源。想动手验证的话可以克隆仓库后直接运行python validate_paper.py纯 CPU 即可跑通论文的 9 项定理验证。相关源码导航文件作用turboquant/kv_cache.pyvalue 的 2/4 比特打包与解包turboquant/quantizer.pykey 的 MSE 索引打包与 QJL 符号打包turboquant/triton_kernels.py直接消费打包字节的融合解码内核turboquant/store.py压缩 KV 的分块存储与内存核算README.md基准测试与压缩比数据赞分享【免费下载链接】turboquantTurboQuant: Near-optimal KV cache quantization for LLM inference (3-bit keys, 2-bit values) with Triton kernels vLLM integration项目地址https://gitcode.com/gh_mirrors/tu/turboquant点击查看免费下载相关推荐ONNX FLOAT4E2M1 技术详解4 位浮点格式、转换规则与字节打包实现ONNX FLOAT4E2M1 技术详解4 位浮点格式、转换规则与字节打包实现 导读 FLOAT4E2M1 是 ONNX 在 1.18.0 版本中引入的一种人工智能机器学习深度学习puter.kv.MAX_KEY_SIZE 详解Puter 键值存储的 Key 字节上限puter.kv.MAX_KEY_SIZE 详解Puter 键值存储的 Key 字节上限 导读 puter.kv.MAX_KEY_SIZE 是 Puter 前后端前端云原生Transfer Learning 实战MLU Accelerated CV 课程中的迁移学习技术Transfer Learning 实战MLU Accelerated CV 课程中的迁移学习技术 迁移学习是计算机视觉领域的革命性技术它让开发者能够利用预创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进