🚀 Prova Zilliz Cloud, la versione completamente gestita di Milvus, gratuitamente—sperimenta prestazioni 10 volte più veloci! Prova Ora>>

milvus-logo
LFAI
  • Home
  • Blog
  • DiskANN, una soluzione ANNS basata su disco con alto richiamo e alto QPS su un set di dati su scala miliardaria

DiskANN, una soluzione ANNS basata su disco con alto richiamo e alto QPS su un set di dati su scala miliardaria

  • Engineering
September 24, 2021
Zilliz

Chengming Li, ingegnere R&S di Zilliz, si è laureato alla SouthEast University con un master in informatica. Attualmente si occupa di problemi di ANNS su dati ad alta dimensionalità, comprese soluzioni basate su grafi e quantizzazione.

"DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node" è un articolo pubblicato su NeurIPS nel 2019. L'articolo introduce un metodo all'avanguardia per eseguire la costruzione di indici e la ricerca su dataset di dimensioni miliardarie utilizzando una singola macchina con soli 64 GB di RAM e un SSD sufficientemente grande. Inoltre, soddisfa i tre requisiti di ANNS (Approximate Nearest Neighbor Search) sul dataset di grandi dimensioni: elevato richiamo, bassa latenza e alta densità (numero di nodi in una singola macchina). Questo metodo costruisce un indice basato su grafi su un dataset SIFT-1B su scala miliardaria utilizzando una singola macchina con 64 GB di RAM e una CPU a 16 core, raggiungendo 5000 QPS (query al secondo) con un richiamo superiore al 95%@1 e una latenza media inferiore a 3ms.

Gli autori

Suhas Jayaram Subramanya: ex dipendente del Microsoft India Research Institute, dottorando alla CMU. I suoi principali interessi di ricerca sono il calcolo ad alte prestazioni e gli algoritmi di apprendimento automatico per dati su larga scala.

Devvrit: Assistente di ricerca presso l'Università del Texas ad Austin. I suoi interessi di ricerca sono l'informatica teorica, l'apprendimento automatico e l'apprendimento profondo.

Rohan Kadekodi: Studente di dottorato presso l'Università del Texas. Il suo indirizzo di ricerca è il sistema e lo storage, che comprende principalmente lo storage persistente, il file system e lo storage kV.

Ravishankar Krishaswamy: Ricercatore principale dell'istituto di ricerca indiano di Microsoft. Dottore della CMU. La direzione di ricerca è l'algoritmo di approssimazione basato su grafi e clustering.

Harsha Vardhan Simhadri: ricercatore principale dell'istituto di ricerca indiano Microsoft. Dottore della CMU. In passato ha studiato algoritmi paralleli e sistemi runtime. Ora il suo lavoro principale è sviluppare nuovi algoritmi e scrivere modelli di programmazione.

Motivazioni

La maggior parte degli algoritmi ANNS mainstream effettua dei compromessi tra le prestazioni di costruzione dell'indice, le prestazioni di ricerca e il richiamo. Gli algoritmi basati su grafi, come HNSW e NSG, sono attualmente lo stato dell'arte in termini di prestazioni di ricerca e richiamo. Poiché il metodo di indicizzazione a grafo residente in memoria occupa una quantità eccessiva di memoria, è relativamente difficile indicizzare e ricercare un insieme di dati su larga scala utilizzando una singola macchina con risorse di memoria limitate.

Molte applicazioni richiedono risposte rapide di ANNS basato sulla distanza euclidea su un insieme di dati su scala miliardaria. Di seguito sono riportate due soluzioni principali:

  1. Indice invertito + quantizzazione: raggruppare il dataset in M partizioni e comprimere il dataset utilizzando schemi di quantizzazione come PQ (Product Quantization). Questa soluzione produce un basso richiamo a causa della perdita di precisione causata dalla compressione dei dati. Aumentare il topk aiuta a migliorare il richiamo, mentre il QPS diminuisce di conseguenza.
  2. Dividere e indicizzare: dividere il set di dati in diversi frammenti disgiunti e costruire un indice in-memory per ciascun frammento. Quando arrivano le richieste di interrogazione, la ricerca viene eseguita sugli indici di ogni shard e i risultati vengono restituiti dopo l'unione. Questa soluzione provoca un'espansione eccessiva della scala del dataset e quindi sono necessarie più macchine a causa della limitazione delle risorse di memoria in una singola macchina, con conseguente basso QPS.

Entrambe le soluzioni sopra menzionate sono limitate dalla restrizione di memoria di una singola macchina. Il presente documento propone la progettazione di un meccanismo di indicizzazione residente su SSD per risolvere questo problema. La sfida dell'indicizzazione residente su SSD consiste nel ridurre il numero di accessi casuali al disco e il numero di richieste di accesso al disco.

Contributi

Questo lavoro presenta uno schema ANNS residente su SSD chiamato DiskANN, che può supportare efficacemente la ricerca su dataset di grandi dimensioni. Questo schema è basato su un algoritmo a grafo presentato in questo articolo: Vamana. I contributi di questo lavoro includono:

  1. DiskANN è in grado di indicizzare e ricercare un dataset di oltre 100 dimensioni su una singola macchina con 64 GB di RAM, fornendo oltre il 95% di recall@1 con latenze inferiori a 5 millisecondi.
  2. Per ridurre al minimo il numero di accessi al disco, è stato proposto un nuovo algoritmo a grafo, chiamato Vamana, con un raggio di ricerca più piccolo rispetto a quelli di NSG e HNSW.
  3. Vamana può lavorare in memoria e le sue prestazioni non sono inferiori a quelle di NSG e HNSW.
  4. Gli indici Vamana più piccoli costruiti su partizioni sovrapposte di un grande insieme di dati possono essere uniti in un unico grafo senza perdere la connettività.
  5. Vamana può essere combinato con schemi di quantizzazione come PQ. La struttura del grafo e i dati originali sono memorizzati sul disco, mentre i dati compressi sono conservati in memoria.

Vamana

Questo algoritmo è simile all'idea di NSG[2][4] (per coloro che non capiscono NSG, si prega di fare riferimento a [2], e se non si vuole leggere documenti, si può fare riferimento a [4]). La loro differenza principale risiede nella strategia di trimming. Per essere precisi, alla strategia di trimming di NSG è stato aggiunto un interruttore alfa. L'idea principale della strategia di trimming di NSG è che la scelta dei vicini del punto target sia la più varia possibile. Se il nuovo vicino è più vicino a un vicino del punto target rispetto al punto target, non è necessario aggiungere questo punto all'insieme dei punti vicini. In altre parole, per ogni vicino del punto target, non ci possono essere altri punti vicini entro il raggio circostante dist (punto target, punto vicino). Questa strategia di trimming controlla efficacemente l'out-degree del grafo ed è relativamente radicale. Riduce l'ingombro in memoria dell'indice, migliora la velocità di ricerca, ma riduce anche l'accuratezza della ricerca. La strategia di trimming di Vamana consiste nel controllare liberamente la scala di trimming attraverso il parametro alfa. Il principio di funzionamento consiste nel moltiplicare la distanza (punto vicino, punto candidato) nella condizione di trimming con un parametro alfa (non inferiore a 1). Solo quando la distanza (punto di destinazione, un certo punto candidato) è maggiore della distanza di riferimento allargata viene adottata la strategia di trimming, aumentando la tolleranza di mutua esclusione tra i vicini del punto di destinazione.

Il processo di indicizzazione di Vamana è relativamente semplice:

  1. Inizializzare un grafo casuale;
  2. Calcolare il punto di partenza, che è simile al punto di navigazione di NSG. In primo luogo, si trova il centroide globale, quindi si individua il punto più vicino al centroide globale come punto di navigazione. La differenza tra Vamana e NSG è che l'input di NSG è già un grafo di prossimità, quindi gli utenti possono semplicemente eseguire una ricerca approssimativa del punto di centroide direttamente sul grafo di prossimità iniziale. Tuttavia, Vamana inizializza un grafo dei vicini casuale, quindi gli utenti non possono condurre una ricerca approssimativa direttamente sul grafo casuale. È necessario effettuare un confronto globale per ottenere un punto di navigazione come punto di partenza delle iterazioni successive. Lo scopo di questo punto è minimizzare il raggio di ricerca medio;
  3. Eseguire la ricerca approssimata dei vicini più vicini su ogni punto in base al grafo dei vicini casuale inizializzato e al punto di partenza della ricerca determinato al punto 2, rendere tutti i punti sul percorso di ricerca gli insiemi di vicini candidati ed eseguire la strategia di ritaglio dei bordi utilizzando alfa = 1. Come nel caso di NSG, la selezione dell'insieme di punti sul percorso di ricerca a partire dal punto di navigazione come insieme di vicini candidati aumenterà alcuni bordi lunghi e ridurrà efficacemente il raggio di ricerca.
  4. Regolare alfa > 1 (il documento consiglia 1,2) e ripetere il passaggio 3. Mentre il passo 3 si basa su un grafo di vicini casuale, il grafo è di bassa qualità dopo la prima iterazione. Pertanto, è necessaria un'altra iterazione per migliorare la qualità del grafo, che è molto importante per il tasso di richiamo.

Il presente documento confronta i tre indici a grafo, ossia Vamana, NSG e HNSW. In termini di indicizzazione e prestazioni delle query, Vamana e NSG sono relativamente vicini ed entrambi superano leggermente HNSW. Per i dati si rimanda alla sezione Esperimenti.

2.png 2.png

Per visualizzare il processo di costruzione dell'indice di Vamana, il documento fornisce un grafico in cui vengono utilizzati 200 punti bidimensionali per simulare due cicli di iterazione. La prima riga utilizza alfa = 1 per tagliare i bordi. Si può notare che la strategia di rifilatura è relativamente radicale e un gran numero di bordi viene rifilato. Dopo aver aumentato il valore di alfa e allentato le condizioni di rifilatura, molti bordi vengono ovviamente aggiunti di nuovo. Nel grafo finale, vengono aggiunti molti bordi lunghi. In questo modo è possibile ridurre efficacemente il raggio di ricerca.

DiscoANN

Un personal computer con soli 64 GB di memoria non riuscirebbe a contenere nemmeno un miliardo di dati grezzi, per non parlare dell'indice costruito su di essi. Ci sono due sfide da affrontare: 1. Come indicizzare un insieme di dati di tale portata con risorse di memoria limitate? 2. Come calcolare la distanza durante la ricerca se i dati originali non possono essere caricati in memoria?

Il documento propone le seguenti soluzioni:

  1. Per la prima sfida: dividere i dati in k cluster utilizzando k-means, quindi allocare ogni punto nei cluster più vicini a i. In genere, 2 è sufficiente per il numero i. Costruire un indice Vamana basato sulla memoria per ogni cluster e infine unire i k indici Vamana in uno solo.
  2. Per la seconda sfida: costruire indici sui vettori originali e interrogare i vettori compressi. La costruzione di indici sul vettore originale garantisce la qualità del grafo, mentre il vettore compresso può essere caricato in memoria per una ricerca a grana grossa. Sebbene la ricerca con i vettori compressi possa causare una perdita di precisione, la direzione generale sarà corretta finché la qualità del grafo è sufficientemente alta. Il risultato finale della distanza sarà calcolato utilizzando il vettore originale.

La disposizione degli indici di DiskANN è simile a quella degli indici dei grafi generali. L'insieme dei vicini di ogni punto e i dati del vettore originale sono memorizzati insieme. In questo modo si sfrutta meglio la localizzazione dei dati.

Come accennato in precedenza, se i dati dell'indice sono memorizzati sull'unità SSD, il numero di accessi al disco e le richieste di lettura e scrittura del disco devono essere ridotti il più possibile per garantire un basso ritardo di ricerca. Pertanto DiskANN propone due strategie di ottimizzazione:

  1. Cache hotspot: memorizzare tutti i punti entro C salti dal punto di partenza in memoria. Il valore di C è preferibile impostarlo tra 3 e 4.
  2. Ricerca a raggiera: In parole povere, consiste nel precaricare le informazioni sui vicini. Quando si cerca un punto p, il punto vicino di p deve essere caricato dal disco se non è presente in memoria. Poiché una piccola quantità di operazioni di accesso casuale all'SSD richiede circa lo stesso tempo di un'operazione di accesso a un singolo settore dell'SSD, è possibile caricare le informazioni sui vicini di W punti non accessibili alla volta. W non può essere impostato troppo grande o troppo piccolo. Un W grande comporta uno spreco di risorse di calcolo e di larghezza di banda dell'SSD, mentre uno piccolo aumenta il ritardo della ricerca.

Esperimento

L'esperimento è composto da tre gruppi:

Confronto tra indici basati sulla memoria: Vamana VS. NSG VS. HNSW

Set di dati: SIFT1M (128 dimensioni), GIST1M (960 dimensioni), DEEP1M (96 dimensioni) e un set di dati di 1M campionato casualmente da DEEP1B.

Parametri dell'indice (tutti i set di dati utilizzano lo stesso set di parametri):

HNSW:M = 128, efc = 512.

Vamana: R = 70, L = 75, alfa = 1,2.

NSG: R = 60, L = 70, C= 500.

I parametri di ricerca non sono forniti nel documento, che potrebbe essere coerente con i parametri di indicizzazione. Per la selezione dei parametri, i parametri di NSG citati nell'articolo si basano sui parametri elencati nel repository GitHub di NSG per selezionare il gruppo con prestazioni migliori. Vamana e NSG sono relativamente vicini, quindi anche i parametri sono impostati vicini. Tuttavia, il motivo della selezione dei parametri di HNSW non è indicato. Riteniamo che il parametro M di HNSW sia relativamente grande. Potrebbe portare a un confronto meno convincente tra gli indici a grafo se i loro out-degrees non sono impostati allo stesso livello.

Con i parametri di indicizzazione sopra indicati, i tempi di indicizzazione di Vamana, HNSW e NSG sono rispettivamente di 129, 219 e 480 secondi. Il tempo di indicizzazione di NSG include il tempo di costruzione del grafo dei vicini iniziale con EFANN [3].

Curva Richiamo-QPS:

3.png 3.png

Dalla Figura 3 si può notare che Vamana ha un'ottima performance sui tre set di dati, simile a NSG e leggermente migliore di HNSW.

Confronto del raggio di ricerca:

Dalla Figura 2.c, possiamo vedere che Vamana ha il percorso di ricerca medio più breve a parità di tasso di richiamo rispetto a quelli di NSG e HNSW.

Confronto tra un indice costruito una sola volta e un indice unito di grandi dimensioni

Set di dati: SIFT1B

Parametri dell'indice costruito una sola volta: L = 50, R = 128, alfa = 1,2. Dopo un'esecuzione di 2 giorni su una macchina DDR3 da 1800 G, il picco di memoria è di circa 1100 G e l'out-degree medio è di 113,9.

Procedura di indicizzazione basata sulla fusione:

  1. Formare 40 cluster sul set di dati utilizzando kmeans;
  2. Ogni punto viene distribuito nei 2 cluster più vicini;
  3. Costruire un indice Vamana con L = 50, R = 64 e alfa = 1,2 per ogni cluster;
  4. Unire gli indici di ciascun cluster.

Questo indice ha generato un indice di 384 GB con un out-of-degree medio di 92,1. L'indice è stato eseguito per 5 giorni su una macchina da 64 GB DDR4.

I risultati del confronto sono i seguenti (Figura 2a): 4.png 4.png

In conclusione:

  1. L'indice costruito una sola volta è significativamente migliore dell'indice basato sulla fusione;
  2. Anche l'indice basato sulla fusione è eccellente;
  3. Lo schema di indicizzazione basato sulla fusione è applicabile anche al set di dati DEEP1B (Figura 2b).

Indice basato su disco: DiskANN VS. FAISS VS. IVF-OADC+G+P

IVFOADC+G+P è un algoritmo proposto nel riferimento [5].

Questo documento confronta solo DiskANN con IVFOADC+G+P, poiché il riferimento [5] ha dimostrato che IVFOADC+G+P è migliore di FAISS. Inoltre, FAISS richiede risorse GPU, che non sono supportate da tutte le piattaforme.

IVF-OADC+G+P sembra essere una combinazione di HNSW e IVF-PQ. Determina i cluster utilizzando HNSW ed esegue la ricerca aggiungendo alcune strategie di potatura al cluster di destinazione.

Il risultato è riportato nella Figura 2a. Le dimensioni del codebook sono 16 e 32 nella figura. Il set di dati è SIFT1B, quantificato da OPQ.

Dettagli sull'implementazione del codice

Il codice sorgente di DiskANN è open-sourced su https://github.com/microsoft/DiskANN.

Nel gennaio 2021, il codice sorgente della soluzione DiskANN è stato reso pubblico.

Di seguito vengono presentati principalmente il processo di indicizzazione e il processo di ricerca.

Costruzione dell'indice

Ci sono 8 parametri per la costruzione dell'indice:

data_type: le opzioni includono float/int8/uint8.

file_dati.bin: Il file binario dei dati originali. I primi due numeri interi del file rappresentano rispettivamente il numero totale n del vettore del dataset e la dimensione del vettore dim. Gli ultimi n dim sizeof(data_type) byte sono dati vettoriali continui.

prefisso_indice_percorso: Il prefisso del percorso del file di output. Dopo la costruzione dell'indice, verranno generati diversi file relativi all'indice. Questo parametro è il prefisso comune della directory in cui sono memorizzati.

R: Il massimo grado di uscita dell'indice globale.

L: Il parametro L dell'indice Vamana, il limite superiore della dimensione dell'insieme di candidati.

B: La soglia di memoria durante l'interrogazione. Controlla la dimensione del codebook PQ, in GB.

M: La soglia di memoria quando si costruisce un indice. Determina la dimensione del frammento, in GB.

T: Il numero di thread.

Processo di indicizzazione (funzione di ingresso: aux_utils.cpp::build_disk_index):

  1. Genera vari nomi di file di output in base a index_prefix_path.
  2. Controllo dei parametri.
  3. Leggere il meta di data_file.bin per ottenere n e dim. Determinare il numero di sottospazio m del codebook di PQ in base a B e n.
  4. generare_pq_pivots: Campiona il punto centrale dell'insieme di addestramento PQ utilizzando la frequenza di campionamento p = 1500000/n in modo uniforme per addestrare PQ globalmente.
  5. generare_dati_pq_da_pivot: Genera un codebook PQ globale e salva separatamente il punto centrale e il codebook.
  6. build_merged_vamana_index: taglia il set di dati originale, costruisce indici Vamana in segmenti e infine unisce gli indici in uno solo.
  • partizione_con_budget_ram: Determinare il numero di frammenti k in base al parametro M. Campionare l'insieme di dati utilizzando kmeans, distribuendo ogni punto ai due cluster più vicini. Frammentare l'insieme di dati e ogni frammento produce due file: un file di dati e un file ID. Il file ID e il file di dati si corrispondono e ogni ID nel file ID corrisponde a un vettore nel file di dati. Gli ID si ottengono numerando ciascun vettore dei dati originali da 0 a n-1. L'ID è relativamente importante ed è legato al merge.
    • Campionare uniformemente l'insieme di allenamento con una frequenza di campionamento di 1500000/n;
    • Inizializza num_parts = 3. Itera da 3:
      • Eseguire num_parts-means++ sull'insieme di allenamento al passo i;
      • Utilizzare una frequenza di campionamento di 0,01 per campionare un insieme di test in modo uniforme a livello globale e dividere l'insieme di test nei 2 cluster più vicini;
      • Contare il numero di punti in ogni cluster e dividerlo per la frequenza di campionamento per stimare il numero di punti in ogni cluster;
      • Stimare la memoria richiesta dal cluster più grande nel passo 3 in base alla dimensione dell'indice Vamana; se non supera il parametro M, passare al passo iii, altrimenti num_parts ++ tornare al passo 2;
    • Dividere il set di dati originali in file di gruppo num_parts, ogni gruppo di file include file di dati frammentati e file ID corrispondenti ai dati frammentati.
  • Creare indici Vamana separatamente per tutte le fette del passo a e salvarli su disco;
  • merge_shards: unire num_parts shard Vamana in un indice globale:
    • Leggere il file ID dei frammenti di num_parts in idmap. Questa idmap è equivalente a stabilire una mappatura in avanti di frammento->id;
    • Stabilire una mappatura inversa di id->frammenti in base a idmap e sapere in quali due frammenti si trova ogni vettore;
    • Utilizzare un lettore con 1 GB di cache per aprire gli indici Vamana di num_parts slice e utilizzare uno scrittore con 1 GB di cache per aprire il file di output, pronto per la fusione;
    • Inserire i punti di navigazione di num_parts dell'indice Vamana nel file dei punti centrali, che verrà utilizzato durante la ricerca;
    • Avviare la fusione in base all'ID, da piccolo a grande, leggere l'insieme dei punti vicini di ciascun vettore originale in ogni frammento a turno secondo la mappatura inversa, deduplicare, mescolare, troncare e scrivere sul file di output. Poiché in origine l'affettatura era ordinata globalmente, anche l'unione è ordinata, l'ID dell'indice finale e l'ID dei dati originali corrispondono uno a uno.
    • Eliminare i file temporanei, compresi i file dei frammenti, gli indici dei frammenti e i file ID dei frammenti.
  1. creare_disk_layout: L'indice globale generato nel passaggio 6 ha solo una tabella di adiacenza compatta. Questo passaggio serve ad allineare l'indice. La tabella di adiacenza e i dati originali vengono memorizzati insieme. Durante la ricerca, caricare la tabella di adiacenza e leggere il vettore originale insieme per un calcolo accurato della distanza. Esiste anche il concetto di SETTORE, con una dimensione predefinita di 4096. Ogni SETTORE contiene solo 4096 / node_size di informazioni vettoriali. node_size = dimensione del singolo vettore + dimensione della tabella di adiacenza del singolo nodo.

  2. Infine, si esegue un campionamento uniforme globale di 150000 / n, lo si salva e lo si usa come riscaldamento durante la ricerca.

Ricerca

Ci sono 10 parametri di ricerca:

  • tipo_indice: Le opzioni includono Float/int8/uint8, simili al primo parametro data_type quando si costruisce un indice.
  • percorso_prefisso_indice: Si fa riferimento al parametro index_prefix_path.
  • num_nodi_da_cache: Numero di hotspot della cache.
  • num_threads: Numero di thread di ricerca.
  • beamwidth: limite superiore del numero di punti di precaricamento. Il sistema determina se è impostato su 0.
  • query_file.bin: File del set di query.
  • truthset.bin: File del set di risultati, "null" significa che il set di risultati non è stato fornito, il programma lo calcola da solo;
  • K: topk;
  • result_output_prefix: Percorso di salvataggio dei risultati della ricerca;
  • L*: Elenco dei parametri di ricerca. È possibile aggiungere più valori. Per ogni L, verranno fornite informazioni statistiche durante la ricerca con L diverse.

Processo di ricerca:

  1. Caricare i dati relativi: caricare il set di query, i dati del punto centrale PQ, i dati del codebook, il punto di partenza della ricerca e altri dati e leggere il meta indice.
  2. Usare l'insieme dei dati campionati durante l'indicizzazione per eseguire la ricerca con il raggio in cache, contare i tempi di accesso di ogni punto e caricare nella cache i punti num_nodes_to_cache con la frequenza di accesso più alta.
  3. Per impostazione predefinita, è prevista un'operazione di WARMUP. Come per il passo 2, anche questo set di dati di esempio viene utilizzato per effettuare una cached_beam_search.
  4. In base al numero di parametri L indicati, ogni L verrà eseguito con cached_beam_search ancora una volta con l'insieme di query e verranno emesse statistiche come il tasso di richiamo e il QPS. Il processo di riscaldamento e di statistica dei dati hotspot non viene conteggiato nel tempo di interrogazione.

Informazioni su cached_beam_search:

  1. Trova il candidato più vicino al punto di interrogazione dal punto di partenza del candidato. Viene utilizzata la distanza PQ e il punto di partenza viene aggiunto alla coda di ricerca.
  2. Avvio della ricerca:
  • Dalla coda di ricerca, non ci sono più di beam_width + 2 punti non visitati. Se questi punti sono presenti nella cache, aggiungerli alla coda di ricerca della cache. Se non sono stati visitati, aggiungerli alla coda dei punti mancati. Assicurarsi che la dimensione della coda di miss non superi beam_width.
  • Inviare richieste asincrone di accesso al disco ai punti della coda di miss.
  • Per i punti trovati dalla cache, utilizzare i dati originali e i dati della query per calcolare la distanza esatta, aggiungerli alla coda dei risultati e quindi utilizzare PQ per calcolare la distanza dai punti vicini che non sono stati visitati prima di aggiungerli alla coda di ricerca. La lunghezza della coda di ricerca è limitata dai parametri.
  • Elaborare i punti mancanti memorizzati nella cache nel passo a, in modo simile al passo c.
  • Quando la coda di ricerca è vuota, la ricerca termina e viene restituita la coda dei risultati topk.

Riassumere

Sebbene si tratti di un lavoro relativamente lungo, nel complesso è eccellente. Le idee del documento e del codice sono chiare: dividere un certo numero di bucket sovrapposti tramite k-means, quindi dividere i bucket per costruire un indice a mappa e infine unire gli indici, un'idea relativamente nuova. Per quanto riguarda l'indice a grafo basato sulla memoria Vamana, si tratta essenzialmente di una versione inizializzata in modo casuale di NSG che può controllare la granularità del taglio. Durante l'interrogazione, sfrutta appieno la cache + la pipeline, copre parte del tempo di io e migliora il QPS. Tuttavia, secondo il documento, anche se le condizioni della macchina non sono straordinarie, il tempo di addestramento richiede fino a 5 giorni e l'usabilità è relativamente bassa. In futuro sarà sicuramente necessario ottimizzare l'addestramento. Dal punto di vista del codice, la qualità è relativamente alta e può essere utilizzata direttamente nell'ambiente di produzione.

Riferimenti

  1. Suhas Jayaram Subramanya, Fnu Devvrit, Harsha Vardhan Simhadri, Ravishankar Krishnawamy, Rohan Kadekodi. DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node. NeurIPS 2019.
  2. [Cong Fu, Chao Xiang, Changxu Wang e Deng Cai. Ricerca approssimata e veloce dei vicini di casa con i grafi di diffusione naviganti. PVLDB, 12(5):461 - 474, 2019. doi: 10.14778/3303753.3303754.] (http://www.vldb.org/pvldb/vol12/p461-fu.pdf)
  3. Cong Fu e Deng Cai. GitHub - ZJULearning/efanna: libreria veloce per la ricerca di RNA e la costruzione di grafi KNN.
  4. Motore di ricerca per 高维数据检索工业级解决方案

5. Dmitry Baranchuk, Artem Babenko e Yury Malkov. Rivisitazione degli indici invertiti per i vicini approssimati su scala miliardaria.

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

Continua a Leggere