milvus-logo
LFAI
首页
  • 概念

Knowhere

本主题介绍 Milvus 的核心向量执行引擎 Knowhere。

概述

Knowhere 是 Milvus 的核心向量执行引擎,它集成了多个向量相似性搜索库,包括FaissHnswlibAnnoy。Knowhere 还设计用于支持异构计算。它可以控制在哪个硬件(CPU 或 GPU)上执行索引构建和搜索请求。这就是Knowhere名称的由来--知道在哪里执行操作。未来的版本将支持更多类型的硬件,包括 DPU 和 TPU。

Milvus架构中的Knowhere

下图显示了 Knowhere 在 Milvus 架构中的位置。

Knowhere Knowhere

最底层是系统硬件。第三方索引库位于硬件之上。然后,Knowhere 通过 CGO 与上层的索引节点和查询节点进行交互,CGO 允许 Go 包调用 C 代码。

Knowhere的优势

以下是 Knowhere 与 Faiss 相比的优势。

支持比特视图

Milvus 引入了比特集机制来实现 "软删除"。软删除的向量仍然存在于数据库中,但在向量相似性搜索或查询时不会被计算。

比特集中的每个比特都对应一个索引向量。如果一个向量在比特集中被标记为 "1",则表示该向量已被软删除,在向量搜索过程中将不会涉及。比特集参数适用于 Knowhere 中所有公开的 Faiss 索引查询 API,包括 CPU 和 GPU 索引。

有关比特集机制的更多信息,请查看比特集

支持二进制向量索引的多种相似性度量方法

Knowhere支持HammingJaccardTanimotoSuperstructureSubstructure。Jaccard和Tanimoto可用于测量两个样本集之间的相似性,而Superstructure和Substructure可用于测量化学结构的相似性。

支持 AVX512 指令集

除了Faiss已经支持的AArch64SSE4.2AVX2指令集外,Knowhere还支持AVX512指令集,与AVX2指令集相比,AVX512指令集可将索引构建和查询性能提高20%至30%

自动选择SIMD指令

Knowhere支持在任何CPU处理器(包括内部平台和云平台)上自动调用合适的SIMD指令(如SIMD SSE、AVX、AVX2和AVX512),因此用户无需在编译时手动指定SIMD标志(如"-msse4")。

Knowhere 是通过重构 Faiss 的代码库而构建的。依赖于 SIMD 加速的常用函数(如相似性计算)被分解出来。然后为每个函数实现四个版本(即 SSE、AVX、AVX2 和 AVX512),并将每个版本放入单独的源文件中。然后,使用相应的 SIMD 标志对源文件进行单独编译。因此,在运行时,Knowhere 可以根据当前的 CPU 标志自动选择最合适的 SIMD 指令,然后使用挂钩功能链接正确的函数指针。

其他性能优化

阅读《Milvus: A Purpose-Built Vector Data Management System》,了解有关 Knowhere 性能优化的更多信息。

Knowhere 代码结构

Milvus 中的计算主要涉及向量和标量操作。Knowhere 只处理向量索引的操作。

索引是一种独立于原始向量数据的数据结构。一般来说,建立索引需要四个步骤:创建索引、训练数据、插入数据和建立索引。在一些人工智能应用中,数据集训练与向量搜索是分离的。先对数据集的数据进行训练,然后插入 Milvus 等向量数据库进行相似性搜索。例如,开放数据集 sift1M 和 sift1B 区分了用于训练的数据和用于测试的数据。

然而,在 Knowhere 中,用于训练的数据和用于搜索的数据是相同的。Knowhere 会对一个数据中的所有数据进行训练,然后插入所有训练过的数据并为它们建立索引。

DataObj基类

DataObj 是 Knowhere 中所有数据结构的基类。 是 中唯一的虚拟方法。Index 类继承自 ,其字段名为 "size_"。Index 类还有两个虚拟方法-- 和 。从 派生的 类是所有向量索引的虚拟基类。 提供的方法包括 , , , 和 。Size() DataObj DataObj Serialize() Load() Index VecIndex VecIndex Train() Query() GetStatistics() ClearStatistics()

base class 基类

上图右侧列出了其他一些索引类型。

  • Faiss 索引有两个基类:FaissBaseIndex 用于浮点向量上的所有索引,FaissBaseBinaryIndex 用于二进制向量上的所有索引。

  • GPUIndex 是所有 Faiss GPU 索引的基类。

  • OffsetBaseIndex 是所有自主开发索引的基类。鉴于索引文件中只存储向量 ID,128 维向量的文件大小可减少 2 个数量级。

IDMAP IDMAP

从技术上讲,IDMAP 不是索引,而是用于暴力搜索。向量插入数据库时,既不需要数据训练,也不需要建立索引。搜索将直接在插入的向量数据上进行。

不过,为了保持代码的一致性,IDMAP 也继承自VecIndex 类及其所有虚拟接口。IDMAP 的用法与其他索引相同。

IVF 索引

IVF IVF

IVF(倒置文件)索引是最常用的索引。IVF 类派生自VecIndexFaissBaseIndex ,并进一步扩展到IVFSQIVFPQGPUIVF 派生自GPUIndexIVF 。然后GPUIVF 进一步扩展到GPUIVFSQGPUIVFPQ

IVFSQHybrid 是一个自主开发的混合索引。粗量化器在 GPU 上执行,而桶中的搜索则在 CPU 上进行。 的召回率与 相同,但性能更好。IVFSQHybrid GPUIVFSQ

二进制索引的基类结构相对更简单。BinaryIDMAPBinaryIVF 源自FaissBaseBinaryIndexVecIndex

第三方索引

third-party indexes 第三方索引

目前,除了 Faiss 之外,只支持两种第三方索引:基于树的索引Annoy 和基于图的索引HNSW 。这两种常用的第三方索引均源自VecIndex

向Knowhere添加索引

如果想在Knowhere中添加新的索引,首先可以参考现有的索引:

  • 要添加基于量化的索引,请参考IVF_FLAT

  • 要添加基于图形的索引,请参考HNSW

  • 要添加基于树的索引,请参阅Annoy

参考现有索引后,可以按照以下步骤向Knowhere添加新索引。

  1. IndexEnum 中添加新索引的名称。数据类型为字符串。

  2. 在文件ConfAdapter.cpp 中为新索引添加数据验证检查。验证检查主要用于验证数据训练和查询的参数。

  3. 为新索引创建一个新文件。新索引的基类应包括VecIndexVecIndex 的必要虚拟接口。

  4. VecIndexFactory::CreateVecIndex() 中添加新索引的索引构建逻辑。

  5. unittest 目录下添加单元测试。

下一步工作

在了解了 Knowhere 如何在 Milvus 中运行之后,你可能还想

翻译自DeepLogo

反馈

此页对您是否有帮助?