Che cosa potenzia la ricerca di similarità nel database vettoriale Milvus?
immagine di copertina
Questo articolo è stato scritto da Yudong Cai e tradotto da Angela Ni.
Knowhere, il motore di esecuzione vettoriale principale, è per Milvus quello che un motore è per un'auto sportiva. Questo articolo presenta cos'è Knowhere, come si differenzia da Faiss e come è strutturato il codice di Knowhere.
Vai a:
- Il concetto di Knowhere
- Knowhere nell'architettura Milvus
- Knowhere contro Faiss
- Capire il codice di Knowhere
- Aggiungere indici a Knowhere
Il concetto di Knowhere
In senso stretto, Knowhere è un'interfaccia operativa per l'accesso ai servizi negli strati superiori del sistema e alle librerie di ricerca di similarità vettoriale come Faiss, Hnswlib, Annoy negli strati inferiori del sistema. Inoltre, Knowhere è anche responsabile dell'elaborazione eterogenea. Più precisamente, Knowhere controlla su quale hardware (ad esempio, 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.
In senso più ampio, Knowhere incorpora anche altre librerie di indici di terze parti, come Faiss. Pertanto, nel suo complesso, Knowhere è riconosciuto come il motore di calcolo vettoriale principale del database vettoriale Milvus.
Dal concetto di Knowhere, si evince che esso elabora solo compiti di calcolo dei dati, mentre compiti come lo sharding, il bilanciamento del carico e il disaster recovery esulano dall'ambito di lavoro di Knowhere.
A partire da Milvus 2.0.1, Knowhere (in senso lato) diventa indipendente dal progetto Milvus.
Knowhere nell'architettura di Milvus
architettura di knowhere
Il calcolo in Milvus coinvolge principalmente operazioni vettoriali e scalari. Knowhere gestisce solo le operazioni sui vettori in Milvus. La figura sopra illustra l'architettura di Knowhere in Milvus.
Il livello più basso è l'hardware di sistema. Le librerie di indici di terze parti si trovano sopra l'hardware. Quindi Knowhere interagisce con il nodo indice e il nodo di interrogazione in alto tramite CGO.
Questo articolo parla di Knowhere nel suo senso più ampio, come indicato nella cornice blu dell'illustrazione dell'architettura.
Knowhere vs Faiss
Knowhere non solo estende ulteriormente le funzioni di Faiss, ma ne ottimizza anche le prestazioni. In particolare, Knowhere presenta i seguenti vantaggi.
1. Supporto per BitsetView
Inizialmente, il bitset è stato introdotto in Milvus per 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 del 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.
I parametri bitset vengono aggiunti a tutte le API di interrogazione dell'indice Faiss esposte in Knowhere, compresi gli indici della CPU e della GPU.
Per saperne di più su come bitset consente la versatilità della ricerca vettoriale.
2. Supporto per altre metriche di similarità per l'indicizzazione di vettori binari
Oltre a Hamming, Knowhere supporta anche 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 utilizzati per misurare la somiglianza tra strutture chimiche.
3. Supporto per il set di istruzioni AVX512
Faiss supporta diversi set di istruzioni, tra cui AArch64, SSE4.2 e AVX2. Knowhere estende ulteriormente i set di istruzioni supportati aggiungendo AVX512, che può migliorare le prestazioni della creazione di indici e delle interrogazioni del 20-30% rispetto ad AVX2.
4. Selezione automatica delle istruzioni SIMD
Knowhere è stato progettato per funzionare bene su un ampio spettro di processori CPU (sia su piattaforme on-premises che cloud) con diverse istruzioni SIMD (ad esempio, SIMD SSE, AVX, AVX2 e AVX512). Quindi la sfida è: dato un singolo software binario (ad esempio, Milvus), come fare in modo che invochi automaticamente le istruzioni SIMD adatte su qualsiasi processore della CPU? Faiss non supporta la selezione automatica delle istruzioni SIMD e gli utenti devono specificare manualmente il flag SIMD (ad esempio, "-msse4") durante la compilazione. Tuttavia, Knowhere è stato costruito con il refactoring della base di codice di Faiss. Le funzioni comuni (ad esempio, il calcolo della somiglianza) che si basano sull'accelerazione 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.
5. Altre ottimizzazioni delle prestazioni
Per ulteriori informazioni sull'ottimizzazione delle prestazioni di Knowhere, leggete Milvus: A Purpose-Built Vector Data Management System.
Comprendere il codice di Knowhere
Come detto nella prima sezione, Knowhere gestisce solo operazioni di ricerca vettoriale. Pertanto, Knowhere elabora solo il campo vettoriale di un'entità (attualmente è supportato solo un campo vettoriale per le entità di una collezione). Anche la costruzione di indici e la ricerca di similarità vettoriale sono mirate al campo vettoriale di un segmento. Per comprendere meglio il modello dei dati, leggete il blog qui.
campi entità
Indice
L'indice è un tipo di struttura dati indipendente dai dati vettoriali originali. L'indicizzazione richiede quattro fasi: creare un indice, formare i dati, inserire i dati e costruire un indice.
Per alcune applicazioni di intelligenza artificiale, l'addestramento del set di dati è un processo indipendente dalla ricerca vettoriale. In questo tipo di applicazioni, i dati dei dataset vengono prima addestrati e poi inseriti in un database vettoriale come Milvus per la ricerca di similarità. I dataset aperti come sift1M e sift1B forniscono dati per l'addestramento e il test. Tuttavia, in Knowhere, i dati per l'addestramento e la ricerca sono mescolati insieme. In altre parole, Knowhere addestra tutti i dati in un segmento e poi inserisce tutti i dati addestrati e costruisce un indice per essi.
Struttura del codice di Knowhere
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 Index 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 come Train()
, Query()
, GetStatistics()
e ClearStatistics()
.
classe base
Altri tipi di indice sono elencati a destra nella figura precedente.
- L'indice Faiss ha due sottoclassi: FaissBaseIndex per tutti gli indici su vettori in virgola mobile e FaissBaseBinaryIndex 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. Nel file di indice viene memorizzato solo l'ID del vettore. Di conseguenza, la dimensione di un file di indice per vettori a 128 dimensioni può essere ridotta di 2 ordini di grandezza. Si consiglia di prendere in considerazione anche i vettori originali quando si utilizza questo tipo di indice per la ricerca di similarità vettoriale.
IDMAP
Tecnicamente parlando, IDMAP non è un indice, ma è piuttosto utilizzato per la ricerca a forza bruta. Quando i vettori vengono inseriti nel database vettoriale, non è necessario addestrare i dati e costruire l'indice. Le ricerche saranno condotte direttamente sui dati vettoriali inseriti.
Tuttavia, per motivi di coerenza del codice, IDMAP eredita anche dalla classe VecIndex con tutte le sue interfacce virtuali. L'uso di IDMAP è lo stesso degli altri indici.
FIV
Gli indici IVF (inverted file) sono i più utilizzati. La classe IVF deriva da VecIndex e FaissBaseIndex e si estende ulteriormente a IVFSQ e IVFPQ. GPUIVF deriva da GPUIndex e IVF. GPUIVF si estende ulteriormente a GPUIVFSQ e GPUIVFPQ.
IVFSQHybrid è una classe per l'indice ibrido auto-sviluppato che viene eseguito mediante quantizzazione grossolana su GPU. 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 di base per gli indici binari è relativamente più semplice. BinaryIDMAP e BinaryIVF sono derivati da FaissBaseBinaryIndex e VecIndex.
indice 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.
Aggiunta di indici a Knowhere
Se si desidera aggiungere nuovi indici a Knowhere, è possibile fare riferimento prima agli indici esistenti:
- Per aggiungere un indice basato sulla quantizzazione, fare riferimento a IVF_FLAT.
- Per aggiungere un indice basato sui grafi, fare riferimento a HNSW.
- Per aggiungere un indice ad albero, fare riferimento a Annoy.
Dopo aver fatto riferimento agli indici esistenti, è possibile seguire i passaggi seguenti 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
.
Informazioni sulla serie Deep Dive
Con l'annuncio ufficiale della disponibilità generale di Milvus 2.0, abbiamo organizzato questa serie di blog Milvus Deep Dive per fornire un'interpretazione approfondita dell'architettura e del codice sorgente di Milvus. Gli argomenti trattati in questa serie di blog includono:
- Il concetto di Knowhere
- Knowhere nell'architettura di Milvus
- Knowhere vs Faiss
- Comprendere il codice di Knowhere
- Aggiunta di indici a Knowhere
- Informazioni sulla serie Deep Dive
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word