文件 GpuIndexCagra.h

namespace faiss

实现具有多种变体的 k 均值聚类。

版权所有 (c) Facebook, Inc. 及其附属公司。

此源代码已获得 MIT 许可,该许可位于此源树的根目录中的 LICENSE 文件中。

IDSelector 旨在定义要处理的向量子集(用于删除或作为搜索的子集)

PQ4 SIMD 压缩和累积函数

基本内核使用 bbs = nb * 2 * 16 向量累积 nq 查询向量,并为此生成一个输出矩阵。对于 nq * nb <= 4 来说,这很有意思,否则寄存器溢出会变得太大。

这些函数的实现分布在 3 个 cpp 文件中,以减少并行编译时间。模板是显式实例化的。

此文件包含用于计算距离的内核的回调。

在整个库中,向量作为 float * 指针提供。当批量处理(添加/搜索)多个向量时,大多数算法都可以优化。在这种情况下,它们作为矩阵传递。当 n 个大小为 d 的向量作为 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

定义了一些对向量集应用转换的对象 通常这些是预处理步骤。

namespace gpu

枚举

enum class graph_build_algo

enumerator IVF_PQ

使用 IVF-PQ 构建所有邻居 knn 图。

enumerator NN_DESCENT

使用 NN-Descent 构建所有邻居 knn 图。

enum class codebook_gen

用于指定如何创建 PQ 码本的类型。

enumerator PER_SUBSPACE
enumerator PER_CLUSTER
enum class search_algo

enumerator SINGLE_CTA

适用于大批量大小。

enumerator MULTI_CTA

适用于小批量大小。

enumerator MULTI_KERNEL
enumerator AUTO
enum class hash_mode

enumerator HASH
enumerator SMALL
enumerator AUTO
struct IVFPQBuildCagraConfig

公共成员

uint32_t n_lists = 1024

倒排列表(簇)的数量

提示:每个簇的向量数(n_rows/n_lists)应约为 1,000 到 10,000。

uint32_t kmeans_n_iters = 20

搜索 kmeans 中心(索引构建)的迭代次数。

double kmeans_trainset_fraction = 0.5

在迭代 kmeans 构建期间使用的数据比例。

uint32_t pq_bits = 8

通过 PQ 压缩后的向量元素位长。

可能的值:[4, 5, 6, 7, 8]。

提示:“pq_bits”越小,索引大小越小,搜索性能越好,但召回率越低。

uint32_t pq_dim = 0

通过 PQ 压缩后的向量维度。 当为零时,使用启发式方法选择最佳值。

注意:pq_dim /// pq_bits 必须是 8 的倍数。

提示:较小的“pq_dim”会导致较小的索引大小和更好的搜索性能,但召回率较低。 如果“pq_bits”为 8,“pq_dim”可以设置为任何数字,但 8 的倍数对于获得良好的性能是可取的。 如果“pq_bits”不是 8,“pq_dim”应为 8 的倍数。 为了获得良好的性能,“pq_dim”最好是 32 的倍数。 理想情况下,“pq_dim”也应该是数据集维度的约数。

codebook_gen codebook_kind = codebook_gen::PER_SUBSPACE

PQ 码本的创建方式。

bool force_random_rotation = false

即使 dim % pq_dim == 0,也在输入数据和查询上应用随机旋转矩阵。

注意:如果 dim 不是 pq_dim 的倍数,则始终对输入数据和查询应用随机旋转,以将工作空间从 dim 转换为 rot_dim,这可能比原始空间稍大,并且是 pq_dim 的倍数(rot_dim % pq_dim == 0)。 但是,当 dimpq_dim 的倍数时,此转换不是必需的(dim == rot_dim,因此无需添加“额外”数据列/特征)。

默认情况下,如果 dim == rot_dim,则旋转变换将使用单位矩阵初始化。当 force_random_rotation == true 时,无论 dimpq_dim 的值如何,都会生成一个随机正交变换矩阵。

bool conservative_memory_allocation = false

默认情况下,该算法为单个集群(list_data)分配比必要更多的空间。这允许摊销内存分配的成本,并减少重复调用 extend (扩展数据库)期间的数据复制次数。

另一种是保守分配行为;启用后,该算法始终分配存储给定数量记录所需的最小内存量。如果您希望尽可能少地使用 GPU 内存来存储数据库,请将此标志设置为 true

struct IVFPQSearchCagraConfig

公共成员

uint32_t n_probes = 20

要搜索的聚类数量。

cudaDataType_t lut_dtype = CUDA_R_32F

在搜索时动态创建的查找表的数据类型。

可能的值:[CUDA_R_32F, CUDA_R_16F, CUDA_R_8U]

使用低精度类型可以减少搜索时所需的共享内存量,因此即使对于具有较大维度的数据集,也可以使用快速共享内存内核。请注意,选择低精度类型时,召回率会略有下降。

cudaDataType_t internal_distance_dtype = CUDA_R_32F

用于存储在搜索时计算的距离/相似性的数据类型。

可能的值:[CUDA_R_16F, CUDA_R_32F]

如果在搜索时性能限制器是设备内存访问,则选择 FP16 会稍微提高性能。

double preferred_shmem_carveout = 1.0

首选的 SM 统一内存/L1 缓存作为共享内存使用的比例。

可能的值:[0.0 - 1.0],作为 sharedMemPerMultiprocessor 的一部分。

人们希望增加 carveout 以确保主搜索内核具有良好的 GPU 占用率,但不要使其过高,从而留下一些内存用作 L1 缓存。请注意,此值仅被解释为提示。此外,GPU 通常只允许一组固定的缓存配置,因此提供的值会向上舍入到最接近的配置。请参阅目标 GPU 架构的 NVIDIA 调整指南。

请注意,这是一个低级调整参数,如果调整不当,可能会对搜索性能产生严重的负面影响。

struct GpuIndexCagraConfig : public faiss::gpu::GpuIndexConfig

公共成员

size_t intermediate_graph_degree = 128

用于剪枝的输入图的度数。

size_t graph_degree = 64

输出图的度数。

graph_build_algo build_algo = graph_build_algo::IVF_PQ

用于构建 knn 图的 ANN 算法。

size_t nn_descent_niter = 20

如果使用 NN_DESCENT 构建,则运行的迭代次数。

IVFPQBuildCagraConfig *ivf_pq_params = nullptr
IVFPQSearchCagraConfig *ivf_pq_search_params = nullptr
float refine_rate = 2.0f
bool store_dataset = true
struct SearchParametersCagra : public faiss::SearchParameters

公共成员

size_t max_queries = 0

要同时搜索的最大查询数量(批处理大小)。当为 0 时自动选择。

size_t itopk_size = 64

在搜索期间保留的中间搜索结果的数量。

这是调整准确性和搜索速度之间权衡的主要旋钮。更高的值会提高搜索准确性。

size_t max_iterations = 0

搜索迭代的上限。当为 0 时自动选择。

search_algo algo = search_algo::AUTO

要使用的搜索实现。

size_t team_size = 0

用于计算单个距离的线程数。4、8、16 或 32。

size_t search_width = 1

在每次迭代中选择作为搜索起点的图节点数。又名搜索宽度?

size_t min_iterations = 0

搜索迭代的下限。

size_t thread_block_size = 0

线程块大小。0、64、128、256、512、1024。当为 0 时自动选择。

hash_mode hashmap_mode = hash_mode::AUTO

哈希映射类型。当为 AUTO 时自动选择。

size_t hashmap_min_bitlen = 0

哈希映射位长度的下限。大于 8。

float hashmap_max_fill_rate = 0.5

哈希映射填充率的上限。大于 0.1,小于 0.9。

uint32_t num_random_samplings = 1

初始随机种子节点选择的迭代次数。1 或更多。

uint64_t seed = 0x128394

用于初始随机种子节点选择的位掩码。

struct GpuIndexCagra : public faiss::gpu::GpuIndex

公共函数

GpuIndexCagra(GpuResourcesProvider *provider, int dims, faiss::MetricType metric = faiss::METRIC_L2, GpuIndexCagraConfig config = GpuIndexCagraConfig())
virtual void train(idx_t n, const float *x) override

基于给定的向量数据训练 CAGRA。

void copyFrom(const faiss::IndexHNSWCagra *index)

从给定的 CPU 索引初始化自身;将覆盖自身中的所有数据

void copyTo(faiss::IndexHNSWCagra *index) const

将自身复制到给定的 CPU 索引;将覆盖索引实例中的所有数据

virtual void reset() override

从数据库中移除所有元素。

std::vector<idx_t> get_knngraph() const

受保护的函数

virtual bool addImplRequiresIDs_() const override

addImpl_ 是否需要 ID? 如果是这样,并且未提供任何 ID,我们将根据添加 ID 的顺序依次生成它们

virtual void addImpl_(idx_t n, const float *x, const idx_t *ids) override

重写以实际执行添加。 保证所有数据都驻留在我们的设备上

virtual void searchImpl_(idx_t n, const float *x, int k, float *distances, idx_t *labels, const SearchParameters *search_params) const override

GpuIndex 调用以进行搜索。

受保护的属性

const GpuIndexCagraConfig cagraConfig_

我们的配置选项。

std::shared_ptr<CuvsCagra> index_

我们拥有的实例;包含倒排列表。