一人工程 · solus opus

← 全部作品

image数学向量检索量化

高维球面上的随机旋转 + Beta 量化

Google TurboQuant 两步:旋转让分量独立成 Beta 分布,再按 Beta 形状 Lloyd-Max 量化。turbovec 在这上面叠手写 SIMD,10M 文档 31GB→4GB,每个 cell 都比 FAISS IndexPQFastScan 快。

高维球面上的随机旋转 + Beta 量化

高维球面上的随机旋转 + Beta 量化

今天 HN best #28 看到 ryancodrai/turbovec—— 一个跑在 Google TurboQuant(arXiv 2504.19874)之上的 Rust + Python 实现, 不是复刻玩具索引,是冲着 FAISS IndexPQFastScan 去的: 10M 个 float32 向量原本 31 GB,它压到 4 GB,搜索还更快。

两步魔法

第一步:随机旋转。 高维单位球面上的方向向量, 每两个坐标分量之间都有相关结构; 乘一个固定的随机正交矩阵 R,所有分量就近似互相独立了, 并且每个分量都服从 Beta 分布(不是均匀分布,峰值在中间)。

第二步:按 Beta 分布的形状做 scalar quantization。 不切等宽桶,而是用 Lloyd-Max 算法按 Beta 的密度找最优分界点, 2-bit 切 4 桶,4-bit 切 16 桶。

没有训练、没有 codebook、没有任何 per-corpus 步骤。 这是 "data-oblivious" 的意思:相同的 R、相同的桶切法, 对任何向量分布都成立,所以在线加向量不需要重建索引。

画里

超球上一千多个方向向量像夜空; 一道旋转把每颗星绕轴扭一下; 然后每颗星被分到同心球壳里,最内壳偏暖橙(坐标接近 0),最外壳偏冷青(坐标接近 ±1)。 "中段细密、两端稀疏" 的桶分布就是 Beta 形状的反面—— 桶越密的地方分布概率越大。

性能上发生了什么

turbovec 报告里的硬数字:

  • 4-bit:ARM 3.4×、x86 3.4× vs FAISS IndexPQFastScan(按 cell 平均)
  • 2-bit:ARM +26%、x86 +20%
  • 单条插入:6.3–19.7 µs,比 FAISS 单条插入快 7.6–13.9×
  • IdMapIndex.remove(id) 是 O(1) swap-and-pop,0.44–1.22 µs

打的是手写 SIMD:ARM 上 NEON 的 SDOT/SMMLA 直接在 vector-major 布局上算点积, x86 上是 AVX-512 VNNI;2-bit 还要靠 vpermb 做 LUT 扫描。

一个不显眼的细节

它用的是比 TurboQuant 论文里更强的 baseline—— FAISS IndexPQ(LUT256, nbits=8, float32 LUT), 所以这个 3.4× 不是挑软柿子捏出来的。 作者还做了 TQ+(calibrated TurboQuant),把低维 GloVe 上 2-bit R@1 从输给 FAISS 0.008 翻到赢 0.008——也就 1.6 个百分点的来回,但确实能救回来。

跟我画的关系

图是 "旋转 + 量化" 这两步的视觉化。 不是论文图,不是库 logo,只是这步把 vector-major 单元换到球壳坐标的感觉。