文件 IndexBinaryIVF.h
-
namespace faiss
实现了具有多种变体的 k-means 聚类。
版权所有 (c) Facebook, Inc. 及其附属公司。
此源代码根据 MIT 许可证获得许可,该许可证位于此源树的根目录中的 LICENSE 文件中。
IDSelector 旨在定义要处理的向量子集(用于删除或作为搜索的子集)
PQ4 SIMD 打包和累加函数
基本内核使用 bbs = nb * 2 * 16 个向量累加 nq 个查询向量,并为此生成一个输出矩阵。 对于 nq * nb <= 4 来说,这很有趣,否则寄存器溢出会变得太大。
这些函数的实现分布在 3 个 cpp 文件中,以减少并行编译时间。 模板被显式实例化。
此文件包含计算距离的内核的回调。
在整个库中,向量以 float * 指针的形式提供。 当批量处理(添加/搜索)多个向量时,大多数算法都可以得到优化。 在这种情况下,它们作为矩阵传入。 当大小为 d 的 n 个向量以 float * x 的形式提供时,向量 i 的分量 j 是
x[ i * d + j ]
其中 0 <= i < n 且 0 <= j < d。 换句话说,矩阵始终是紧凑的。 当指定矩阵的大小时,我们将其称为 n*d 矩阵,这意味着行优先存储。
I/O 函数可以读取/写入到文件名、文件句柄或抽象介质的对象。
读取函数返回应该使用 delete 释放的对象。 这些对象中的所有引用都由该对象拥有。
倒排列表的定义 + 一些实现该接口的通用类。
由于 IVF(倒排文件)索引对于大规模用例非常有用,因此我们将与它们相关的一些函数组合到这个小型库中。 大多数函数都可以用于 IndexIVF 和嵌入在 IndexPreTransform 中的 IndexIVF。
在此文件中,实现了 L2 和内积之外的额外度量
实现了一些神经网络层,主要用于支持 QINCo
定义了一些对向量集应用转换的对象。 这些通常是预处理步骤。
-
struct IndexBinaryIVF : public faiss::IndexBinary
- #include <IndexBinaryIVF.h>
基于倒排文件 (IVF) 的 Index
在倒排文件中,量化器(一个 IndexBinary 实例)为每个要添加的向量提供一个量化索引。 量化索引映射到一个列表(也称为倒排列表或posting list),其中存储了向量的 ID。
否则,该对象与 IndexIVF 类似
公共函数
-
IndexBinaryIVF(IndexBinary *quantizer, size_t d, size_t nlist)
倒排文件接收一个量化器(一个 IndexBinary)作为输入,它实现了将向量映射到列表标识符的函数。 该指针是被借用的:当量化器在使用 IndexBinaryIVF 时,不应被删除。
-
IndexBinaryIVF()
-
~IndexBinaryIVF() override
-
virtual void reset() override
从数据库中删除所有元素。
-
virtual void add(idx_t n, const uint8_t *x) override
将维度为 d 的 n 个向量添加到索引中。
向量被隐式分配标签 ntotal .. ntotal + n - 1
- 参数:
x – 输入矩阵,大小为 n * d / 8
-
virtual void add_with_ids(idx_t n, const uint8_t *x, const idx_t *xids) override
与 add 相同,但存储 xids 而不是顺序 id。
默认实现会因断言而失败,因为它并非所有索引都支持。
- 参数:
xids – 如果非空,则为要存储的向量的 id(大小为 n)
-
void add_core(idx_t n, const uint8_t *x, const idx_t *xids, const idx_t *precomputed_idx)
向量加法的实现,其中向量分配是预定义的。
- 参数:
precomputed_idx – 输入向量的量化索引(大小为 n)
-
void search_preassigned(idx_t n, const uint8_t *x, idx_t k, const idx_t *assign, const int32_t *centroid_dis, int32_t *distances, idx_t *labels, bool store_pairs, const IVFSearchParameters *params = nullptr) const
搜索一组向量,这些向量已由 IVF 量化器预先量化。 用查询结果填充相应的堆。search() 调用此函数。
- 参数:
n – 要查询的向量数
x – 查询向量,大小为 nx * d
assign – 粗量化索引,大小为 nx * nprobe
centroid_dis – 到粗质心的距离,大小为 nx * nprobe
distance – 输出距离,大小为 n * k
labels – 输出标签,大小为 n * k
store_pairs – 在结果的上/下 32 位中存储 inv list index + inv list offset,而不是 id(用于重新排序)。
params – 用于覆盖对象的搜索参数
-
virtual BinaryInvertedListScanner *get_InvertedListScanner(bool store_pairs = false) const
-
virtual void search(idx_t n, const uint8_t *x, idx_t k, int32_t *distances, idx_t *labels, const SearchParameters *params = nullptr) const override
分配向量,然后调用 search_preassign
-
virtual void range_search(idx_t n, const uint8_t *x, int radius, RangeSearchResult *result, const SearchParameters *params = nullptr) const override
查询维度为 d 的 n 个向量到索引。
返回所有距离 < radius 的向量。 请注意,许多索引不实现 range_search(只有 k-NN 搜索是强制性的)。 距离被转换为浮点数以重用 RangeSearchResult 结构,但它们是整数。 按照惯例,仅返回距离 < radius 的距离(严格比较),即 radius = 0 不返回任何结果,1 仅返回完全相同的向量。
- 参数:
x – 要搜索的输入向量,大小为 n * d / 8
radius – 搜索半径
result – 结果表
-
void range_search_preassigned(idx_t n, const uint8_t *x, int radius, const idx_t *assign, const int32_t *centroid_dis, RangeSearchResult *result) const
-
virtual void reconstruct(idx_t key, uint8_t *recons) const override
重建存储的向量。
此函数可能未针对某些索引定义。
- 参数:
key – 要重建的向量的 id
recons – 重建的向量(大小 d / 8)
-
virtual void reconstruct_n(idx_t i0, idx_t ni, uint8_t *recons) const override
重建索引向量的子集。
覆盖默认实现以绕过 reconstruct(),该方法要求维护 direct_map。
- 参数:
i0 – 要重建的第一个向量
ni – 要重建的向量数量
recons – 重建向量的输出数组,大小为 ni * d / 8
-
virtual void search_and_reconstruct(idx_t n, const uint8_t *x, idx_t k, int32_t *distances, idx_t *labels, uint8_t *recons, const SearchParameters *params = nullptr) const override
类似于搜索,但也重建了搜索结果的存储向量(或者在有损编码的情况下进行近似)。
覆盖默认实现,以避免必须维护 direct_map,而是通过 search_preassigned() 中的
store_pairs
标志来获取代码偏移量。- 参数:
recons – 重建的向量大小 (n, k, d / 8)
-
virtual void reconstruct_from_offset(idx_t list_no, idx_t offset, uint8_t *recons) const
根据位置(倒排列表索引 + 倒排列表偏移量)而不是 ID 重建向量。
当不维护 direct_map 并且使用设置了
store_pairs
的 search_preassigned() 计算倒排列表偏移量时,此方法非常有用。
-
virtual size_t remove_ids(const IDSelector &sel) override
数据集操作函数。
-
virtual void merge_from(IndexBinary &other, idx_t add_id) override
将条目从另一个数据集移动到自身。输出时,other 为空。 add_id 将添加到所有移动的 id(对于顺序 id,这将是 this->ntotal)
-
virtual void check_compatible_for_merge(const IndexBinary &otherIndex) const override
检查两个索引是否兼容(即,它们以相同的方式训练并具有相同的参数)。否则抛出异常。
-
inline size_t get_list_size(size_t list_no) const
-
void make_direct_map(bool new_maintain_direct_map = true)
初始化 direct map
- 参数:
new_maintain_direct_map – 如果为 true,则创建 direct map,否则清除它
-
void replace_invlists(InvertedLists *il, bool own = false)
公共成员
-
InvertedLists *invlists = nullptr
访问实际数据。
-
bool own_invlists = true
-
size_t nprobe = 1
查询时的 probes 数量
-
size_t max_codes = 0
执行查询要访问的最大代码数量
-
bool use_heap = true
在扫描倒排列表时,选择使用堆还是计数来选择 k 个最小值。
-
bool per_invlist_search = false
按批次收集计算结果
-
DirectMap direct_map
用于直接访问元素的 map。 启用 reconstruct()。
-
IndexBinary *quantizer = nullptr
将向量映射到倒排列表的量化器
-
size_t nlist = 0
可能的键值的数量
-
bool own_fields = false
对象是否拥有量化器
-
ClusteringParameters cp
用于覆盖默认的聚类参数
-
IndexBinaryIVF(IndexBinary *quantizer, size_t d, size_t nlist)
-
struct BinaryInvertedListScanner
公共函数
-
virtual void set_query(const uint8_t *query_vector) = 0
从现在开始,我们处理这个查询。
-
virtual uint32_t distance_to_code(const uint8_t *code) const = 0
计算单个查询到代码的距离
-
virtual size_t scan_codes(size_t n, const uint8_t *codes, const idx_t *ids, int32_t *distances, idx_t *labels, size_t k) const = 0
计算到代码的距离。(距离,标签)应组织为最小或最大堆
- 参数:
n – 要扫描的代码数
codes – 要扫描的代码 (n * code_size)
ids – 相应的 ID(如果 store_pairs 则忽略)
distances – 堆距离 (大小为 k)
labels – 堆标签 (大小为 k)
k – 堆大小
-
virtual void scan_codes_range(size_t n, const uint8_t *codes, const idx_t *ids, int radius, RangeQueryResult &result) const = 0
-
inline virtual ~BinaryInvertedListScanner()
-
virtual void set_query(const uint8_t *query_vector) = 0
-
struct IndexBinaryIVF : public faiss::IndexBinary