CAGRA#
CAGRA is a graph-based nearest neighbors implementation with state-of-the art query performance for both small- and large-batch sized search.
Please note that the CAGRA implementation is currently experimental and the API is subject to change from release to release. We are currently working on promoting CAGRA to a top-level stable API within RAFT.
#include <raft/neighbors/cagra.cuh>
namespace raft::neighbors::cagra
-
template<typename DataT, typename IdxT, typename accessor>
void build_knn_graph(raft::resources const &res, mdspan<const DataT, matrix_extent<int64_t>, row_major, accessor> dataset, raft::host_matrix_view<IdxT, int64_t, row_major> knn_graph, std::optional<float> refine_rate = std::nullopt, std::optional<ivf_pq::index_params> build_params = std::nullopt, std::optional<ivf_pq::search_params> search_params = std::nullopt)# Build a kNN graph.
The kNN graph is the first building block for CAGRA index. This function uses the IVF-PQ method to build a kNN graph.
The output is a dense matrix that stores the neighbor indices for each pont in the dataset. Each point has the same number of neighbors.
See cagra::build for an alternative method.
The following distance metrics are supported:
L2Expanded
Usage example:
using namespace raft::neighbors; // use default index parameters cagra::index_params build_params; cagra::search_params search_params auto knn_graph = raft::make_host_matrix<IdxT, IdxT>(dataset.extent(0), 128); // create knn graph cagra::build_knn_graph(res, dataset, knn_graph.view(), 2, build_params, search_params); auto optimized_gaph = raft::make_host_matrix<IdxT, IdxT>(dataset.extent(0), 64); cagra::optimize(res, dataset, knn_graph.view(), optimized_graph.view()); // Construct an index from dataset and optimized knn_graph auto index = cagra::index<T, IdxT>(res, build_params.metric(), dataset, optimized_graph.view());
- Template Parameters:
DataT – data element type
IdxT – type of the dataset vector indices
- Parameters:
res – [in] raft resources
dataset – [in] a matrix view (host or device) to a row-major matrix [n_rows, dim]
knn_graph – [out] a host matrix view to store the output knn graph [n_rows, graph_degree]
refine_rate – [in] refinement rate for ivf-pq search
build_params – [in] (optional) ivf_pq index building parameters for knn graph
search_params – (optional) ivf_pq search parameters
-
template<typename DataT, typename IdxT = uint32_t, typename d_accessor = host_device_accessor<std::experimental::default_accessor<DataT>, memory_type::device>, typename g_accessor = host_device_accessor<std::experimental::default_accessor<IdxT>, memory_type::host>>
void sort_knn_graph(raft::resources const &res, mdspan<const DataT, matrix_extent<int64_t>, row_major, d_accessor> dataset, mdspan<IdxT, matrix_extent<int64_t>, row_major, g_accessor> knn_graph)# Sort a KNN graph index. Preprocessing step for
cagra::optimize
: If a KNN graph is not built usingcagra::build_knn_graph
, then it is necessary to call this function before callingcagra::optimize
. If the graph is built bycagra::build_knn_graph
, it is already sorted and you do not need to call this function.Usage example:
using namespace raft::neighbors; cagra::index_params build_params; auto knn_graph = raft::make_host_matrix<IdxT, IdxT>(dataset.extent(0), 128); // build KNN graph not using `cagra::build_knn_graph` // build(knn_graph, dataset, ...); // sort graph index sort_knn_graph(res, dataset.view(), knn_graph.view()); // optimize graph cagra::optimize(res, dataset, knn_graph.view(), optimized_graph.view()); // Construct an index from dataset and optimized knn_graph auto index = cagra::index<T, IdxT>(res, build_params.metric(), dataset, optimized_graph.view());
- Template Parameters:
DataT – type of the data in the source dataset
IdxT – type of the dataset vector indices
- Parameters:
res – [in] raft resources
dataset – [in] a matrix view (host or device) to a row-major matrix [n_rows, dim]
knn_graph – [inout] a matrix view (host or device) of the input knn graph [n_rows, knn_graph_degree]
-
template<typename IdxT = uint32_t, typename g_accessor = host_device_accessor<std::experimental::default_accessor<IdxT>, memory_type::host>>
void optimize(raft::resources const &res, mdspan<IdxT, matrix_extent<int64_t>, row_major, g_accessor> knn_graph, raft::host_matrix_view<IdxT, int64_t, row_major> new_graph)# Prune a KNN graph.
Decrease the number of neighbors for each node.
See cagra::build_knn_graph for usage example
- Template Parameters:
IdxT – type of the indices in the source dataset
- Parameters:
res – [in] raft resources
knn_graph – [in] a matrix view (host or device) of the input knn graph [n_rows, knn_graph_degree]
new_graph – [out] a host matrix view of the optimized knn graph [n_rows, graph_degree]
-
template<typename T, typename IdxT = uint32_t, typename Accessor = host_device_accessor<std::experimental::default_accessor<T>, memory_type::host>>
index<T, IdxT> build(raft::resources const &res, const index_params ¶ms, mdspan<const T, matrix_extent<int64_t>, row_major, Accessor> dataset)# Build the index from the dataset for efficient search.
The build consist of two steps: build an intermediate knn-graph, and optimize it to create the final graph. The index_params struct controls the node degree of these graphs.
It is required that dataset and the optimized graph fit the GPU memory.
To customize the parameters for knn-graph building and pruning, and to reuse the intermediate results, you could build the index in two steps using cagra::build_knn_graph and cagra::optimize.
The following distance metrics are supported:
L2
Usage example:
using namespace raft::neighbors; // use default index parameters cagra::index_params index_params; // create and fill the index from a [N, D] dataset auto index = cagra::build(res, index_params, dataset); // use default search parameters cagra::search_params search_params; // search K nearest neighbours auto neighbors = raft::make_device_matrix<uint32_t>(res, n_queries, k); auto distances = raft::make_device_matrix<float>(res, n_queries, k); cagra::search(res, search_params, index, queries, neighbors, distances);
- Template Parameters:
T – data element type
IdxT – type of the indices in the source dataset
- Parameters:
res – [in]
params – [in] parameters for building the index
dataset – [in] a matrix view (host or device) to a row-major matrix [n_rows, dim]
- Returns:
the constructed cagra index
-
template<typename T, typename IdxT>
void search(raft::resources const &res, const search_params ¶ms, const index<T, IdxT> &idx, raft::device_matrix_view<const T, int64_t, row_major> queries, raft::device_matrix_view<IdxT, int64_t, row_major> neighbors, raft::device_matrix_view<float, int64_t, row_major> distances)# Search ANN using the constructed index.
See the cagra::build documentation for a usage example.
- Template Parameters:
T – data element type
IdxT – type of the indices
- Parameters:
res – [in] raft resources
params – [in] configure the search
idx – [in] cagra index
queries – [in] a device matrix view to a row-major matrix [n_queries, index->dim()]
neighbors – [out] a device matrix view to the indices of the neighbors in the source dataset [n_queries, k]
distances – [out] a device matrix view to the distances to the selected neighbors [n_queries, k]
-
struct index_params : public raft::neighbors::ann::index_params#
- #include <cagra_types.hpp>