Knowhere
Milvusのコアとなるベクトル実行エンジンKnowhereについて紹介します。
概要
KnowhereはMilvusの中核となるベクトル実行エンジンで、Faiss、Hnswlib、Annoyを含む複数のベクトル類似性検索ライブラリを内蔵しています。また、Knowhereはヘテロジニアスコンピューティングをサポートするように設計されています。インデックス構築と検索要求をどのハードウェア(CPUまたはGPU)で実行するかを制御する。これがKnowhereの名前の由来である。将来のリリースでは、DPUやTPUを含む、より多くの種類のハードウェアがサポートされる予定です。
MilvusアーキテクチャにおけるKnowhere
下図は、MilvusアーキテクチャにおけるKnowhereの位置を示しています。
Knowhere
最下層はシステム・ハードウェアです。その上にサードパーティのインデックス・ライブラリが配置されています。一番上のレイヤでは、KnowhereはCGOを介してインデックスノードやクエリノードと対話します。
Knowhereの利点
以下はKnowhereがFaissより優れている点です。
BitsetViewのサポート
Milvusは "ソフト削除 "を実現するためにビットセット機構を導入しています。ソフト削除されたベクトルはデータベースに存在しますが、ベクトルの類似性検索やクエリの際に計算されることはありません。
ビットセットの各ビットはインデックス付きベクトルに対応する。あるベクトルがビットセットで "1 "とマークされた場合、そのベクトルはソフト削除され、ベクトル検索には関与しないことを意味する。bitset パラメータは、CPU および GPU インデックスを含む、Knowhere で公開されているすべての Faiss インデックス照会 API に適用されます。
bitset メカニズムの詳細については、bitset を参照してください。
バイナリ・ベクトルのインデックス作成における複数の類似性メトリクスのサポート
Knowhereはハミング、Jaccard、Tanimoto、Superstructure、Substructureをサポートしています。Jaccard と Tanimoto は 2 つのサンプル・セット間の類似度を測定するために使用でき、Superstructure と Substructure は化学構造の類似度を測定するために使用できます。
AVX512命令セットのサポート
FaissがすでにサポートしているAArch64、SSE4.2、AVX2以外に、KnowhereはAVX512もサポートしています。AVX512はAVX2と比較してインデックス構築とクエリの性能を20~30%向上させることができます。
SIMD命令の自動選択
Knowhereは、あらゆるCPUプロセッサ(オンプレミスとクラウドの両方のプラットフォーム)で適切なSIMD命令(SIMD SSE、AVX、AVX2、AVX512など)を自動的に呼び出すことをサポートしているため、ユーザーはコンパイル時にSIMDフラグ("-msse4 "など)を手動で指定する必要がありません。
KnowhereはFaissのコードベースをリファクタリングして構築されています。SIMDアクセラレーションに依存する一般的な関数(類似度計算など)はファクタアウトされます。次に、各関数について4つのバージョン(すなわち、SSE、AVX、AVX2、AVX512)が実装され、それぞれが別々のソースファイルに入れられます。その後、ソースファイルは対応する SIMD フラグで個別にコンパイルされます。したがって、Knowhere は実行時に現在の CPU フラグに基づいて最適な SIMD 命令を自動的に選択し、フッキングを使用して適切な関数ポインタをリンクします。
その他の性能最適化
Knowhereのパフォーマンス最適化については、Milvus: A Purpose-Built Vector Data Management Systemを参照してください。
Knowhereのコード構造
Milvusの計算には主にベクトル演算とスカラー演算が含まれます。Knowhereはベクトル・インデックスの操作のみを扱います。
インデックスは元のベクトルデータから独立したデータ構造です。一般的に、インデックスの作成には、インデックスの作成、データの学習、データの挿入、インデックスの構築という4つのステップが必要です。AIアプリケーションの中には、データセットの学習とベクトル探索が分離されているものもある。データセットのデータはまず学習され、類似検索のためにmilvusのようなベクトルデータベースに挿入される。例えば、オープンデータセットsift1Mとsift1Bは、学習用データとテスト用データを区別している。
しかし、Knowhereでは学習用データと検索用データは同じです。Knowhereはセグメント内のすべてのデータを学習し、学習済みデータを挿入してインデックスを作成します。
DataObj
基底クラス
DataObj
Size()
は の唯一の仮想メソッドです。Indexクラスは 、"size_"というフィールドを継承しています。また、Index クラスには と の 2 つの仮想メソッドがあります。 から派生した クラスは、すべてのベクトル・インデックスの仮想基底クラスです。 は、 、 、 、 などのメソッドを提供します。DataObj
DataObj
Serialize()
Load()
Index
VecIndex
VecIndex
Train()
Query()
GetStatistics()
ClearStatistics()
基底クラス
その他のインデックス・タイプを上図の右側にいくつか示します。
Faissインデックスには2つの基底クラスがあります:浮動小数点ベクトル上のすべてのインデックス用の
FaissBaseIndex
、バイナリ・ベクトル上のすべてのインデックス用のFaissBaseBinaryIndex
。GPUIndex
はすべてのFaiss GPUインデックスの基底クラスです。OffsetBaseIndex
はすべての自己開発インデックスの基本クラスです。ベクトルIDのみがインデックス・ファイルに格納されることを考えると、128次元ベクトルのファイル・サイズは2桁小さくなります。
IDMAP
ブルートフォース検索
IDMAP
厳密に言えば、IDMAP
はインデックスではなく、ブルートフォース検索に使用されます。ベクトルがデータベースに挿入される際、データ学習もインデックス構築も必要ない。検索は挿入されたベクトルデータに対して直接行われる。
しかし、コードの一貫性を保つために、IDMAP
はVecIndex
クラスを継承し、その仮想インターフェースもすべて継承している。IDMAP
の使い方は他のインデックスと同じである。
IVFインデックス
IVF
IVF(転置ファイル)インデックスは最も頻繁に使用される。IVF
クラスはVecIndex
とFaissBaseIndex
から派生し、さらにIVFSQ
とIVFPQ
へと拡張される。GPUIVF
はGPUIndex
とIVF
から派生する。そしてGPUIVF
はさらにGPUIVFSQ
とGPUIVFPQ
に拡張される。
IVFSQHybrid
は、独自に開発したハイブリッド・インデックスである。粗い量子化器はGPUで実行され、バケット内の検索はCPUで実行される。このタイプのインデックスは、GPUの計算能力を活用することで、CPUとGPU間のメモリコピーの発生を減らすことができる。 は、 と同じ想起率を持つが、より優れた性能を持つ。IVFSQHybrid
GPUIVFSQ
BinaryIDMAP
とBinaryIVF
はFaissBaseBinaryIndex
とVecIndex
から派生したものである。
サードパーティ・インデックス
サード・パーティ・インデックス
現在、Faiss以外のサードパーティ・インデックスとしてサポートされているのは、ツリーベース・インデックスAnnoy
とグラフベース・インデックスHNSW
の2種類のみである。これら 2 つの一般的で頻繁に使用されるサードパーティ・インデックスは、いずれもVecIndex
から派生したものである。
Knowhere へのインデックスの追加
Knowhere に新しいインデックスを追加する場合、まず既存のインデックスを参照します:
量子化ベースのインデックスを追加するには、
IVF_FLAT
を参照。グラフベースのインデックスを追加するには、
HNSW
を参照。ツリーベースのインデックスを追加するには、
Annoy
を参照してください。
既存のインデックスを参照した後、以下の手順に従って新しいインデックスを Knowhere に追加できます。
IndexEnum
に新しいインデックスの名前を追加します。デー タ 型は文字列です。フ ァ イ ル
ConfAdapter.cpp
に、 新 し い イ ンデ ッ ク ス にデー タ 検証チ ェ ッ ク を追加 し ます。検証チェックは、主にデータ学習とクエリのパラメータを検証するためのものです。新しいインデックス用に新しいファイルを作成します。新しいインデックスの基底クラスには、
VecIndex
とVecIndex
の必要な仮想インタフェースを含める。新しいインデックスのインデックス構築ロジックを
VecIndexFactory::CreateVecIndex()
に追加する。unittest
ディレクトリの下にユニットテストを追加する。
次のステップ
MilvusでKnowhereがどのように動作するのかを学んだ後は、次のことを行ってください:
Milvusでデータがどのように処理されるかを理解する。