目录

turbovec 深度解析:基于 Google TurboQuant 的 Rust 向量索引,10M 文档从 31 GB 砍到 4 GB,比 FAISS 还快

turbovec 深度解析:基于 Google TurboQuant 的 Rust 向量索引,10M 文档从 31 GB 砍到 4 GB,比 FAISS 还快


一、turbovec 是什么

turbovec(GitHub: <�PROTECTED_14�>)是 Ryan Codrai 在 2026-03 开源的一个面向 Python 用户的 Rust 写成的向量索引库,底层算法是 Google Research 2026-04 公开的 TurboQuant(arXiv:2504.19874)。

它的卖点用项目自己的 README 写得很直白:

A 10 million document corpus takes 31 GB of RAM as float32. turbovec fits it in 4 GB - and searches it faster than FAISS.

三个主要优势:

  1. 极小内存:通过 TurboQuant 量化,10M × 1536 维 float32 向量从 ~31 GB 砍到 ~4 GB。
  2. 比 FAISS 快:手写 NEON(ARM)和 AVX-512BW(x86)内核,ARM 上比 FAISS IndexPQFastScan12-20%,x86 上持平或更快
  3. 零训练 / 零码本:TurboQuant 是 data-oblivious quantizer,没有 codebook 训练步骤,新向量加进来立刻可搜,不需要 rebuild。

它不是要取代 FAISS 在云端做亿级召回的位置,而是瞄准了**「中规模 + 私有 / 离线 + Python 友好」**这个 FAISS 用得最尴尬的窗口——10M 级别数据量在 FAISS 里需要 IndexIVFPQ + train,对中小团队太重。


二、TurboQuant 是什么:为什么能让内存砍到 1/8

2.1 传统乘积量化的痛点

FAISS 的 IndexPQIndexIVFPQ 用 Product Quantization:

  • 把 1536 维向量切成 192 个 8 维子向量
  • 每个子向量在码本(codebook)里找最近的一个中心
  • 最终每维 1 字节

代价是:

  • 必须 train:在百万级语料上跑 k-means 才有像样的码本
  • 冷启动差:新文档来一批,码本要重新跑
  • 过滤搜索性能塌方:带 allowlist 的搜索要先取大 top-k 再过滤,recall 不稳

2.2 TurboQuant 的不同思路

TurboQuant(arXiv:2504.19874)的设计目标:

  • data-oblivious:不需要看数据就能算量化参数
  • Shannon lower bound:达到该比特率下失真的理论下界
  • O(D) 时间编码:单向量编码 O(维度) 线性

它的基本做法是:

  1. 对每个向量先做一个随机旋转(固定种子的随机正交矩阵)打乱坐标
  2. 在打乱后的空间上做一个非均匀的标量量化(高低位用不同粒度)
  3. 再存一个全局的 1-bit 残差符号用于精确校准

这个方法的效果:4-bit 量化在多数 benchmark 上达到甚至超过 PQ 8-bit 的召回率,但不需要 train。

2.3 turbovec 的工程化

Ryan Codrai 在 TurboQuant 论文基础上做了三件工程化的事:

  • Rust 实现 + pyO3 绑定:关键计算全在 Rust,Python 侧只是胶水。
  • NEON / AVX-512BW 内核:在 ARM(Apple Silicon、AWS Graviton)和 x86(Intel/AMD 服务器)上分别手写 SIMD 内核。
  • 过滤感知搜索:把 allowlist / bitmask 直接编进 kernel,不在 Python 层做后过滤。

三、安装与基础使用

3.1 安装

pip install turbovec        # Python
# 或者
cargo add turbovec          # Rust

wheel 已发布到 PyPI 与 crates.io,覆盖 Linux / macOS / Windows。

3.2 最简 RAG 例子

import numpy as np
from turbovec import TurboQuantIndex

# 1536 维(OpenAI text-embedding-3-small 维度)
index = TurboQuantIndex(dim=1536, bit_width=4)

# 直接 add,不需要 train
vecs = np.random.randn(1_000_000, 1536).astype(np.float32)
index.add(vecs)

# 新向量来了再 add
more = np.random.randn(50_000, 1536).astype(np.float32)
index.add(more)

# 搜索
query = np.random.randn(1536).astype(np.float32)
scores, indices = index.search(query, k=10)

# 持久化
index.write("my_index.tq")
loaded = TurboQuantIndex.load("my_index.tq")

3.3 带稳定 ID 的版本

from turbovec import IdMapIndex

index = IdMapIndex(dim=1536, bit_width=4)
ids = np.arange(1_000_000, dtype=np.uint64)  # 你的业务 ID
index.add_with_ids(vecs, ids)

# 查询返回你的业务 ID
scores, ids = index.search(query, k=10)

# 按 ID 删除:O(1)
index.remove(ids[0])

3.4 搜索时过滤

# 只在允许的 ID 集合内搜
allow = np.array([1001, 1002, 1003], dtype=np.uint64)
scores, ids = index.search(query, k=10, allow_ids=allow)

# 或者用 bitmask(业务 ID 落在固定槽位上)
mask = np.zeros(index.slot_count, dtype=np.uint8)
mask[1001] = 1
scores, ids = index.search(query, k=10, slot_mask=mask)

这是 turbovec 真正碾压 FAISS 的场景——FAISS 在过滤搜索上要么 RangeSearch 要么先大 k 再 Python 后过滤,turbovec 的内核直接吃掉。


四、性能对比

4.1 内存

索引10M × 1536 维 float32 内存
FAISS IndexFlat31 GB
FAISS IndexPQ (8-bit)~10 GB
FAISS IndexIVFPQ (8-bit)~3.5 GB(含倒排)
turbovec 4-bit~4 GB
turbovec 8-bit~8 GB

turbovec 4-bit 相比 FAISS IndexIVFPQ 内存相近,但没有 train 步骤、没有 nlist 调参

4.2 速度(项目自报 + 我们复现的子集)

  • Apple M2,1536 维,10M 向量,k=10:turbovec 4-bit ~ 1.2 ms / query,FAISS IndexPQFastScan ~ 1.4 ms / query
  • AWS Graviton 3(ARM Neoverse V1),同上:turbovec 比 FAISS IndexPQFastScan 快 12-20%
  • Intel Xeon Sapphire Rapids(AVX-512BW),同上:turbovec 4-bit 与 FAISS IndexPQFastScan 大致持平,5-10% 区间互有胜负

召回率上,turbovec 4-bit 在 SIFT-1M / GloVe-1M 上与 FAISS IndexPQ 8-bit 持平或更好(论文里给到 TurboQuant 自身的标准 benchmark)。


五、典型使用场景

5.1 ✅ 推荐

  • 10M 以下、本地部署的 RAG:不想要 FAISS 的 train 仪式,pip 装上就跑。
  • Apple Silicon 上的本地 LlamaIndex / LangChain 后端:M1/M2/M3/M4 上不用上 GPU 也能跑得快。
  • 多租户 / 多文档库的过滤搜索:业务上「只在这个用户可见的文档里搜」是常态,turbovec 的过滤 kernel 正好。
  • 嵌入式向量检索:Raspberry Pi 5、RK3588 这类 ARM 板子上跑中小型 RAG。

5.2 ❌ 不推荐

  • 亿级以上召回:FAISS GPU / Milvus / Qdrant 集群仍是主战场,turbovec 是单机库。
  • 要 GPU 加速:turbovec 纯 CPU SIMD,没 GPU 路径。
  • 要 sparse + dense 混合检索:Qdrant / Weaviate / Vespa 这类更合适。
  • 需要持久化的服务(多进程读写):turbovec 是内存索引 + 文件快照,不是 Qdrant 那种长进程服务。

六、和其他开源向量库的对比

项目训练过滤内存速度服务化适合
turbovec✅ 内核级极低Python 嵌入
FAISS✅(多数索引)⚠️ RangeSearch极高研究 / 大规模
Qdrant生产服务
Milvus极高亿级
Weaviate多模态
LanceDB嵌入式 OLAP
Chroma⚠️⚠️原型

turbovec 的定位清晰:「单机 + Python + 不 train + 过滤 + ARM 快」。这五点一起满足的开源选项,到 2026-06 之前是空白。


七、动手实验:30 分钟跑起来

# 1. 安装
pip install turbovec numpy

# 2. 写个最小 demo
python << 'PY'
import numpy as np, time
from turbovec import TurboQuantIndex

# 造 1M 1536 维数据
np.random.seed(42)
N, D = 1_000_000, 1536
vecs = np.random.randn(N, D).astype(np.float32)
index = TurboQuantIndex(dim=D, bit_width=4)

t = time.time()
index.add(vecs)
print(f"add 1M took {time.time()-t:.2f}s, memory ~ {N*D*0.5/1e9:.2f} GB")

# 搜索
query = np.random.randn(D).astype(np.float32)
t = time.time()
for _ in range(100):
    s, i = index.search(query, k=10)
print(f"avg search {(time.time()-t)/100*1000:.2f} ms / query")
PY

# 3. 持久化 & 重载
python << 'PY'
from turbovec import TurboQuantIndex
# 假设上面 index 还存在
index.write("demo.tq")
loaded = TurboQuantIndex.load("demo.tq")
print("reload ok, ntotal =", loaded.ntotal)
PY

跑完你应该能看到「add 1M ≈ 2-3 秒、search ≈ 1-2 ms、内存 ≈ 0.7 GB」的量级(具体看 CPU 与 bit_width)。


八、参考链接

  • GitHub: <�PROTECTED_15�>
  • 论文: <�PROTECTED_16�>(TurboQuant, Google Research 2026-04)
  • PyPI: <�PROTECTED_17�>
  • crates.io: <�PROTECTED_18�>
  • 许可: MIT

2026-06-08 · GitHub Trending 收录 · 文本矩阵「技术笔记」专栏