Faiss/PQ 编码器

PQ:把高维向量编码成短码

把向量拆成多组子向量,用各自码本中的编号表示每组子向量。

v1.9.0内存管理核验 2026-10-08
相关概念

工程问题#

向量库规模增长后,原始浮点数据难以全部装入内存,扫描时的数据搬运也昂贵。

实际实现#

ProductQuantizer 将 d 维分成 M 组,为各组训练码本并编码;查询预计算子向量到码字的距离表,再查表累加近似距离。

处理流程#

  1. 按子空间训练多个码本
  2. 将每段向量编码成码字编号
  3. 为查询计算子空间距离表
  4. 累加查表距离并挑选候选

源码片段#

固定版本 · 原文摘录
faiss/impl/ProductQuantizer.cppv1.9.0 · L429–L440
查看原文件
429void ProductQuantizer::compute_distance_table(const float* x, float* dis_table)430        const {431    if (transposed_centroids.empty()) {432        // use regular version433        for (size_t m = 0; m < M; m++) {434            fvec_L2sqr_ny(435                    dis_table + m * ksub,436                    x + m * dsub,437                    get_centroids(m, 0),438                    dsub,439                    ksub);440        }
ProductQuantizer::compute_distance_table

遍历 M 个子空间,将查询子向量与该子空间的 ksub 个码字计算平方 L2 距离,写入各自的查表区段。后续按数据库向量保存的码字编号取表项并累加。本片段是未启用转置码本的分支,不是逐浮点分量做标量量化,也不是完整检索流程。

CPPMIT

收益与取舍#

工程分析

带来的收益

  • 每向量编码约占 M×nbits/8 字节
  • 查表计算降低扫描原始浮点数据的需求

付出的代价

  • 有损量化会改变距离与结果排序
  • 码本训练和查询距离表也消耗时间与内存

可比较的选择

保留原始向量做重排可改善候选排序精度,但增加原始数据存储与读取;不能找回未进入候选集的结果。

版本与适用范围#

字节公式不含码本、ID 和外层索引;此实现要求 d 能被 M 整除。PQ 本身是编码方法,可与 IVF 等检索结构组合。

参考来源#

源码、官方文档与原始论文
01
ProductQuantizer 训练、编码与查表

faiss/impl/ProductQuantizer.cpp · ProductQuantizer::train / compute_distance_table / search

源码v1.9.0
14 个匹配案例