> For the complete documentation index, see [llms.txt](https://sliu583.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sliu583.gitbook.io/blog/specific-work/shivarams-group/embeddings/diskann-fast-accurate-billion-point-nearest-neighbor-search-on-a-single-node.md).

# DiskANN: Fast accurate billion-point nearest neighbor search on a single node

### Intro & Problem Statement&#x20;

* KNN:&#x20;
  * dataset P, target k, query q. Extract KNN of q from P quickly.&#x20;
  * Application domains: embeddings&#x20;
  * Curse of dimensionality, almost impossible to find exact search result (motivation for ANN)&#x20;
* ANN:&#x20;
  * Goal: maximize recall while retrieving the results as quickly as possible&#x20;
  * Trade-off: **recall v.s latency (and/or indexing time)**&#x20;
  * Algorithms&#x20;
    * k-d trees&#x20;
    * Locality Sensitive Hashing (LSH)
    * Graph-based: HNSW, NSG

#### Indexing large datasets: two approaches&#x20;

1. Based on **Inverted Index + Data Compression** and includes methods such as FAISS and IVFOADC+G+P
   1. Clustered + Compressed (e.x. PQ)&#x20;
   2. *Benefit* : small memory footprint, and low latency of retrieving result using accelerator&#x20;
   3. *Problem* : Recall is low because compression is lossy&#x20;
2. Divide the dataset into disjoint **shards**, and build in-memory index for each shard&#x20;
   1. *Problem* : increased search latency and reduced throughput since the query needs to be routed to several shards&#x20;

### Motivation&#x20;

* SOTA **approximate nearest neighbor search (ANNS)** algorithms generate indices that must be stored in **main memory** for fast high-recall search.&#x20;
  * Expensive, Limit the size of the dataset&#x20;
  * E.x. FAISS: supports searching only from RAM
* Search **throughput** of an SSD-resident index is limited by the number of random disk accesses/query and **latency** is limited by the round-trips (each round-trip can consist of multiple reads) to the disk.&#x20;
  * SSD: **a few hundred microseconds** to serve a random read and can service about \~300K random reads per second&#x20;
    * But: search applications require mean latencies of **a few milliseconds** for KNN search.&#x20;
  * **Main challenges for SSD-resident index** are
    * reducing the number of random SSD accesses to a few dozen&#x20;
    * reducing the number of round trip requests to disk to under ten, preferably five&#x20;
  * Naively mapping indices to SSDs does not work! (Generate several hundreds of disk reads per query)

### Contribution&#x20;

* DiskANN: SSD-resident ANNS system based on new graph-based indexing algorithm called Vamana&#x20;
  * **DiskANN**: index and serve 1B dataset (d = 100s) using 64GB RAM, with low latency and high precision&#x20;
  * **Vamana**:&#x20;
    * generate graph indices with smaller diameter to minimize the number of sequential disk reads
    * Used in memory, outperform SOTA algorithms like HNSW and NSG&#x20;
    * Partitions and merge &#x20;
    * Compression: cache in RAM
    * Note: what's the contribution of last two...?&#x20;

### Vamana Graph Construction Algorithm

![Greedy Search ](/files/-MW_rLQLyXzbMlmYgsxj)

![RobustPrune used in Vamana Indexing Algorithm  ](/files/-MW_rCoOTA0LqDQEE7ya)

![Vamana Indexing algorithm](/files/-MW_rWukJSfkccyiHFpG)

#### Comparison to HNSW and NSG

* HNSW & NSG have no tunable parameter α (default value is 1). This is the main factor that Vamana achieves a better trade-off between graph degree and diameter.&#x20;
* Some features that help Vamana and NSG add long-range edges, while HNSW has an additional step of constructing a hierarchy of graphs over a nested sequence of samples of the dataset&#x20;
* Pertains to the initial graph: HNSW and Vamana have simpler initializations over NSG
* Vamana makes two passes over the dataset to improve graph quality &#x20;

### DiskANN System Design&#x20;

#### Key questions to address

1. How do we build a graph over a billion points?
2. How do we do distance comparisons between the query point and points in our candidate list at search time, if we cannot even store the vector data?&#x20;

#### Index construction algorithms&#x20;

* Address question 1&#x20;
* Key: send each base point to multiple nearby centers to obtain overlapping clusters
  * partition dataset into K clusters using K-means
  * Assign each base point to the l-closest centers (typically l = 2)&#x20;
  * Build Vamana indices for the points assigned to each of the clusters
  * Merge all different graphs into a single graph by taking union of edges&#x20;
* Why good: overlapping nature of clusters provide connectivity for the algorithm to succeed even if the query's NN are split across multiple shards&#x20;
* **Note**: Use full-precision coordinates to build the graph index. Graph with full-precision vectors on SSD

#### Search algorithms&#x20;

* &#x20;Use PQ data at search time. Store compressed vectors of all the data points in memory.&#x20;
  * **Beam Search**&#x20;
    * Natural way to search is to use Algorithm 1, fetching the neighborhood information from the SSD as needed. Use compressed vectors to guide the best vertices (and neighbors) to read from disk
    * To reduce the number of round trips to SSD (to fetch neighborhoods sequentially) without increasing compute (distance calculations) excessively, fetch the neighborhoods of a small number, W (say 4,8) of the closest points in L\V in one shot, and update L to be the top L candidates in L along with all the neighbors retrieved in this step.&#x20;
    * Beam width: to strike a balance between latency and throughput&#x20;

#### **Other**

* Cache frequently visited vertices&#x20;
  * Either known query distribution or all vertices that are 3/4 hops from the starting point&#x20;
* Fetching and re-ranking full-precision coordinates stored on the SSD&#x20;
  * Full precision coordinates essentially piggyback on the cost of expanding the neighborhoods&#x20;

### Metric for success

* High recall&#x20;
* Low query latency&#x20;

### Result

#### With HNSW, NSG for In-memory search performance&#x20;

* Dataset: SIFT1M, GIST1M, DEEP1M&#x20;
* Vamana matches or outperforms the current best ANNS methods on both hundred and thousand-dimensional datasets obtained from different sources&#x20;

#### With HNSW, NSG for number of hops&#x20;

* More suitable for SSD-based serving than other graph-based algorithms as it makes 2-3 times fewer hops for search to converge on large datasets compared to HNSW and NSG&#x20;
  * Hops = number of rounds of disk reads on the critical path of the search&#x20;

#### Billion-scale datasets: one-shot Vamana v.s Merged Vamana&#x20;

* Dataset: ANN\_SIFT1B&#x20;
* Take away
  * Partition and merging are fast and can be done directly on disk, so the entire build process consumes under 64 GB main memory&#x20;
  * Single index outperforms merged index, which traverses more links to reach the same neighborhoods, thus increasing search latency&#x20;
  * Merged index is still a good choice for Billion-scale k-ANN indexing&#x20;
    * Require no more than 20% extra latency and target recall when compared to single index&#x20;

#### Billion-scale datasets: DiskANN v.s IVF-based Methods&#x20;

* IVFOADC+G+P
  * Uses inverted indexing and PQ to develop indicies with low-memory footprint and serve queries with high-throughput and good 1-recall\@100
  * Not compared with FAISS: because need GPUs might not be available and <https://arxiv.org/abs/1802.02422> demonstrate superior recall over FAISS (??)
* DiskANN: matches memory footprint, achieve significantly higher recall at same latency&#x20;

Thoughts&#x20;

* Single machine setting. Are these meaningful experimental comparisons in our case? It's a single node and it hasn't been compared with FAISS&#x20;
* Apply this ...
