news 2026/6/10 8:46:09

我拿 TurboQuant 把 1000 万文档塞进 4GB 内存,FAISS 用了 31GB

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
我拿 TurboQuant 把 1000 万文档塞进 4GB 内存,FAISS 用了 31GB

turbovec 是第一个把 Google 论文里的 TurboQuant 算法落地的向量检索库。Rust + 手写 SIMD,零训练零调参,比 FAISS 快 20%,内存只要 1/8。

读完你会知道:怎么 10 行代码跑起来、TurboQuant 为什么能做到不训练、手写 SIMD 的架构思路、以及什么时候用它什么时候别用。


🎯 这个项目解决什么问题?

你有没有在本地跑过 RAG?

加载一个 embedding 模型,把几千篇文档向量化存进 FAISS,查个 top-10 大概 50ms——还行。然后文档涨到 1 万、10 万、100 万。内存从 300MB 涨到 3GB 再到 30GB,查询延迟从 50ms 爬到 200ms。你开始调 IVF 参数、倒排索引、PQ 训练……这些都不是"本地 RAG"该有的体验。

turbovec 给出的答案是:同一个 1000 万文档的语料库(1536 维 float32),FAISS 需要 31GB RAM,turbovec 只需要 4GB。而且搜索速度比 FAISS IndexPQFastScan 快 12%–20%。

核心武器是 Google Research 的论文TurboQuant(arXiv:2504.19874),2025 年 4 月提交。一种>

原始向量 1536 × f32
6KB/条

随机旋转
使坐标分布集中

LLoyd-Max 最优标量量化
每坐标 → 4-bit

TurboQuant编码
1536 × 4bit = 768B/条

内存节省 87.5%
1000万条:60GB → 7.5GB


🔧 快速上手

先确认环境:需要Rust 1.75+(编译二进制)或直接用 Python bindings。

安装

# Python 用户:直接 pippipinstallturbovec# Rust 用户:在 Cargo.toml 中添加# turbovec = "0.4"

10 行代码跑通

importnumpyasnpfromturbovecimportTurboQuantIndex# 创建索引:1536维(OpenAI ada/text-embedding-3-small 的维度)index=TurboQuantIndex(dim=1536,bit_width=4)# 模拟 10 万条向量(实际用你的 embedding 模型生成)vectors=np.random.randn(100_000,1536).astype(np.float32)index.add(vectors)# 查询 top-10query=np.random.randn(1536).astype(np.float32)scores,indices=index.search(query,k=10)print(f"Top-10 indices:{indices}, scores:{scores}")# 持久化到磁盘index.write("my_index.tq")loaded=TurboQuantIndex.load("my_index.tq")

如果你需要稳定的外部 ID(而不是add顺序),用IdMapIndex

fromturbovecimportIdMapIndex idx=IdMapIndex(dim=1536,bit_width=4)external_ids=np.array([1001,1002,1003],dtype=np.uint64)idx.add_with_ids(vectors[:3],external_ids)# 搜索返回的是你的外部 IDscores,ids=idx.search(query,k=2)# ids 会是 [1003, 1001] 而不是 [2, 0]# O(1) 按 ID 删除idx.remove(1002)

过滤搜索:把 BM25、SQL、ACL 的结果当白名单

这是 turbovec 最实用的功能之一——你可以把上游系统的召回结果作为 allowlist 传给search,turbovec 只在这些候选里做向量检索:

# 假设你从 PostgreSQL 查出 500 个候选 IDcandidate_ids=np.array([101,205,307,...],dtype=np.uint64)scores,ids=idx.search(query,k=10,allowed=candidate_ids)# 结果只来自 candidate_ids,不会召回其他文档

⚠️常见踩坑

  • bit_width只支持 2、4、8,传别的值会 panic
  • 向量维度目前上限约 32768(受内部 SIMD 块布局约束)
  • search需要&T而非&mut T,天然支持并发读取——多个线程可以同时查同一个索引

⚙️ 技术原理

核心问题:量化器怎么做到不训练的?

FAISS 的 Product Quantization(PQ)需要先拿一批训练数据,用 K-means 学出子空间的聚类中心(codebook)。这个训练过程有四个问题:

  1. 需要代表性数据:训练集分布必须和实际查询集分布一致
  2. 训练耗时:K-means 在百万级向量上跑很慢
  3. 不支持在线添加:加新向量后 codebook 可能过时,需要重建索引
  4. 调参地狱:子空间数 m、每个子空间的 bits 数、IVF 倒排单元数……

TurboQuant 用了一个巧妙的数学技巧绕过了训练:随机旋转 + 坐标独立性

三步看懂 TurboQuant 原理

第一步:随机旋转

对每个输入向量x ⃗ ∈ R d \vec{x} \in \mathbb{R}^dxRd,用一个固定的随机正交矩阵R RR做旋转变换:

y ⃗ = R ⋅ x ⃗ \vec{y} = R \cdot \vec{x}y=Rx

旋转后,y ⃗ \vec{y}y的每个坐标都服从一个集中化的 Beta 分布。这是高维几何的一个经典现象:高维球面上均匀分布的向量,其单个坐标的分布会向 0 集中。

第二步:坐标间近似独立

在高维空间(d ≥ 256)中,旋转后不同坐标之间的相关性极低。这意味着你可以把每个坐标当作独立的一维信号来量化,不需要对跨坐标的"向量结构"建模。这就是 TurboQuant 不需要训练 codebook 的根本原因——既然坐标之间几乎独立,最优的标量量化器(Lloyd-Max)就够了。

第三步:两步法消除内积偏差

对最近邻搜索,我们需要的是"近似内积",而 MSE 最优的量化器会引入系统性偏差——量化后的内积和原始内积之间存在偏移。TurboQuant 的解法分两步:

  1. 先用 MSE 最优的标量量化器把每坐标压到 4-bit(或 2-bit)
  2. 对残差(原始值减量化值)再做一次1-bit Quantized JL 变换——用一个随机±1向量和残差做内积,得到一个无偏估计

两步结果的就是内积的无偏估计。

输入向量 x ∈ ℝ^d

随机旋转: y = Rx

每坐标独立 Lloyd-Max 量化
y_i → h_i ∈ {0,...,15}(4-bit)

重建: ŷ_i = LUT[h_i]

内积近似: ⟨x,q⟩ ≈ Σ(ŷ_i · q_i)

残差: r = y - ŷ

1-bit QJL: 随机 ±1 向量投影

残差修正: 无偏内积估计

排序取 top-k

和 FAISS PQ 的核心差异

维度turbovec (TurboQuant)FAISS (PQ)
训练需求零训练需要代表性数据训练 codebook
在线添加直接 add,即时可用需要重建或增量训练
检索速度手工 SIMD 内核,AVX-512/NEONSIMD via MKL/OpenBLAS
内存效率4-bit 模式下 0.5B/维PQ 典型 4-8B/维
过滤搜索原生支持,不损失召回需要后过滤或 IVF 内嵌
内存开销无需存 codebookcodebook 本身占用内存

TurboQuant 的盲区:几十亿向量的场景,需要 IVF 做粗筛——turbovec 不做这个。不过说实话,到这个量级你应该直接上 Milvus 或 Qdrant,本地 RAG 根本碰不到这种规模。


🏗️ 架构分析

turbovec 的代码组织很 Rust——模块边界小且清晰:

turbovec/ ├── src/ │ ├── lib.rs # 入口:TurboQuantIndex, IdMapIndex │ ├── rotation.rs # 随机旋转矩阵(固定 seed=42) │ ├── codebook.rs # Lloyd-Max 最优量化器质心表 │ ├── encode.rs # 编码管道:旋转→量化→打包 │ ├── search.rs # SIMD 搜索内核(NEON/AVX2/AVX-512) │ ├── pack.rs # 打包/解包:4-bit→密集字节布局 │ ├── id_map.rs # ID 映射索引 │ └── io.rs # 序列化/反序列化 ├── turbovec-python/ # Python bindings (PyO3 + maturin) └── benchmarks/ # 性能对比数据

几个让我印象深的设计

1. SIMD 双架构:一条#[cfg]搞定

search.rs里根据编译目标自动选路径:aarch64 走 NEON,x86_64 走 AVX2/AVX-512BW。x86 端抄了 FAISS 的"perm0 交错布局"——32 个向量的量化 code 按寄存器宽度交错排,MADD 每个 cycle 都吃满。

4-bit 模式下,一个 AVX-512 寄存器同时处理 128 个维度的查表。ARM 端用顺序布局(M 系列芯片缓存策略不同),实测比交错布局更快。

2. OnceLock 的并发魔法

这段把 Rust 的OnceLock用得很漂亮:

  • 旋转矩阵、质心表、SIMD 块布局的初始化,第一个调search的线程结账
  • 后续所有线程直接读缓存,零锁开销
  • add操作直接换掉OnceLock,invalidate 缓存

你不用手动调prepare(),也不用担心竞态——Rust 的类型系统替你保证了(search&selfadd&mut self)。

3. 过滤搜索的零开销路径

大多数向量数据库做过滤都是"多取一些 + 后过滤"——多取 k*N 个结果,然后丢掉不在 allowlist 里的。turbovec 直接在 SIMD 内核里跳过整块不包含合法 ID 的向量 block(32 个一组),用BLOCKS_SKIPPED_BY_MASK原子计数器跟踪跳过比例。

不够好的地方

  • 没有内存映射(mmap):索引只能全量加载到内存,不能像 FAISS 那样映射磁盘文件。1000 万条 4-bit 向量约 7.5GB,能跑但不能懒加载
  • 维度上限:受 SIMD 块布局约束,维度超过 ~32768 就无法编码。虽然 99% 的 embedding 模型远小于这个值,但如果要索引拼接向量就受限
  • 社区年轻:LangChain/LlamaIndex/Haystack 的集成已经写了(见docs/integrations/),但生态深度还远不如 FAISS

✅ 优缺点 & 适用场景

三个优点

  1. 零门槛向量检索:不需要懂量化理论,不需要挑训练数据,不需要调 IVF 参数。pip install turbovec之后 3 行代码就能跑
  2. 内存效率接近理论极限:Shannon 下界只差 2.7 倍常数,实际 4-bit 编码的召回率在 GloVe 100 万数据集上和 brute-force 几乎无差别
  3. 过滤搜索不牺牲召回:allowlist 路径直接在 SIMD 内核完成,不是后过滤——你拿 k 个就真的拿到 k 个

两个缺点

  1. 不支持倒排索引:亿级以上数据量还是要去用 Milvus
  2. 纯本地方案,无分布式支持:没有 server 模式、没有 sharding、没有副本

谁应该立刻试试

  • 在本地跑 RAG、用 Ollama/llama.cpp 做 embedding 的人
  • 在资源受限设备上做向量检索(树莓派、边缘设备——ARM NEON 内核表现极好)
  • 需要隐私保护的场景(数据不离开本机,不需要托管服务)

谁应该再等等

  • 向量量级超过 1 亿——turbovec 的纯暴力搜索路线不适合
  • 依赖完整的向量数据库生态(监控、备份、分布式查询)
  • 需要混合检索(dense + sparse),虽然可以把 sparse 结果作为 allowlist 传入,但这套方案不如原生 BM25+向量 hybrid 式方案直接

总结:turbovec 不是要替代 FAISS 或 Milvus。它的定位非常清晰——给 “本地 RAG” 场景一个不需要学习成本的、内存高效的、速度不输任何人的向量索引方案。如果你在笔记本上跑一个本地知识库,turbovec 应该成为你的默认选择。


项目地址:github.com/RyanCodrai/turbovec | 论文:arXiv:2504.19874

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 8:45:02

提升专注力与记忆力:Impulse大脑训练高级版全面评测

# 提升专注力与记忆力:Impulse大脑训练高级版全面评测在信息爆炸的时代,专注力与记忆力成为了稀缺资源。无论是学生、职场人士,还是追求终身学习的爱好者,都渴望找到一种高效、科学的方法来训练大脑。今天,我们将深入评…

作者头像 李华
网站建设 2026/6/10 8:43:54

contextily:Python 地图可视化的底图利器

文章目录contextily:Python 地图可视化的底图利器核心功能:获取瓦片并叠加安装与依赖适用场景contextily:Python 地图可视化的底图利器 做地理数据可视化时,matplotlib 画出的地图往往是纯色块和线条,缺少真实地理环境…

作者头像 李华
网站建设 2026/6/10 8:39:03

Claude Code最新版安装教程记录

自行安装git、node node版本大于18 用git bash 框安装 npm install -g anthropic-ai/claude-code claude --version cd 你的项目目录 claude 用户目录下 C:\Users\yonghu.claude\settings.json 这个文件配置模型地址和api-key {"env": {"ANTHROPIC_AUTH_TOKEN&q…

作者头像 李华
网站建设 2026/6/10 8:37:45

写代码时反复打开的几个在线工具,分享给你们

日常开发中总有一些高频小需求,比如调个正则、格式化 JSON、写个 Cron 表达式…今天把我收藏夹里几个常用的在线开发工具整理出来,都是浏览器打开就能用的,希望能帮到你。前言 前两天清理浏览器收藏夹,发现有几个在线工具的打开频…

作者头像 李华