diff --git a/build.sh b/build.sh
index 8571a574c..37aadad88 100755
--- a/build.sh
+++ b/build.sh
@@ -54,6 +54,7 @@ LIBCUVS_BUILD_DIR=${LIBCUVS_BUILD_DIR:=${REPODIR}/cpp/build}
SPHINX_BUILD_DIR=${REPODIR}/docs
DOXYGEN_BUILD_DIR=${REPODIR}/cpp/doxygen
PYTHON_BUILD_DIR=${REPODIR}/python/cuvs/_skbuild
+RUST_BUILD_DIR=${REPODIR}/rust
BUILD_DIRS="${LIBCUVS_BUILD_DIR} ${PYTHON_BUILD_DIR}"
# Set defaults for vars modified by flags to this script
@@ -395,6 +396,9 @@ if hasArg docs; then
set -x
cd ${DOXYGEN_BUILD_DIR}
doxygen Doxyfile
+ cd ${RUST_BUILD_DIR}
+ cargo doc -p cuvs --no-deps
+ rsync -av ${RUST_BUILD_DIR}/target/doc/ ${SPHINX_BUILD_DIR}/source/_static/rust
cd ${SPHINX_BUILD_DIR}
sphinx-build -b html source _html
fi
diff --git a/ci/build_docs.sh b/ci/build_docs.sh
index 983e97385..fbb004da4 100755
--- a/ci/build_docs.sh
+++ b/ci/build_docs.sh
@@ -12,7 +12,12 @@ rapids-dependency-file-generator \
--matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION}" | tee env.yaml
rapids-mamba-retry env create --force -f env.yaml -n docs
+
+# seeing failures on activating the environment here on unbound locals
+# apply workaround from https://github.com/conda/conda/issues/8186#issuecomment-532874667
+set +eu
conda activate docs
+set -eu
rapids-print-env
diff --git a/dependencies.yaml b/dependencies.yaml
index 7fff7811a..cd6cb0cf0 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -44,6 +44,8 @@ files:
- cupy
- docs
- py_version
+ - rust
+ - build
rust:
output: none
includes:
diff --git a/docs/source/rust_api.rst b/docs/source/rust_api.rst
index 254136e3a..8297dbef9 100644
--- a/docs/source/rust_api.rst
+++ b/docs/source/rust_api.rst
@@ -2,7 +2,14 @@
Rust API Documentation
~~~~~~~~~~~~~~~~~~~~~~
-.. _api:
+.. raw:: html
-.. toctree::
- :maxdepth: 4
+
+
+
+
diff --git a/rust/cuvs/src/cagra/index.rs b/rust/cuvs/src/cagra/index.rs
index 3c45efafd..3394889aa 100644
--- a/rust/cuvs/src/cagra/index.rs
+++ b/rust/cuvs/src/cagra/index.rs
@@ -21,11 +21,18 @@ use crate::dlpack::ManagedTensor;
use crate::error::{check_cuvs, Result};
use crate::resources::Resources;
+/// CAGRA ANN Index
#[derive(Debug)]
pub struct Index(ffi::cuvsCagraIndex_t);
impl Index {
- /// Builds a new index
+ /// Builds a new Index from the dataset for efficient search.
+ ///
+ /// # Arguments
+ ///
+ /// * `res` - Resources to use
+ /// * `params` - Parameters for building the index
+ /// * `dataset` - A row-major matrix on either the host or device to index
pub fn build>(
res: &Resources,
params: &IndexParams,
@@ -53,6 +60,15 @@ impl Index {
}
}
+ /// Perform a Approximate Nearest Neighbors search on the Index
+ ///
+ /// # Arguments
+ ///
+ /// * `res` - Resources to use
+ /// * `params` - Parameters to use in searching the index
+ /// * `queries` - A matrix in device memory to query for
+ /// * `neighbors` - Matrix in device memory that receives the indices of the nearest neighbors
+ /// * `distances` - Matrix in device memory that receives the distances of the nearest neighbors
pub fn search(
self,
res: &Resources,
diff --git a/rust/cuvs/src/cagra/index_params.rs b/rust/cuvs/src/cagra/index_params.rs
index 7ff68d3f3..ecc660531 100644
--- a/rust/cuvs/src/cagra/index_params.rs
+++ b/rust/cuvs/src/cagra/index_params.rs
@@ -24,6 +24,7 @@ pub type BuildAlgo = ffi::cuvsCagraGraphBuildAlgo;
pub struct IndexParams(pub ffi::cuvsCagraIndexParams_t);
impl IndexParams {
+ /// Returns a new IndexParams
pub fn new() -> Result {
unsafe {
let mut params = core::mem::MaybeUninit::::uninit();
diff --git a/rust/cuvs/src/cagra/mod.rs b/rust/cuvs/src/cagra/mod.rs
index 55705c27a..417ed9b0d 100644
--- a/rust/cuvs/src/cagra/mod.rs
+++ b/rust/cuvs/src/cagra/mod.rs
@@ -14,6 +14,69 @@
* limitations under the License.
*/
+//! CAGRA is a graph-based nearest neighbors implementation with state-of-the art
+//! query performance for both small- and large-batch sized search.
+//!
+//! Example:
+//! ```
+//!
+//! use cuvs::cagra::{Index, IndexParams, SearchParams};
+//! use cuvs::{ManagedTensor, Resources, Result};
+//!
+//! use ndarray::s;
+//! use ndarray_rand::rand_distr::Uniform;
+//! use ndarray_rand::RandomExt;
+//!
+//! fn cagra_example() -> Result<()> {
+//! let res = Resources::new()?;
+//!
+//! // Create a new random dataset to index
+//! let n_datapoints = 65536;
+//! let n_features = 512;
+//! let dataset =
+//! ndarray::Array::::random((n_datapoints, n_features), Uniform::new(0., 1.0));
+//!
+//! // build the cagra index
+//! let build_params = IndexParams::new()?;
+//! let index = Index::build(&res, &build_params, &dataset)?;
+//! println!(
+//! "Indexed {}x{} datapoints into cagra index",
+//! n_datapoints, n_features
+//! );
+//!
+//! // use the first 4 points from the dataset as queries : will test that we get them back
+//! // as their own nearest neighbor
+//! let n_queries = 4;
+//! let queries = dataset.slice(s![0..n_queries, ..]);
+//!
+//! let k = 10;
+//!
+//! // CAGRA search API requires queries and outputs to be on device memory
+//! // copy query data over, and allocate new device memory for the distances/ neighbors
+//! // outputs
+//! let queries = ManagedTensor::from(&queries).to_device(&res)?;
+//! let mut neighbors_host = ndarray::Array::::zeros((n_queries, k));
+//! let neighbors = ManagedTensor::from(&neighbors_host).to_device(&res)?;
+//!
+//! let mut distances_host = ndarray::Array::::zeros((n_queries, k));
+//! let distances = ManagedTensor::from(&distances_host).to_device(&res)?;
+//!
+//! let search_params = SearchParams::new()?;
+//!
+//! index.search(&res, &search_params, &queries, &neighbors, &distances)?;
+//!
+//! // Copy back to host memory
+//! distances.to_host(&res, &mut distances_host)?;
+//! neighbors.to_host(&res, &mut neighbors_host)?;
+//!
+//! // nearest neighbors should be themselves, since queries are from the
+//! // dataset
+//! println!("Neighbors {:?}", neighbors_host);
+//! println!("Distances {:?}", distances_host);
+//! Ok(())
+//! }
+//! ```
+
mod index;
mod index_params;
mod search_params;
diff --git a/rust/cuvs/src/cagra/search_params.rs b/rust/cuvs/src/cagra/search_params.rs
index 11ac92bdd..14956966e 100644
--- a/rust/cuvs/src/cagra/search_params.rs
+++ b/rust/cuvs/src/cagra/search_params.rs
@@ -25,6 +25,7 @@ pub type HashMode = ffi::cuvsCagraHashMode;
pub struct SearchParams(pub ffi::cuvsCagraSearchParams_t);
impl SearchParams {
+ /// Returns a new SearchParams object
pub fn new() -> Result {
unsafe {
let mut params = core::mem::MaybeUninit::::uninit();
diff --git a/rust/cuvs/src/dlpack.rs b/rust/cuvs/src/dlpack.rs
index b86959db1..a1d4e41c6 100644
--- a/rust/cuvs/src/dlpack.rs
+++ b/rust/cuvs/src/dlpack.rs
@@ -19,6 +19,8 @@ use std::convert::From;
use crate::error::{check_cuda, Result};
use crate::resources::Resources;
+/// ManagedTensor is a wrapper around a dlpack DLManagedTensor object.
+/// This lets you pass matrices in device or host memory into cuvs.
#[derive(Debug)]
pub struct ManagedTensor(ffi::DLManagedTensor);
@@ -41,6 +43,8 @@ impl ManagedTensor {
bytes
}
+ /// Creates a new ManagedTensor on the current GPU device, and copies
+ /// the data into it.
pub fn to_device(&self, _res: &Resources) -> Result {
unsafe {
let bytes = self.bytes();
@@ -64,6 +68,8 @@ impl ManagedTensor {
Ok(ManagedTensor(ret))
}
}
+
+ /// Copies data from device memory into host memory
pub fn to_host<
T: IntoDtype,
S: ndarray::RawData + ndarray::RawDataMut,
diff --git a/rust/cuvs/src/lib.rs b/rust/cuvs/src/lib.rs
index 7a6f847f5..273f04723 100644
--- a/rust/cuvs/src/lib.rs
+++ b/rust/cuvs/src/lib.rs
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+//! cuVS: Rust bindings for Vector Search on the GPU
+//!
+//! This crate provides Rust bindings for cuVS, allowing you to run
+//! approximate nearest neighbors search on the GPU.
+
pub mod cagra;
mod dlpack;
mod error;
diff --git a/rust/cuvs/src/resources.rs b/rust/cuvs/src/resources.rs
index ad7113e6b..a5c503dc5 100644
--- a/rust/cuvs/src/resources.rs
+++ b/rust/cuvs/src/resources.rs
@@ -17,10 +17,14 @@
use crate::error::{check_cuvs, Result};
use std::io::{stderr, Write};
+/// Resources are objects that are shared between function calls,
+/// and includes things like CUDA streams, cuBLAS handles and other
+/// resources that are expensive to create.
#[derive(Debug)]
pub struct Resources(pub ffi::cuvsResources_t);
impl Resources {
+ /// Returns a new Resources object
pub fn new() -> Result {
let mut res: ffi::cuvsResources_t = 0;
unsafe {