首页
/ Faiss 向量相似性搜索库:核心原理、索引体系与实战入门全解

Faiss 向量相似性搜索库:核心原理、索引体系与实战入门全解

2026-09-05 18:02:46作者:沈韬淼Beryl

本文基于 Faiss 仓库的 README.md 及其关联的安装、变更日志文档展开,系统讲解 Faiss 的定位与相似性搜索模型、以 Index 为核心的索引抽象、conda/CMake 两条安装路径、GPU 索引的 drop-in 用法,以及演示程序与调优入口,帮助读者快速建立对这一 C++/Python 向量检索库的完整认知,并能独立完成安装、构建与首次检索实操。

Faiss 是什么:面向亿级向量的相似性搜索与聚类库

README.md 对 Faiss 的定义是:一个用于稠密向量高效相似性搜索(similarity search)与聚类(clustering)的库。其关键特性可以归纳为四点:

  • 规模上限高:包含针对“任意规模向量集合”的搜索算法,覆盖“大到可能装不进 RAM”的场景,即向量超出内存容量时仍可查询;
  • 附带评估与调参工具:仓库不仅提供索引实现,还内置评测与参数调优(AutoTune)的支持代码;
  • C++ 内核 + 完整 Python/numpy 封装:核心算法用 C++ 实现,Python 接口基于 Swig 自动生成,可直接操作 numpy 数组;
  • 部分关键算法有 GPU 实现:README 指出“最常用的一些算法在 GPU 上有实现”,且 GPU 索引可作为 CPU 索引的直接替换(drop-in replacement)。

Faiss 主要由 Meta 的 Fundamental AI Research 团队开发,MIT 协议开源(见 LICENSE)。当前仓库版本号为 1.15.0,在 faiss/Index.h 中以宏 FAISS_VERSION_MAJOR/MINOR/PATCH 定义;CHANGELOG.md 显示 1.15.0 于 2026-07-31 发布,新增了 EDEN 量化器、Metal(Apple GPU)IVF-PQ 索引、cuVS IVF-SQ 后端、RISC-V RVV 距离内核等特性。

相似性搜索的数学模型:L2、内积与余弦相似

README 的“Introduction”部分明确了 Faiss 的基本假设:

  1. 实例被表示为向量,并以整数 ID 标识;
  2. 向量间的比较基于 L2(欧氏)距离或点积(dot product)
  3. “相似”的定义:与查询向量 L2 距离最小,或点积最大的向量;
  4. 余弦相似(cosine similarity)也被支持,其实现原理是“在归一化向量上的点积”——即向量归一化后余弦相似等价于内积,因此 Faiss 无需为余弦单独实现一套距离核。

这一设计在源码中有直接对应。faiss/MetricType.h 定义了 MetricType 枚举,覆盖 METRIC_INNER_PRODUCTMETRIC_L2METRIC_L1METRIC_LinfMETRIC_Lp,以及一组与 scipy.spatial.distance 对齐的扩展度量(METRIC_CanberraMETRIC_BrayCurtisMETRIC_JensenShannonMETRIC_JaccardMETRIC_NaNEuclideanMETRIC_GOWER)。同文件中的 is_similarity_metric()faiss/MetricType.h)区分“相似度”(越大越近,如内积)与“差异度”(越小越近,如 L2)两类度量——这是 Faiss 用统一代码路径同时支撑 min/max 两种检索语义的关键开关。

索引抽象:围绕 Index 的权衡体系

README 的“How Faiss works”一节指出,Faiss 构建在一个核心抽象上:一种存储向量集合、并支持 L2 与/或点积比较的索引类型。其中部分索引(如精确检索的 Flat 索引)是简单基线,其余索引结构则对应一组可调节的权衡维度:

  • 搜索时间(search time)
  • 搜索质量(search quality)
  • 每个向量占用的内存(memory per vector)
  • 训练时间(training time)
  • 添加向量的时间(adding time)
  • 是否需要外部数据做无监督训练(need for external data for unsupervised training)

这个抽象在 C++ 端体现为基类 faiss::Index,见 faiss/Index.h。它包含如下核心成员:

struct Index {
    int d;               ///< 向量维度
    idx_t ntotal;        ///< 已索引向量总数
    bool verbose;        ///< 详细输出开关
    bool is_trained;     ///< 是否无需训练 / 已完成训练
    MetricType metric_type;  ///< 索引使用的度量类型
    float metric_arg;        ///< 度量的参数(如 METRIC_Lp 的 p)
    explicit Index(idx_t d_in = 0, MetricType metric = METRIC_L2) ...
};

注意 is_trained 字段:IVF 类等需要先做 k-means 训练才能 add 向量的索引,正是通过该标志表达“训练前置”约束;Flat 类索引则默认无需训练。头文件注释(faiss/Index.h)还说明了贯穿全库的数据布局约定:n 个 d 维向量以 float* 行主序紧凑存储,元素 x[i * d + j] 是第 i 个向量的第 j 个分量——这与 Python 侧传入的 numpy 二维数组(C-contiguous)完全一致,因此 Swig 封装可以零拷贝传递。

Python 侧所有具体索引都继承自该基类,例如 faiss/python/init.pyi 中的 IndexFlatL2(IndexFlat)第 1817 行IndexIVFFlat(IndexIVF)。README 特别提到两类代表性路线:

  • 压缩表示路线:基于二值向量和紧凑量化码(compact quantization codes)的方法只使用向量的压缩表示,无需保留原始向量。代价是精度下降,但可以“在单台服务器的内存中扩展到数十亿(billions)向量”;
  • 图上索引路线:HNSW 和 NSG 等索引在原始向量之上叠加图结构来提升检索效率,保留原始向量、精度更高。

index_factory 一行代码构建复杂索引

Python 接口提供了字符串驱动的工厂函数,是权衡上述维度最便捷的入口(faiss/python/init.pyi):

import faiss

d, n = 128, 100_000
x = faiss.random_norm(d, n).astype("float32")

# "IVF4096,PQ16" 表示:4096 个倒排桶 + 16 维乘积量化
index = faiss.index_factory(d, "IVF4096,PQ16", faiss.METRIC_L2)
index.train(x)
index.add(x)

# IVF 索引支持运行时参数,如 nprobe
params = faiss.IndexIVFSearchParameters()
params.nprobe = 32

D, I = index.search(x[:10], 10)  # 返回距离矩阵 D 与 ID 矩阵 I

同文件还导出了 clone_index(深拷贝索引)、write_index/read_index(序列化/反序列化,见 第 2393-2399 行)等工具函数,构成“构建—训练—添加—检索—持久化”的完整闭环。

安装 Faiss:conda 预编译包与源码构建

README 的“Installing”一节给出两条路径:conda 预编译库与 CMake 源码构建。完整细节在 INSTALL.md,以下是与源码互相印证后的完整说明。

路径一:conda 预编译包(推荐)

稳定版与 nightly 预发布版定期推送到 pytorch conda 频道,提供三个包:

包名 平台 说明
faiss-cpu Linux(x86-64 / aarch64)、macOS(arm64)、Windows(x86-64) 仅 CPU 索引
faiss-gpu Linux(x86-64),CUDA 11.4 与 12.1 CPU + GPU 索引
faiss-gpu-cuvs Linux(x86-64),CUDA 13.2 GPU 索引由 NVIDIA cuVS 26.06 提供

安装命令(摘自 INSTALL.md):

# 仅 CPU
$ conda install -c pytorch -c conda-forge faiss-cpu=1.15.0

# GPU(+CPU)
$ conda install -c pytorch -c nvidia -c conda-forge faiss-gpu=1.15.0

# GPU(+CPU),NVIDIA cuVS 后端
$ conda install -c pytorch -c nvidia -c rapidsai -c conda-forge libnvjitlink faiss-gpu-cuvs=1.15.0

要点:conda-forge 频道是必需的(x86-64 上提供最新 MKL、ARM 上提供 OpenBLAS,主 Anaconda 频道更新不及时);faiss-gpu 需额外 nvidia 频道获取 CUDA;AMD ROCm 版 GPU 包“尚不可用”(文档原文明确标注 not yet available)。除 conda 外,INSTALL.md 还给出了 Pixi 的等价命令(pixi init -c pytorch -c conda-forgepixi add faiss-cpu=1.15.0)。

路径二:CMake 源码构建

基本依赖(INSTALL.md):

  • 必需:C++20 编译器(OpenMP 2 以上)、一个 BLAS 实现(Intel 机器强烈建议 MKL);
  • 可选:GPU 索引需要 nvcc 与 CUDA toolkit;AMD GPU 需要 ROCm;cuVS 实现需要 libcuvs=26.06;Python 绑定需要 Python 3、numpy 和 swig。

构建流程分四步,README 称“它用 cmake 编译”:

# Step 1: 配置(常用开关见下)
$ cmake -B build .

# Step 2: 构建 C++ 库(默认 libfaiss.a;-DBUILD_SHARED_LIBS=ON 时为 libfaiss.so)
$ make -C build -j faiss

# Step 3: 构建并安装 Python 绑定(可选)
$ make -C build -j swigfaiss
$ (cd build/faiss/python && python setup.py install)

# Step 4: 安装 C++ 库与头文件(可选)
$ make -C build install

常用 CMake 选项(完整清单见 INSTALL.md):

  • -DFAISS_ENABLE_GPU=OFF / -DFAISS_ENABLE_PYTHON=OFF:关闭 GPU 索引 / Python 绑定;
  • -DFAISS_OPT_LEVEL=avx2(x86-64 可选 genericavx2avx512avx512_spr;aarch64 可选 genericsve):启用对应 SIMD 指令集编译,此时需构建 faiss_avx2 / faiss_avx512 / faiss_avx512_spr 目标;
  • -DBUILD_TESTING=OFF-DBUILD_SHARED_LIBS=ON-DFAISS_ENABLE_C_API=ON(构建 C API,说明见 c_api/INSTALL.md);
  • -DBLA_VENDOR=Intel10_64_dyn -DMKL_LIBRARIES=/path/to/mkl/libs:指定 Intel MKL,文档称其显著快于 OpenBLAS;
  • -DFAISS_ENABLE_CUVS=ON:启用 cuVS 的 IVF-Flat、IVF-PQ 与 CAGRA GPU 索引(前提 -DFAISS_ENABLE_GPU=ON);
  • -DFAISS_ENABLE_SVS=ON:集成 Intel SVS 图索引(如 Vamana),CMake 会自动拉取并构建 SVS 运行时;
  • -DCMAKE_CUDA_ARCHITECTURES="75;72":指定目标 GPU 架构。

Python 侧绑定由 Swig 驱动,接口声明文件为 faiss/python/swigfaiss.swig,类型存根为 faiss/python/init.pyi

验证安装:演示程序

INSTALL.md 给出由浅入深的验证路径,与仓库 demos/ 目录一一对应:

# 小型 IVFPQ 示例:建索引、存储、检索,常规机器约 20s,MKL 加速下约 2.5s
$ make -C build demo_ivfpq_indexing
$ ./build/demos/demo_ivfpq_indexing

# GPU 版等价示例(含索引在 CPU/GPU 间的搬运)
$ make -C build demo_ivfpq_indexing_gpu
$ ./build/demos/demo_ivfpq_indexing_gpu

# SIFT1M 实测:高层 AutoTune API 演示(需先把 ANN_SIFT1M 数据集解包到源码根目录 sift1M/)
$ make -C build demo_sift1M
$ ./build/demos/demo_sift1M

demos/demo_auto_tune.py 则把 SIFT1M 测试扩展到多种索引类型,自动寻找最优工作点;将其 keys_to_test 改为 keys_gpu 并置 use_gpu = True 即可测 GPU 代码。更多 Python 教程见 tutorial/python/(如 1-Flat.py6-HNSW.py7-PQFastScan.py)。

GPU 实现:CPU 索引的 drop-in 替换

README 的 Introduction 末尾专门描述了 GPU 行为,要点有三:

  1. 输入来源灵活:GPU 索引的输入可以来自 CPU 内存或 GPU 显存,从 CPU/GPU 显存到 GPU 的拷贝自动处理;
  2. drop-in 替换:在带 GPU 的服务器上,可直接把 IndexFlatL2 替换为 GpuIndexFlatL2 等 GPU 索引;若输入输出都常驻 GPU,速度更快;
  3. 支持单卡与多卡:README 明确“单卡与多卡用法均受支持”。

从源码结构看,这一说法对应到 faiss/gpu/GpuIndexFlat.h 中的 GpuIndexFlatL2 类,以及 faiss/gpu/GpuCloner.hGpuCloner——后者负责把任意 CPU 索引按 GpuClonerOptions 配置翻译/搬移到 GPU。多卡场景则由 StandardGpuResourcesfaiss/gpu/StandardGpuResources.h)管理多张卡的资源分配,C API 层也暴露了对应的封装(c_api/gpu/StandardGpuResources_c.h)。

README 还提到可选的 NVIDIA cuVS 后端:启用后用户可以在 Faiss 原生 GPU 实现与 cuVS 实现之间按算法选择。这与 INSTALL.md 的描述一致——cuVS 提供 GPU 上近似近邻与聚类的先进实现,构建 Faiss 时开启 FAISS_ENABLE_CUVS 即可在两种实现间切换。

文档、基准测试与延伸阅读

README 的“Full documentation”一节列出了文档入口。在仓库内部可落地的有:

README 同时指向 wiki(入门教程、FAQ、故障排查)、Doxygen 逐类文档与 issues/discussions 社区入口;这些为仓库外资源,本文不展开。

学术引用与项目背景

若在自己的研究论文中使用 Faiss,README 给出的引用信息为:

@article{douze2024faiss,
  title={The Faiss library},
  author={Matthijs Douze and Alexandr Guzhva and Chengqi Deng and Jeff Johnson and Gergely Szilvasy and Pierre-Emmanuel Mazaré and Maria Lomeli and Lucas Hosseini and Hervé Jégou},
  year={2024},
  eprint={2401.08281},
  archivePrefix={arXiv},
  primaryClass={cs.LG}
}

GPU 版本的引用:

@article{johnson2019billion,
  title={Billion-scale similarity search with {GPUs}},
  author={Johnson, Jeff and Douze, Matthijs and J{\'e}gou, Herv{\'e}},
  journal={IEEE Transactions on Big Data},
  volume={7},
  number={3},
  pages={535--547},
  year={2019},
  publisher={IEEE}
}

主要作者分工(README “Authors”一节):Hervé Jégou 发起项目并写出首个实现;Matthijs Douze 实现大部分 CPU Faiss;Jeff Johnson 实现全部 GPU Faiss;Lucas Hosseini 实现二值索引与构建系统;Chengqi Deng 实现 NSG、NNdescent 及大量加性量化代码;Alexandr Guzhva 负责 SIMD、内存分配与布局、向量编解码快速解码内核等优化;Gergely Szilvasy 负责构建系统与基准测试框架。

小结:从 README 出发的一条上手路线

  1. 先跑 conda 安装conda install -c pytorch -c conda-forge faiss-cpu=1.15.0,用 faiss.index_factory(d, "IVF4096,PQ16") 走通“train → add → search”流程(度量语义见 faiss/MetricType.h);
  2. 再跑演示demos/demo_sift1Mdemos/demo_auto_tune.py 体验 AutoTune 自动调参;
  3. 需要性能时看权衡维度:按 README 列出的六个权衡轴(搜索时间/质量/内存/训练/添加/外部数据)选择 IVF+PQ、FastScan、HNSW 或 NSG 等结构,并用 INSTALL.mdFAISS_OPT_LEVEL=avx2/avx512 与 MKL 选项压榨 CPU 性能;
  4. 有 GPU 时做 drop-in 替换:把 IndexFlatL2 换成 GpuIndexFlatL2,借助 GpuCloner 搬运索引,输入输出常驻显存以获得最高吞吐。

以上所有路径与参数均以当前仓库(版本 1.15.0)的实际内容为准;GPU 平台支持范围、CUDA 版本要求等适用前提,请对照 INSTALL.md 中对应条目确认。

登录后查看全文
热门项目推荐
相关项目推荐