Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Rust API docs #49

Merged
merged 2 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions ci/build_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ files:
- cupy
- docs
- py_version
- rust
- build
rust:
output: none
includes:
Expand Down
13 changes: 10 additions & 3 deletions docs/source/rust_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
Rust API Documentation
~~~~~~~~~~~~~~~~~~~~~~

.. _api:
.. raw:: html

.. toctree::
:maxdepth: 4
<iframe src="./_static/rust/cuvs/index.html" height="720px" width="100%"></iframe>

<!-- hide the 'view source' section here, since it doesn't work with the iframe
and we want the iframe to use the space -->
<style type="text/css">
.bd-sidebar-secondary {
display: none;
}
</style>
18 changes: 17 additions & 1 deletion rust/cuvs/src/cagra/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Into<ManagedTensor>>(
res: &Resources,
params: &IndexParams,
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions rust/cuvs/src/cagra/index_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<IndexParams> {
unsafe {
let mut params = core::mem::MaybeUninit::<ffi::cuvsCagraIndexParams_t>::uninit();
Expand Down
63 changes: 63 additions & 0 deletions rust/cuvs/src/cagra/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<f32, _>::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::<u32, _>::zeros((n_queries, k));
//! let neighbors = ManagedTensor::from(&neighbors_host).to_device(&res)?;
//!
//! let mut distances_host = ndarray::Array::<f32, _>::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;
Expand Down
1 change: 1 addition & 0 deletions rust/cuvs/src/cagra/search_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SearchParams> {
unsafe {
let mut params = core::mem::MaybeUninit::<ffi::cuvsCagraSearchParams_t>::uninit();
Expand Down
6 changes: 6 additions & 0 deletions rust/cuvs/src/dlpack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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<ManagedTensor> {
unsafe {
let bytes = self.bytes();
Expand All @@ -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<Elem = T> + ndarray::RawDataMut,
Expand Down
5 changes: 5 additions & 0 deletions rust/cuvs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions rust/cuvs/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Resources> {
let mut res: ffi::cuvsResources_t = 0;
unsafe {
Expand Down
Loading