Knowhere
Questo argomento introduce Knowhere, il motore di esecuzione vettoriale di Milvus.
Panoramica
Knowhere è il motore di esecuzione vettoriale principale di Milvus, che incorpora diverse librerie di ricerca di similarità vettoriale, tra cui Faiss, Hnswlib e Annoy. Knowhere è stato progettato anche per supportare l'elaborazione eterogenea. Controlla su quale hardware (CPU o GPU) eseguire le richieste di creazione di indici e di ricerca. È così che Knowhere prende il suo nome: sa dove eseguire le operazioni. Nelle versioni future saranno supportati altri tipi di hardware, tra cui DPU e TPU.
Knowhere nell'architettura Milvus
La figura seguente illustra la posizione di Knowhere nell'architettura Milvus.
Knowhere
Il livello più basso è l'hardware di sistema. Sopra di esso si trovano le librerie di indici di terze parti. Al livello superiore, Knowhere interagisce con il nodo indice e il nodo di interrogazione tramite CGO, che consente ai pacchetti Go di richiamare codice C.
Vantaggi di Knowhere
I vantaggi di Knowhere rispetto a Faiss sono i seguenti.
Supporto per BitsetView
Milvus introduce un meccanismo di bitset per realizzare la "cancellazione morbida". Un vettore eliminato in modo soft esiste ancora nel database, ma non viene calcolato durante una ricerca o un'interrogazione di similarità vettoriale.
Ogni bit di un bitset corrisponde a un vettore indicizzato. Se un vettore è contrassegnato come "1" nel bitset, significa che questo vettore è stato eliminato in modo soft e non sarà coinvolto in una ricerca vettoriale. Il parametro bitset viene applicato a tutte le API di interrogazione dell'indice Faiss esposte in Knowhere, compresi gli indici della CPU e della GPU.
Per ulteriori informazioni sul meccanismo dei bitset, consultare bitset.
Supporto di più metriche di similarità per l'indicizzazione di vettori binari
Knowhere supporta Hamming, Jaccard, Tanimoto, Superstructure e Substructure. Jaccard e Tanimoto possono essere utilizzati per misurare la somiglianza tra due insiemi di campioni, mentre Superstructure e Substructure possono essere utilizzate per misurare la somiglianza tra strutture chimiche.
Supporto per il set di istruzioni AVX512
Oltre ad AArch64, SSE4.2 e AVX2, i set di istruzioni già supportati da Faiss, Knowhere supporta anche AVX512, che può migliorare le prestazioni della creazione di indici e delle query del 20%-30% rispetto ad AVX2.
Selezione automatica delle istruzioni SIMD
Knowhere supporta l'invocazione automatica delle istruzioni SIMD adatte (ad esempio, SIMD SSE, AVX, AVX2 e AVX512) su qualsiasi processore di CPU (sia su piattaforme on-premises che cloud), in modo che gli utenti non debbano specificare manualmente il flag SIMD (ad esempio, "-msse4") durante la compilazione.
Knowhere è stato realizzato attraverso il refactoring della base di codice di Faiss. Le funzioni comuni (ad esempio, il calcolo della somiglianza) che si affidano alle accelerazioni SIMD vengono eliminate. Quindi, per ogni funzione, vengono implementate quattro versioni (SSE, AVX, AVX2, AVX512), ognuna delle quali viene inserita in un file sorgente separato. I file sorgenti vengono poi compilati singolarmente con il corrispondente flag SIMD. Pertanto, in fase di esecuzione, Knowhere è in grado di scegliere automaticamente le istruzioni SIMD più adatte in base ai flag correnti della CPU e di collegare i puntatori alle funzioni giuste utilizzando l'hooking.
Altre ottimizzazioni delle prestazioni
Per ulteriori informazioni sull'ottimizzazione delle prestazioni di Knowhere, leggete Milvus: A Purpose-Built Vector Data Management System.
Struttura del codice di Knowhere
Il calcolo in Milvus coinvolge principalmente operazioni vettoriali e scalari. Knowhere gestisce solo le operazioni di indicizzazione vettoriale.
Un indice è una struttura di dati indipendente dai dati vettoriali originali. In generale, l'indicizzazione richiede quattro fasi: creare un indice, addestrare i dati, inserire i dati e costruire un indice. In alcune applicazioni di intelligenza artificiale, l'addestramento dei dataset è separato dalla ricerca dei vettori. I dati dei dataset vengono prima addestrati e poi inseriti in un database vettoriale come Milvus per la ricerca di similarità. Ad esempio, i dataset aperti sift1M e sift1B differenziano i dati per l'addestramento da quelli per i test.
In Knowhere, invece, i dati per l'addestramento e per la ricerca sono gli stessi. Knowhere addestra tutti i dati di un segmento, quindi inserisce tutti i dati addestrati e costruisce un indice per essi.
DataObj
: classe base
DataObj
è la classe base di tutte le strutture dati di Knowhere. Size()
è l'unico metodo virtuale di DataObj
. La classe Index eredita da DataObj
con un campo chiamato "size_". La classe Indice ha anche due metodi virtuali: Serialize()
e Load()
. La classe VecIndex
derivata da Index
è la classe base virtuale per tutti gli indici vettoriali. VecIndex
fornisce metodi tra cui Train()
, Query()
, GetStatistics()
e ClearStatistics()
.
classe base
Alcuni altri tipi di indice sono elencati a destra nella figura precedente.
L'indice di Faiss ha due classi base:
FaissBaseIndex
per tutti gli indici su vettori in virgola mobile eFaissBaseBinaryIndex
per tutti gli indici su vettori binari.GPUIndex
è la classe base per tutti gli indici Faiss GPU.OffsetBaseIndex
è la classe base per tutti gli indici sviluppati in proprio. Dato che in un file di indice vengono memorizzati solo gli ID dei vettori, la dimensione del file per i vettori a 128 dimensioni può essere ridotta di 2 ordini di grandezza.
IDMAP
: ricerca a forza bruta
IDMAP
Tecnicamente parlando, IDMAP
non è un indice, ma viene utilizzato per la ricerca bruta. Quando i vettori vengono inseriti nel database, non è necessario né addestrare i dati né costruire un indice. Le ricerche saranno condotte direttamente sui dati vettoriali inseriti.
Tuttavia, per coerenza di codice, IDMAP
eredita anche dalla classe VecIndex
con tutte le sue interfacce virtuali. L'uso di IDMAP
è lo stesso degli altri indici.
Indici FIV
FIV
Gli indici IVF (inverted file) sono i più utilizzati. La classe IVF
è derivata da VecIndex
e FaissBaseIndex
, e si estende ulteriormente a IVFSQ
e IVFPQ
. GPUIVF
è derivata da GPUIndex
e IVF
. Poi GPUIVF
si estende ulteriormente a GPUIVFSQ
e GPUIVFPQ
.
IVFSQHybrid
è un indice ibrido sviluppato in proprio. Un quantizzatore grossolano viene eseguito sulla GPU, mentre la ricerca nel bucket viene eseguita dalla CPU. Questo tipo di indice può ridurre il numero di copie di memoria tra CPU e GPU, sfruttando la potenza di calcolo della GPU. IVFSQHybrid
ha lo stesso tasso di richiamo di GPUIVFSQ
, ma offre prestazioni migliori.
La struttura delle classi base per gli indici binari è relativamente più semplice. BinaryIDMAP
e BinaryIVF
sono derivati da FaissBaseBinaryIndex
e VecIndex
.
Indici di terze parti
indici di terze parti
Attualmente sono supportati solo due tipi di indici di terze parti, oltre a Faiss: l'indice ad albero Annoy
e l'indice a grafo HNSW
. Questi due indici di terze parti, comuni e frequentemente utilizzati, sono entrambi derivati da VecIndex
.
Aggiungere indici a Knowhere
Se si desidera aggiungere nuovi indici a Knowhere, per prima cosa è possibile fare riferimento agli indici esistenti:
Per aggiungere indici basati sulla quantizzazione, fare riferimento a
IVF_FLAT
.Per aggiungere indici basati su grafi, fare riferimento a
HNSW
.Per aggiungere indici ad albero, fare riferimento a
Annoy
.
Dopo aver fatto riferimento all'indice esistente, si può seguire la procedura seguente per aggiungere un nuovo indice a Knowhere.
Aggiungere il nome del nuovo indice in
IndexEnum
. Il tipo di dati è stringa.Aggiungere il controllo di convalida dei dati sul nuovo indice nel file
ConfAdapter.cpp
. Il controllo di convalida serve principalmente a convalidare i parametri per la formazione dei dati e la query.Creare un nuovo file per il nuovo indice. La classe base del nuovo indice deve includere
VecIndex
e l'interfaccia virtuale necessaria diVecIndex
.Aggiungere la logica di costruzione del nuovo indice in
VecIndexFactory::CreateVecIndex()
.Aggiungere il test unitario nella cartella
unittest
.
Il prossimo passo
Dopo aver appreso il funzionamento di Knowhere in Milvus, si consiglia di:
Conoscere i vari tipi di indici supportati da Milvus.
Conoscere il meccanismo dei bitset.
Capire come vengono elaborati i dati in Milvus.