Knowhere
本主題介紹 Milvus 的核心向量執行引擎 Knowhere。
概述
Knowhere 是 Milvus 的核心向量執行引擎,它整合了多個向量相似性搜尋程式庫,包括Faiss、Hnswlib和Annoy。Knowhere 的設計也支援異質運算。它可以控制在何種硬體(CPU 或 GPU)上執行索引建立和搜尋請求。這就是 Knowhere 名字的由來 - 知道在哪裡執行作業。未來的版本將支援更多的硬體類型,包括 DPU 和 TPU。
Knowhere 在 Milvus 架構中的位置
下圖說明了 Knowhere 在 Milvus 架構中的位置。
Knowhere
最底層是系統硬體。上面是第三方索引庫。在最上層,Knowhere 透過 CGO 與索引節點和查詢節點互動,CGO 允許 Go 套件呼叫 C 程式碼。
Knowhere 的優勢
以下是 Knowhere 相對於 Faiss 的優勢。
支援 BitsetView
Milvus 引入了一個 bitset 機制來實現 「軟刪除」。軟刪除的向量仍然存在於資料庫中,但不會在向量相似性搜索或查詢中被計算出來。
位元集中的每個位元對應一個索引向量。如果一個向量在 bitset 中被標記為 "1",就表示這個向量是軟刪除的,在向量搜尋時不會涉及。bitset 參數應用於 Knowhere 中所有外露的 Faiss 索引查詢 API,包括 CPU 和 GPU 索引。
關於 bitset 機制的更多資訊,請參閱bitset。
索引二進位向量時支援多種相似度指標
Knowhere 支援Hamming、Jaccard、Tanimoto、Superstructure 和Substructure。Jaccard 和 Tanimoto 可用於測量兩個樣本集之間的相似性,而 Superstructure 和 Substructure 則可用於測量化學結構的相似性。
支援 AVX512 指令集
除了 Faiss 已經支援的AArch64、SSE4.2和AVX2 指令集之外,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 指令,然後使用掛鉤(hooking)連結正確的函式指針。
其他效能優化
閱讀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()
基類
上圖右側列出了一些其他的索引類型。
Faiss 索引有兩個基類:
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 上執行。 的召回率與 相同,但性能更佳。IVFSQHybrid
GPUIVFSQ
二元索引的基類結構相對較簡單。BinaryIDMAP
和BinaryIVF
是從FaissBaseBinaryIndex
和VecIndex
衍生出來的。
第三方索引
第三方指數
目前,除了 Faiss 之外,只支援兩種第三方索引:樹狀索引Annoy
,以及圖狀索引HNSW
。這兩種常用的第三方指數都來自VecIndex
。
向Knowhere添加索引
如果你想添加新的索引到Knowhere,首先你可以參考現有的索引:
要添加基於量化的指數,請參考
IVF_FLAT
。要添加基於圖表的索引,請參考
HNSW
。要添加基於樹的索引,請參考
Annoy
。
參考現有索引後,您可以按照以下步驟在Knowhere中添加新索引。
在
IndexEnum
中添加新索引的名稱。資料類型為字串。在文件
ConfAdapter.cpp
中為新索引添加數據驗證檢查。驗證檢查主要是驗證數據訓練和查詢的參數。為新索引建立新檔案。新索引的基類應包括
VecIndex
,以及VecIndex
的必要虛擬介面。在
VecIndexFactory::CreateVecIndex()
中加入新索引的索引建立邏輯。在
unittest
目錄下加入單元測試。
下一步
在學習了 Knowhere 如何在 Milvus 中運作之後,你可能還想