From 9c0e38005b9942cba3e3a52e8bf25594fb92bb88 Mon Sep 17 00:00:00 2001 From: "Corey J. Nolet" Date: Wed, 13 Mar 2024 14:32:34 +0100 Subject: [PATCH] `quick start` and `integrations` guides for the docs (#47) Authors: - Corey J. Nolet (https://github.com/cjnolet) Approvers: - Ben Frederickson (https://github.com/benfred) - Jake Awe (https://github.com/AyodeAwe) URL: https://github.com/rapidsai/cuvs/pull/47 --- .gitignore | 1 + README.md | 8 +- docs/source/api_docs.rst | 4 +- docs/source/basics.rst | 90 +++++++++ docs/source/build.md | 178 ----------------- docs/source/build.rst | 233 +++++++++++++++++++++++ docs/source/getting_started.rst | 12 ++ docs/source/index.rst | 5 +- docs/source/integrations.rst | 40 ++++ docs/source/interoperability.rst | 72 +++++++ docs/source/quick_start.md | 183 ------------------ docs/source/working_with_ann_indexes.rst | 102 ++++++++++ 12 files changed, 559 insertions(+), 369 deletions(-) create mode 100644 docs/source/basics.rst delete mode 100644 docs/source/build.md create mode 100644 docs/source/build.rst create mode 100644 docs/source/getting_started.rst create mode 100644 docs/source/integrations.rst create mode 100644 docs/source/interoperability.rst delete mode 100644 docs/source/quick_start.md create mode 100644 docs/source/working_with_ann_indexes.rst diff --git a/.gitignore b/.gitignore index 8cac2b5ae..9fcde3fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,7 @@ _xml # sphinx _html _text +docs/source/_static/rust # clang tooling compile_commands.json diff --git a/README.md b/README.md index 14bb02812..4a2d2de16 100755 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ ## Useful Resources -- [cuVS Reference Documentation](https://docs.rapids.ai/api/cuvs/stable/): API Documentation. -- [cuVS Getting Started](./docs/source/quick_start.md): Getting started with RAFT. -- [Build and Install cuVS](./docs/source/build.md): Instructions for installing and building cuVS. -- [Example Notebooks](./notebooks): Example jupyer notebooks +- [Code Examples](https://github.com/rapidsai/cuvs/tree/HEAD/examples): Self-contained Code Examples. +- [API Reference Documentation](https://docs.rapids.ai/api/cuvs/nightly/api_docs): API Documentation. +- [Getting Started Guide](https://docs.rapids.ai/api/cuvs/nightly/getting_started): Getting started with RAFT. +- [Build and Install Guide](https://docs.rapids.ai/api/cuvs/nightly/build): Instructions for installing and building cuVS. - [RAPIDS Community](https://rapids.ai/community.html): Get help, contribute, and collaborate. - [GitHub repository](https://github.com/rapidsai/cuvs): Download the cuVS source code. - [Issue tracker](https://github.com/rapidsai/cuvs/issues): Report issues or request features. diff --git a/docs/source/api_docs.rst b/docs/source/api_docs.rst index 2a5a867e0..c911539b9 100644 --- a/docs/source/api_docs.rst +++ b/docs/source/api_docs.rst @@ -1,5 +1,5 @@ -API Documentation -================= +API Reference +============= .. toctree:: :maxdepth: 1 diff --git a/docs/source/basics.rst b/docs/source/basics.rst new file mode 100644 index 000000000..4842e2788 --- /dev/null +++ b/docs/source/basics.rst @@ -0,0 +1,90 @@ +cuVS API Basics +=============== + +- `Memory management`_ +- `Resource management`_ + +Memory management +----------------- + +Centralized memory management allows flexible configuration of allocation strategies, such as sharing the same CUDA memory pool across library boundaries. cuVS uses the [RMM](https://github.com/rapidsai/rmm) library, which eases the burden of configuring different allocation strategies globally across GPU-accelerated libraries. + +RMM currently has APIs for C++ and Python. + +C++ +^^^ + +Here's an example of configuring RMM to use a pool allocator in C++ (derived from the RMM example `here `_): + +.. code-block:: c++ + + rmm::mr::cuda_memory_resource cuda_mr; + // Construct a resource that uses a coalescing best-fit pool allocator + // With the pool initially half of available device memory + auto initial_size = rmm::percent_of_free_device_memory(50); + rmm::mr::pool_memory_resource pool_mr{&cuda_mr, initial_size}; + rmm::mr::set_current_device_resource(&pool_mr); // Updates the current device resource pointer to `pool_mr` + rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource(); // Points to `pool_mr` + +Python +^^^^^^ + +And the corresponding code in Python (derived from the RMM example `here `_): + +.. code-block:: python + + import rmm + pool = rmm.mr.PoolMemoryResource( + rmm.mr.CudaMemoryResource(), + initial_pool_size=2**30, + maximum_pool_size=2**32) + rmm.mr.set_current_device_resource(pool) + + +Resource management +------------------- + +cuVS uses an API from the `RAFT `_ library of ML and data mining primitives to centralize and reuse expensive resources, such as memory management. The below code examples demonstrate how to create these resources for use throughout this guide. + +See RAFT's `resource API documentation `_ for more information. + +C +^ + +.. code-block:: c + + #include + #include + + cuvsResources_t res; + cuvsResourcesCreate(&res); + + // ... do some processing ... + + cuvsResourcesDestroy(res); + +C++ +^^^ + +.. code-block:: c++ + + #include + + raft::device_resources res; + +Python +^^^^^^ + +.. code-block:: python + + import pylibraft + + res = pylibraft.common.DeviceResources() + + +Rust +^^^^ + +.. code-block:: rust + + let res = cuvs::Resources::new()?; \ No newline at end of file diff --git a/docs/source/build.md b/docs/source/build.md deleted file mode 100644 index 976482725..000000000 --- a/docs/source/build.md +++ /dev/null @@ -1,178 +0,0 @@ -**# Installation - -The cuVS software development kit provides APIs for C, C++, Python, and Rust languages. This guide outlines how to install the pre-compiled packages, build it from source, and use it in downstream applications. - -## Table of Contents - -- [Install pre-compiled packages](#installing-precompiled-packages) - - [C, C++, and Python through Conda](#installing-through-conda) - - [Python through Pip](#installing-python-through-pip) - - [Rust through crates.io](#installing-rust-through-crates) -- [Build from source](#building-c-and-python-from-source) - - [Prerequisites](#build-prerequisites) - - [CUDA/GPU requirements](#cudagpu-requirements) - - [Build dependencies](#build-dependencies) - - [Required](#required) - - [Create a build environment](#creating-a-build-environment) - - [ccache and sccache](#ccache-and-sccache) - - [C/C++ Libraries](#c-library) - - [Building the Googletests](#building-the-googletests) - - [Python Library](#python-library) - - [Rust Library](#rust-library) - - [Using Cmake Directly](#using-cmake-directly) -- [Build Documentation](#build-documentation) -- [Use cuVS in your application](#use-cuvs-in-your-application) - ------- - -## Installing Pre-compiled Packages - -### C, C++, and Python through Conda - -The easiest way to install the pre-compiled C, C++, and Python packages is through [conda](https://docs.anaconda.com/free/miniconda/index.html). Use the following commands, depending on your CUDA version, to install cuVS packages (replace `rapidsai` with `rapidsai-nightly` to install more up-to-date but less stable nightly packages). `mamba` is preferred over the `conda` command. - -#### C++ Package -```bash -mamba install -c rapidsai -c conda-forge -c nvidia libcuvs cuda-version=12.0 -``` - -#### C Package -```bash -mamba install -c rapidsai -c conda-forge -c nvidia libcuvs_c cuda-version=12.0 -``` - -#### Python Package -```bash -mamba install -c rapidsai -c conda-forge -c nvidia pycuvs cuda-version=12.0 -``` - -### Python through Pip - -The cuVS Python package can also be [installed through pip](https://rapids.ai/pip.html#install). - -For CUDA 11 packages: -```bash -pip install pycuvs-cu11 --extra-index-url=https://pypi.nvidia.com -``` - -And CUDA 12 packages: -```bash -pip install pycuvs-cu12 --extra-index-url=https://pypi.nvidia.com -``` - -Note: these packages statically link the C and C++ libraries so the `libcuvs` and `libcuvs_c` shared libraries won't be readily available to use in your code. - -### Rust through crates.io - -## Build from source - -The core cuVS source code is written in C++ and wrapped through a C API. The C API is wrapped around the C++ APIs and the other supported languages are built around the C API. - - -### Prerequisites - -- Cmake 3.26.4+ -- GCC 9.3+ (11.4+ recommended) -- CUDA Toolkit 11.4+ -- Volta architecture or better (compute capability >= 7.0) - -### Create a build environment - -[Conda](https://docs.anaconda.com/free/miniconda/index.html) environment scripts are provided for installing the necessary dependencies to build cuVS from source. It is preferred to use `mamba`, as it provides significant speedup over `conda`: -```bash -mamba env create --name cuvs -f conda/environments/all_cuda-120_arch-x86_64.yaml -mamba activate cuvs -``` - -The process for building from source with CUDA 11 differs slightly in that your host system will also need to have CUDA toolkit installed which is greater than, or equal to, the version you install into you conda environment. Installing CUDA toolkit into your host system is necessary because `nvcc` is not provided with Conda's cudatoolkit dependencies for CUDA 11. The following example will install create and install dependencies for a CUDA 11.8 conda environment -```bash -mamba env create --name cuvs -f conda/environments/all_cuda-118_arch-x86_64.yaml -mamba activate cuvs -``` - -The recommended way to build and install cuVS from source is to use the `build.sh` script in the root of the repository. This script can build both the C++ and Python artifacts and provides CMake options for building and installing the headers, tests, benchmarks, and the pre-compiled shared library. - - -### C and C++ libraries - -The C and C++ shared libraries are built together using the following arguments to `build.sh`: -```bash -./build.sh libcuvs -``` - -In above example the `libcuvs.so` and `libcuvs_c.so` shared libraries are installed by default into `$INSTALL_PREFIX/lib`. To disable this, pass `-n` flag. - -Once installed, the shared libraries, headers (and any dependencies downloaded and installed via `rapids-cmake`) can be uninstalled using `build.sh`: -```bash -./build.sh libcuvs --uninstall -``` - - -#### Building the Googletests - -Compile the C and C++ Googletests using the `tests` target in `build.sh`. - -```bash -./build.sh libcuvs tests -``` - -The tests will be written to the build directory, which is `cpp/build/` by default, and they will be named `*_TEST`. - -It can take some time to compile all of the tests. You can build individual tests by providing a semicolon-separated list to the `--limit-tests` option in `build.sh`. Make sure to pass the `-n` flag so the tests are not installed. - -```bash -./build.sh libcuvs tests -n --limit-tests=NEIGHBORS_TEST;CAGRA_C_TEST -``` - -### Python library - -The Python library should be built and installed using the `build.sh` script: - -```bash -./build.sh python -``` - -The Python packages can also be uninstalled using the `build.sh` script: -```bash -./build.sh python --uninstall -``` - -### Rust library - - - -### Using CMake directly - -When building cuVS from source, the `build.sh` script offers a nice wrapper around the `cmake` commands to ease the burdens of manually configuring the various available cmake options. When more fine-grained control over the CMake configuration is desired, the `cmake` command can be invoked directly as the below example demonstrates. - -The `CMAKE_INSTALL_PREFIX` installs cuVS into a specific location. The example below installs cuVS into the current Conda environment: -```bash -cd cpp -mkdir build -cd build -cmake -D BUILD_TESTS=ON -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX ../ -make -j install -``` - -cuVS has the following configurable cmake flags available: - -| Flag | Possible Values | Default Value | Behavior | -|------------------------|----------------------| --- |------------------------------------------------------------------------------| -| BUILD_TESTS | ON, OFF | ON | Compile Googletests | -| CUDA_ENABLE_KERNELINFO | ON, OFF | OFF | Enables `kernelinfo` in nvcc. This is useful for `compute-sanitizer` | -| CUDA_ENABLE_LINEINFO | ON, OFF | OFF | Enable the -lineinfo option for nvcc | -| CUDA_STATIC_RUNTIME | ON, OFF | OFF | Statically link the CUDA runtime | -| DETECT_CONDA_ENV | ON, OFF | ON | Enable detection of conda environment for dependencies | -| CUVS_NVTX | ON, OFF | OFF | Enable NVTX Markers | - -### Build documentation - -The documentation requires that the C, C++ and Python libraries have been built and installed. The following will build the docs along with the necessary libraries: - -``` -./build.sh libcuvs python docs -``` - -## Use cuVS in your application - -The [examples/](https://github.com/rapidsai/raft/tree/HEAD/examples) directory at the root of the cuVS repository has self-contains drop-in projects to build and use the cuVS SDK in your applications. \ No newline at end of file diff --git a/docs/source/build.rst b/docs/source/build.rst new file mode 100644 index 000000000..814022465 --- /dev/null +++ b/docs/source/build.rst @@ -0,0 +1,233 @@ +Installation +============ + +The cuVS software development kit provides APIs for C, C++, Python, and Rust languages. This guide outlines how to install the pre-compiled packages, build it from source, and use it in downstream applications. + +- `Installing pre-compiled packages`_ + + * `C, C++, and Python through Conda`_ + + * `Python through Pip`_ + + * `Rust through crates.io`_ + +- `Build from source`_ + + * `Prerequisites`_ + + * `Create a build environment`_ + + * `C and C++ Libraries`_ + + * `Building the Googletests`_ + + * `Python Library`_ + + * `Rust Library`_ + + * `Using Cmake Directly`_ + +- `Build Documentation`_ + + +Installing Pre-compiled Packages +-------------------------------- + +C, C++, and Python through Conda +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The easiest way to install the pre-compiled C, C++, and Python packages is through `conda `_. Use the following commands, depending on your CUDA version, to install cuVS packages (replace `rapidsai` with `rapidsai-nightly` to install more up-to-date but less stable nightly packages). `mamba` is preferred over the `conda` command. + +C++ Package +~~~~~~~~~~~ + +.. code-block:: bash + + mamba install -c rapidsai -c conda-forge -c nvidia libcuvs cuda-version=12.0 + +C Package +~~~~~~~~~ + +.. code-block:: bash + + mamba install -c rapidsai -c conda-forge -c nvidia libcuvs_c cuda-version=12.0 + +Python Package +~~~~~~~~~~~~~~ + +.. code-block:: bash + + mamba install -c rapidsai -c conda-forge -c nvidia cuvs cuda-version=12.0 + +Python through Pip +^^^^^^^^^^^^^^^^^^ + +The cuVS Python package can also be `installed through pip `_. + +For CUDA 11 packages: + +.. code-block:: bash + + pip install cuvs-cu11 --extra-index-url=https://pypi.nvidia.com + +And CUDA 12 packages: + +.. code-block:: bash + + pip install cuvs-cu12 --extra-index-url=https://pypi.nvidia.com + +Note: these packages statically link the C and C++ libraries so the `libcuvs` and `libcuvs_c` shared libraries won't be readily available to use in your code. + +Rust through crates.io +^^^^^^^^^^^^^^^^^^^^^^ + +Build from source +----------------- + +The core cuVS source code is written in C++ and wrapped through a C API. The C API is wrapped around the C++ APIs and the other supported languages are built around the C API. + + +Prerequisites +^^^^^^^^^^^^^ + +- Cmake 3.26.4+ +- GCC 9.3+ (11.4+ recommended) +- CUDA Toolkit 11.4+ +- Volta architecture or better (compute capability >= 7.0) + +Create a build environment +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +`Conda `_ environment scripts are provided for installing the necessary dependencies to build cuVS from source. It is preferred to use `mamba`, as it provides significant speedup over `conda`: + +.. code-block:: bash + + mamba env create --name cuvs -f conda/environments/all_cuda-120_arch-x86_64.yaml + mamba activate cuvs + +The process for building from source with CUDA 11 differs slightly in that your host system will also need to have CUDA toolkit installed which is greater than, or equal to, the version you install into you conda environment. Installing CUDA toolkit into your host system is necessary because `nvcc` is not provided with Conda's cudatoolkit dependencies for CUDA 11. The following example will install create and install dependencies for a CUDA 11.8 conda environment + +.. code-block:: bash + + mamba env create --name cuvs -f conda/environments/all_cuda-118_arch-x86_64.yaml + mamba activate cuvs + +The recommended way to build and install cuVS from source is to use the `build.sh` script in the root of the repository. This script can build both the C++ and Python artifacts and provides CMake options for building and installing the headers, tests, benchmarks, and the pre-compiled shared library. + + +C and C++ libraries +^^^^^^^^^^^^^^^^^^^ + +The C and C++ shared libraries are built together using the following arguments to `build.sh`: + +.. code-block:: bash + + ./build.sh libcuvs + +In above example the `libcuvs.so` and `libcuvs_c.so` shared libraries are installed by default into `$INSTALL_PREFIX/lib`. To disable this, pass `-n` flag. + +Once installed, the shared libraries, headers (and any dependencies downloaded and installed via `rapids-cmake`) can be uninstalled using `build.sh`: + +.. code-block:: bash + + ./build.sh libcuvs --uninstall + + +Building the Googletests +~~~~~~~~~~~~~~~~~~~~~~~~ + +Compile the C and C++ Googletests using the `tests` target in `build.sh`. + +.. code-block:: bash + + ./build.sh libcuvs tests + +The tests will be written to the build directory, which is `cpp/build/` by default, and they will be named `*_TEST`. + +It can take some time to compile all of the tests. You can build individual tests by providing a semicolon-separated list to the `--limit-tests` option in `build.sh`. Make sure to pass the `-n` flag so the tests are not installed. + +.. code-block:: bash + + ./build.sh libcuvs tests -n --limit-tests=NEIGHBORS_TEST;CAGRA_C_TEST + +Python library +^^^^^^^^^^^^^^ + +The Python library should be built and installed using the `build.sh` script: + +.. code-block:: bash + + ./build.sh python + +The Python packages can also be uninstalled using the `build.sh` script: + +.. code-block:: bash + + ./build.sh python --uninstall + +Rust library +^^^^^^^^^^^^ + +Using CMake directly +^^^^^^^^^^^^^^^^^^^^ + +When building cuVS from source, the `build.sh` script offers a nice wrapper around the `cmake` commands to ease the burdens of manually configuring the various available cmake options. When more fine-grained control over the CMake configuration is desired, the `cmake` command can be invoked directly as the below example demonstrates. + +The `CMAKE_INSTALL_PREFIX` installs cuVS into a specific location. The example below installs cuVS into the current Conda environment: + +.. code-block:: bash + + cd cpp + mkdir build + cd build + cmake -D BUILD_TESTS=ON -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX ../ + make -j install + +cuVS has the following configurable cmake flags available: + +.. list-table:: Cmake Flags + + * - Flag + - Possible Values + - Default Value + - Behavior + + * - BUILD_TESTS + - ON, OFF + - ON + - Compile Googletests + + * - CUDA_ENABLE_KERNELINFO + - ON, OFF + - OFF + - Enables `kernelinfo` in nvcc. This is useful for `compute-sanitizer` + + * - CUDA_ENABLE_LINEINFO + - ON, OFF + - OFF + - Enable the `-lineinfo` option for nvcc + + * - CUDA_STATIC_RUNTIME + - ON, OFF + - OFF + - Statically link the CUDA runtime + + * - DETECT_CONDA_ENV + - ON, OFF + - ON + - Enable detection of conda environment for dependencies + + * - CUVS_NVTX + - ON, OFF + - OFF + - Enable NVTX markers + + +Build documentation +^^^^^^^^^^^^^^^^^^^ + +The documentation requires that the C, C++ and Python libraries have been built and installed. The following will build the docs along with the necessary libraries: + +.. code-block:: bash + + ./build.sh libcuvs python docs diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst new file mode 100644 index 000000000..79b35c2d5 --- /dev/null +++ b/docs/source/getting_started.rst @@ -0,0 +1,12 @@ +Getting Started +=============== + +This guide provides an initial starting point of the basic concepts and using the various APIs in the cuVS software development kit. + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + basics.rst + interoperability.rst + working_with_ann_indexes.rst \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index ce8a8e1d2..b8334e858 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,7 +6,7 @@ Useful Resources .. _cuvs_reference: https://docs.rapids.ai/api/cuvs/stable/ -- `Example Notebooks `_: Example Jupyter notebooks +- `Example Notebooks `_: Self-contained Code examples - `RAPIDS Community `_: Get help, contribute, and collaborate. - `GitHub repository `_: Download the cuVS source code. - `Issue tracker `_: Report issues or request features. @@ -21,8 +21,9 @@ cuVS is a library for vector search and clustering on the GPU. :maxdepth: 1 :caption: Contents: - quick_start.md + getting_started.rst build.md + integrations.rst api_docs.rst contributing.md diff --git a/docs/source/integrations.rst b/docs/source/integrations.rst new file mode 100644 index 000000000..6c6e2ce8c --- /dev/null +++ b/docs/source/integrations.rst @@ -0,0 +1,40 @@ +Integrations +============ + +Aside from using cuVS directly, it can be consumed through a number of sdk and vector database integrations. + +- `FAISS`_ +- `Milvus`_ +- `Kinetica`_ + +FAISS +----- + +FAISS v1.8 provides a special conda package that enables a RAFT backend for the Flat, IVF-Flat and IVF-PQ indexes on the GPU. Like the classical FAISS GPU indexes, the RAFT backend also enables interoperability between FAISS CPU indexes, allowing an index to be trained on GPU, searched on CPU, and vice versa. + +The RAFT backend can be enabled by building FAISS from source with the `FAISS_USE_RAFT` cmake flag enabled and setting the `use_raft` configuration option for the RAFT-enabled GPU indexes. + +A pre-compiled conda package can also be installed using the following command: + +.. code-block:: bash + + conda install -c conda-forge -c pytorch -c rapidsai -c nvidia -c "nvidia/label/cuda-11.8.0" faiss-gpu-raft + +The next release of FAISS will feature cuVS support as we continue to migrate the vector search algorithms from RAFT to cuVS. + +Milvus +------ + +In version 2.3, Milvus released support for IVF-Flat and IVF-PQ indexes on the GPU through RAFT. Version 2.4 adds support for brute-force and the graph-based CAGRA index on the GPU. Please refer to the `Milvus documentation `_ to install Milvus with GPU support. + +The GPU indexes can be enabled by using the index types prefixed with `GPU_`, as outlined in the `Milvus index build guide `_. + +Milvus will be migrating their GPU support from RAFT to cuVS as we continue to move the vector search algorithms out of RAFT and into cuVS. + + +Kinetica +-------- + +Starting with release 7.2, Kinetica supports the graph-based the CAGRA algorithm from RAFT. Kinetica will continue to improve its support over coming versions, while also migrating to cuVS as we work to move the vector search algorithms out of RAFT and into cuVS. + +Kinetica currently offers the ability to create a CAGRA index in a SQL `CREATE_TABLE` statement, as outlined in their `vector search indexing docs `_. Kinetica is not open source, but the RAFT indexes can be enabled in the developer edition, which can be installed `here `_. \ No newline at end of file diff --git a/docs/source/interoperability.rst b/docs/source/interoperability.rst new file mode 100644 index 000000000..fc8d19ef4 --- /dev/null +++ b/docs/source/interoperability.rst @@ -0,0 +1,72 @@ +Interoperability +================ + +DLPack (C) +^^^^^^^^^^ + +Multi-dimensional span (C++) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +cuVS is built on top of the GPU-accelerated machine learning and data mining primitives in the `RAFT `_ library. Most of the C++ APIs in cuVS accept `mdspan `_ multi-dimensional array view for representing data in higher dimensions similar to the `ndarray` in the Numpy Python library. RAFT also contains the corresponding owning `mdarray` structure, which simplifies the allocation and management of multi-dimensional data in both host and device (GPU) memory. + +The `mdarray` is an owning object that forms a convenience layer over RMM and can be constructed in RAFT using a number of different helper functions: + +.. code-block:: c++ + + #include + + int n_rows = 10; + int n_cols = 10; + + auto scalar = raft::make_device_scalar(handle, 1.0); + auto vector = raft::make_device_vector(handle, n_cols); + auto matrix = raft::make_device_matrix(handle, n_rows, n_cols); + +The `mdspan` is a lightweight non-owning view that can wrap around any pointer, maintaining shape, layout, and indexing information for accessing elements. + +We can construct `mdspan` instances directly from the above `mdarray` instances: + +.. code-block:: c++ + + // Scalar mdspan on device + auto scalar_view = scalar.view(); + + // Vector mdspan on device + auto vector_view = vector.view(); + + // Matrix mdspan on device + auto matrix_view = matrix.view(); + +Since the `mdspan` is just a lightweight wrapper, we can also construct it from the underlying data handles in the `mdarray` instances above. We use the extent to get information about the `mdarray` or `mdspan`'s shape. + +.. code-block:: c++ + + #include + + auto scalar_view = raft::make_device_scalar_view(scalar.data_handle()); + auto vector_view = raft::make_device_vector_view(vector.data_handle(), vector.extent(0)); + auto matrix_view = raft::make_device_matrix_view(matrix.data_handle(), matrix.extent(0), matrix.extent(1)); + +Of course, RAFT's `mdspan`/`mdarray` APIs aren't just limited to the `device`. You can also create `host` variants: + +.. code-block:: c++ + + #include + #include + + int n_rows = 10; + int n_cols = 10; + + auto scalar = raft::make_host_scalar(handle, 1.0); + auto vector = raft::make_host_vector(handle, n_cols); + auto matrix = raft::make_host_matrix(handle, n_rows, n_cols); + + auto scalar_view = raft::make_host_scalar_view(scalar.data_handle()); + auto vector_view = raft::make_host_vector_view(vector.data_handle(), vector.extent(0)); + auto matrix_view = raft::make_host_matrix_view(matrix.data_handle(), matrix.extent(0), matrix.extent(1)); + +Please refer to RAFT's `mdspan` `documentation `_ to learn more. + + +CUDA array interface (Python) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/source/quick_start.md b/docs/source/quick_start.md deleted file mode 100644 index 3909b40f2..000000000 --- a/docs/source/quick_start.md +++ /dev/null @@ -1,183 +0,0 @@ -# Quick Start - -This guide is meant to provide a quick-start tutorial for interacting with RAFT's C++ & Python APIs. - -## RAPIDS Memory Manager (RMM) - -RAFT relies heavily on the [RMM](https://github.com/rapidsai/rmm) library which eases the burden of configuring different allocation strategies globally across the libraries that use it. - -## Multi-dimensional Spans and Arrays - -Most of the APIs in RAFT accept [mdspan](https://arxiv.org/abs/2010.06474) multi-dimensional array view for representing data in higher dimensions similar to the `ndarray` in the Numpy Python library. RAFT also contains the corresponding owning `mdarray` structure, which simplifies the allocation and management of multi-dimensional data in both host and device (GPU) memory. - -The `mdarray` is an owning object that forms a convenience layer over RMM and can be constructed in RAFT using a number of different helper functions: - -```c++ -#include - -int n_rows = 10; -int n_cols = 10; - -auto scalar = raft::make_device_scalar(handle, 1.0); -auto vector = raft::make_device_vector(handle, n_cols); -auto matrix = raft::make_device_matrix(handle, n_rows, n_cols); -``` - -The `mdspan` is a lightweight non-owning view that can wrap around any pointer, maintaining shape, layout, and indexing information for accessing elements. - - -We can construct `mdspan` instances directly from the above `mdarray` instances: - -```c++ -// Scalar mdspan on device -auto scalar_view = scalar.view(); - -// Vector mdspan on device -auto vector_view = vector.view(); - -// Matrix mdspan on device -auto matrix_view = matrix.view(); -``` -Since the `mdspan` is just a lightweight wrapper, we can also construct it from the underlying data handles in the `mdarray` instances above. We use the extent to get information about the `mdarray` or `mdspan`'s shape. - -```c++ -#include - -auto scalar_view = raft::make_device_scalar_view(scalar.data_handle()); -auto vector_view = raft::make_device_vector_view(vector.data_handle(), vector.extent(0)); -auto matrix_view = raft::make_device_matrix_view(matrix.data_handle(), matrix.extent(0), matrix.extent(1)); -``` - -Of course, RAFT's `mdspan`/`mdarray` APIs aren't just limited to the `device`. You can also create `host` variants: - -```c++ -#include -#include - -int n_rows = 10; -int n_cols = 10; - -auto scalar = raft::make_host_scalar(handle, 1.0); -auto vector = raft::make_host_vector(handle, n_cols); -auto matrix = raft::make_host_matrix(handle, n_rows, n_cols); - -auto scalar_view = raft::make_host_scalar_view(scalar.data_handle()); -auto vector_view = raft::make_host_vector_view(vector.data_handle(), vector.extent(0)); -auto matrix_view = raft::make_host_matrix_view(matrix.data_handle(), matrix.extent(0), matrix.extent(1)); -``` - -And `managed` variants: - -```c++ -#include - -int n_rows = 10; -int n_cols = 10; - -auto matrix = raft::make_managed_mdspan(managed_ptr, raft::make_matrix_extents(n_rows, n_cols)); -``` - -You can also create strided mdspans: - -```c++ - -#include - -int n_elements = 10; -int stride = 10; - -auto vector = raft::make_device_vector_view(vector_ptr, raft::make_vector_strided_layout(n_elements, stride)); -``` - - -## C++ Example - -Most of the primitives in RAFT accept a `raft::handle_t` object for the management of resources which are expensive to create, such CUDA streams, stream pools, and handles to other CUDA libraries like `cublas` and `cusolver`. - -The example below demonstrates creating a RAFT handle and using it with `device_matrix` and `device_vector` to allocate memory, generating random clusters, and computing -pairwise Euclidean distances: - -```c++ -#include -#include -#include -#include - -raft::handle_t handle; - -int n_samples = 5000; -int n_features = 50; - -auto input = raft::make_device_matrix(handle, n_samples, n_features); -auto labels = raft::make_device_vector(handle, n_samples); -auto output = raft::make_device_matrix(handle, n_samples, n_samples); - -raft::random::make_blobs(handle, input.view(), labels.view()); - -auto metric = raft::distance::DistanceType::L2SqrtExpanded; -raft::distance::pairwise_distance(handle, input.view(), input.view(), output.view(), metric); -``` - -## Python Example - -The `pylibraft` package contains a Python API for RAFT algorithms and primitives. `pylibraft` integrates nicely into other libraries by being very lightweight with minimal dependencies and accepting any object that supports the `__cuda_array_interface__`, such as [CuPy's ndarray](https://docs.cupy.dev/en/stable/user_guide/interoperability.html#rmm). The number of RAFT algorithms exposed in this package is continuing to grow from release to release. - -The example below demonstrates computing the pairwise Euclidean distances between CuPy arrays. Note that CuPy is not a required dependency for `pylibraft`. - -```python -import cupy as cp - -from pylibraft.distance import pairwise_distance - -n_samples = 5000 -n_features = 50 - -in1 = cp.random.random_sample((n_samples, n_features), dtype=cp.float32) -in2 = cp.random.random_sample((n_samples, n_features), dtype=cp.float32) - -output = pairwise_distance(in1, in2, metric="euclidean") -``` - -The `output` array in the above example is of type `raft.common.device_ndarray`, which supports [__cuda_array_interface__](https://numba.pydata.org/numba-doc/dev/cuda/cuda_array_interface.html#cuda-array-interface-version-2) making it interoperable with other libraries like CuPy, Numba, and PyTorch that also support it. CuPy supports DLPack, which also enables zero-copy conversion from `raft.common.device_ndarray` to JAX and Tensorflow. - -Below is an example of converting the output `pylibraft.common.device_ndarray` to a CuPy array: -```python -cupy_array = cp.asarray(output) -``` - -And converting to a PyTorch tensor: -```python -import torch - -torch_tensor = torch.as_tensor(output, device='cuda') -``` - -When the corresponding library has been installed and available in your environment, this conversion can also be done automatically by all RAFT compute APIs by setting a global configuration option: -```python -import pylibraft.config -pylibraft.config.set_output_as("cupy") # All compute APIs will return cupy arrays -pylibraft.config.set_output_as("torch") # All compute APIs will return torch tensors -``` - -You can also specify a `callable` that accepts a `pylibraft.common.device_ndarray` and performs a custom conversion. The following example converts all output to `numpy` arrays: -```python -pylibraft.config.set_output_as(lambda device_ndarray: return device_ndarray.copy_to_host()) -``` - - -`pylibraft` also supports writing to a pre-allocated output array so any `__cuda_array_interface__` supported array can be written to in-place: - -```python -import cupy as cp - -from pylibraft.distance import pairwise_distance - -n_samples = 5000 -n_features = 50 - -in1 = cp.random.random_sample((n_samples, n_features), dtype=cp.float32) -in2 = cp.random.random_sample((n_samples, n_features), dtype=cp.float32) -output = cp.empty((n_samples, n_samples), dtype=cp.float32) - -pairwise_distance(in1, in2, out=output, metric="euclidean") -``` diff --git a/docs/source/working_with_ann_indexes.rst b/docs/source/working_with_ann_indexes.rst new file mode 100644 index 000000000..f347a2f42 --- /dev/null +++ b/docs/source/working_with_ann_indexes.rst @@ -0,0 +1,102 @@ +Working with ANN Indexes +======================== + +- `Building an index`_ +- `Searching an index`_ +- `CPU/GPU Interoperability`_ +- `Serializing an index`_ + +Building an index +----------------- + +C +^ + +.. code-block:: c + + #include + + cuvsResources_t res; + cuvsCagraIndexParams_t index_params; + cuvsCagraIndex_t index; + + DLManagedTensor *dataset; + load_dataset(dataset); + + cuvsResourcesCreate(&res); + cuvsCagraIndexParamsCreate(&index_params); + cuvsCagraIndexCreate(&index); + + cuvsCagraBuild(res, index_params, dataset, index); + + cuvsCagraIndexDestroy(index); + cuvsCagraIndexParamsDestroy(index_params); + cuvsResourcesDestroy(res); + +C++ +^^^ + +.. code-block:: c++ + + #include + + using namespace cuvs::neighbors; + + raft::device_matrix_view dataset = load_dataset(); + raft::device_resources res; + + cagra::index_params index_params; + + auto index = cagra::build(res, index_params, dataset); + + +Python +^^^^^^ + +.. code-block:: python + + from cuvs.neighbors import cagra + + dataset = load_data() + index_params = cagra.IndexParams() + + index = cagra.build_index(build_params, dataset) + +Rust +^^^^ + +.. code-block:: rust + + use cuvs::cagra::{Index, IndexParams}; + use cuvs::{Resources, Result}; + + use ndarray_rand::rand_distr::Uniform; + use ndarray_rand::RandomExt; + + /// Example showing how to index and search data with CAGRA + 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)?; + + Ok(()) + } + + +Searching an index +------------------ + + +CPU/GPU interoperability +------------------------ + +Serializing an index +-------------------- \ No newline at end of file