Faiss 1.11.0 向量检索提速:RaBitQ 把每条向量压缩到约 1/32 的存储
【免费下载链接】faissA library for efficient similarity search and clustering of dense vectors.项目地址: https://gitcode.com/GitHub_Trending/fa/faiss
Faiss 1.11.0(2025-04-24 发布,见 CHANGELOG.md)是稠密向量检索库 Faiss 的新版本,解决数据量上涨后 fp32 向量存储与暴力搜索延迟扛不住的瓶颈,核心新增是 RaBitQ 量化索引。读完本文,你能三步建出一个 RaBitQ 索引并发起查询,按数据规模、精度、内存三个条件选到合适索引,并用三个量化指标确认优化生效。
这个版本改了什么
- 新增 RaBitQ 实现:
IndexRaBitQ、IndexIVFRaBitQ及其 FastScan 变体共 4 种索引形态,index factory 直接支持"RaBitQ"、"RaBitQfs"字符串(faiss/IndexRaBitQ.h、faiss/index_factory.cpp) - 新增内存映射与零拷贝反序列化器,加载大索引不必再整体复制一份内存(faiss/impl/mapped_io.h)
- 训练 API 增加
normalize_l2/is_spherical开关,让球面数据的预处理行为显式化(CHANGELOG 1.11.0 Added 一节) - 修复
IndexHNSW的metric_arg传参 bug、为nb_neighbors增加越界检查、修复 ARM 平台上IVFPQFastScan的 range search 行为(CHANGELOG 1.11.0 Fixed 一节) - C API 开始通过 Conda 发布,C 语言接入的安装方式更简单(CHANGELOG 1.11.0 Changed 一节)
RaBitQ 是怎么省事的
把一条 256 维向量想成行李箱里 256 件物品。乘积量化(PQ,把向量切成 M 段、每段查码本表)相当于把物品分装进小袋子再逐个描述;RaBitQ 则是完全不拆行李,每个维度只记 1 个比特:正还是负。于是每维从 4 个字节降到 1/8 个字节,再外加几个字节的校准常数,总存储约是 fp32 的 1/25 到 1/32(码长公式见 faiss/impl/RaBitQuantizer.h 的compute_code_size)。搜索时 CPU 用 and、popcount 这类位运算估计距离,而不是逐维浮点乘法,SIMD 指令集恰好对位运算加速明显。
三步跑通最小示例
第一步:安装。pip 装现成包最简单,想自己编译也可以从源码来:
pip install faiss-cpu # 或:git clone https://gitcode.com/GitHub_Trending/fa/faiss # cmake -B build && cmake --build build -j && cmake --install build第二步:建索引。IndexRaBitQ只需要维度d和每维位数nb_bits,没有 PQ 那种 M 参数,训练也远比聚类轻量。第三步:查询,接口和普通 Faiss 索引完全一致:
import numpy as np import faiss d, n = 256, 200_000 xb = np.random.randn(n, d).astype("float32") xq = np.random.randn(10, d).astype("float32") index = faiss.IndexRaBitQ(d, nb_bits=1) # 1-bit 量化 index.add(xb) D, I = index.search(xq, 10)按场景选索引
| 数据规模 | 精度要求 | 内存条件 | 推荐索引 |
|---|---|---|---|
| 百万以内 | 接近精确搜索 | 不限 | IndexFlatL2暴力搜索 |
| 千万级 | 可接受少量召回损失 | 紧张 | IndexRaBitQ(nb_bits=1) |
| 亿级 | 精度与速度平衡 | 紧张 | IndexIVFRaBitQ(nlist 取 √N 量级) |
| 千万级以上 | 极高精度 | 充足 | IndexHNSWFlat图索引 |
💡 一般从 IVF + RaBitQ 起步,再调nprobe换召回;CPU 支持 AVX-512 时可换 FastScan 变体(factory 字符串"RaBitQfs"),批处理吞吐更高。
怎么确认优化生效
不用搭监控体系,看三个数字就够:
- 查询延迟:用 timeit 跑 10 次 search 取平均毫秒数,benchs/bench_rabitq.py 里的计时函数可以直接照搬
- 召回率:拿精确 top-k 做对照,用
faiss.eval_intersection算交集占比,与升级前的基线对比 - 内存:RaBitQ 1-bit 码每条向量占 (d+7)/8 + 8 字节,乘上向量总数,对比 fp32 的 d×4 字节,省了多少一目了然
📌 该基准脚本会依次跑 256 / 512 / 768 / 1024 维,按维度输出召回与延迟表格,跑一遍就能得到你这台机器上的前后对比。
容易踩的四个坑
- 按 IVFPQ 的签名调用
IndexIVFRaBitQ。原因:它的构造参数是 (quantizer, d, nlist, ...),不存在 IVFPQ 的 M、nbits 参数,RaBitQ 的位宽参数是nb_bits(1-9)。规避:先看 faiss/IndexIVFRaBitQ.h 里的真实签名再写代码 - 在 FastScan 变体里把
qb设为 0。原因:SIMD 查找表需要量化后的查询,头文件明确注明 FastScan 不支持qb=0。规避:保留默认qb=4,需要更精查询量化再调大 - 用
sa_decode的输出去核对 L2 精度。原因:解码偏向保持内积,重建向量的 L2 误差可能偏大。规避:L2 场景以 search 路径的距离为准,不把重建结果当真值 - 小数据硬上量化索引。原因:数据不到百万且内存充裕时,暴力搜索更准也更简单,量化收益只在大规模或内存受限时才体现。规避:先跑
IndexFlatL2建立精度与延迟基线,再决定是否压缩
Faiss 1.11.0 让向量检索的内存和延迟收益集中在nb_bits一个参数上,配合内存映射反序列化,大索引的加载和部署都更省力。想继续深入,可以从以下三个入口看起:
- benchs/bench_rabitq.py:RaBitQ 官方基准脚本,含计时与召回计算
- faiss/impl/RaBitQuantizer.h:量化器核心接口与码长、解码语义的注释
- INSTALL.md:源码编译与安装的完整说明
【免费下载链接】faissA library for efficient similarity search and clustering of dense vectors.项目地址: https://gitcode.com/GitHub_Trending/fa/faiss
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考