Skip to content
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 .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#cpp code owners
cpp/ @rapidsai/cuvs-cpp-codeowners
examples/cpp/ @rapidsai/cuvs-cpp-codeowners
examples/c/ @rapidsai/cuvs-cpp-codeowners

#java code owners
java/ @rapidsai/cuvs-java-codeowners
examples/java/ @rapidsai/cuvs-java-codeowners

#python code owners
python/ @rapidsai/cuvs-python-codeowners

#rust code owners
rust/ @rapidsai/cuvs-rust-codeowners
examples/rust/ @rapidsai/cuvs-rust-codeowners

#docs code owners
docs/ @rapidsai/cuvs-docs-codeowners
Expand Down
1 change: 1 addition & 0 deletions examples/.clang-format
1 change: 1 addition & 0 deletions examples/.clang-tidy
1 change: 1 addition & 0 deletions examples/.clangd
4 changes: 3 additions & 1 deletion examples/c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# =============================================================================
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -35,6 +35,8 @@ set(BUILD_CUVS_C_LIBRARY ON)
include(../cmake/thirdparty/get_dlpack.cmake)
include(../cmake/thirdparty/get_cuvs.cmake)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")

add_executable(CAGRA_C_EXAMPLE src/cagra_c_example.c)
target_include_directories(CAGRA_C_EXAMPLE PUBLIC "$<BUILD_INTERFACE:${DLPACK_INCLUDE_DIR}>")
target_link_libraries(CAGRA_C_EXAMPLE PRIVATE cuvs::c_api $<TARGET_NAME_IF_EXISTS:conda_env>)
Expand Down
79 changes: 43 additions & 36 deletions examples/c/src/L2_c_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@
#include <stdio.h>
#include <stdlib.h>

#define DIM 4
#include "common.h"

#define DIM 4
#define N_ROWS 1

float PointA[N_ROWS][DIM] = {1.0,2.0,3.0,4.0};
float PointB[N_ROWS][DIM] = {2.0,3.0,4.0,5.0};
float PointA[N_ROWS][DIM] = {{1.0, 2.0, 3.0, 4.0}};
float PointB[N_ROWS][DIM] = {{2.0, 3.0, 4.0, 5.0}};

cuvsResources_t res;

void outputVector(float * Vec) {
void outputVector(float* Vec)
{
printf("Vector is ");
for (int i = 0; i < DIM; ++i){
printf(" %f",Vec[i]);
for (int i = 0; i < DIM; ++i) {
printf(" %f", Vec[i]);
}
printf("\n");
}
Expand All @@ -44,18 +47,20 @@ void outputVector(float * Vec) {
* @brief Initialize Tensor.
*
* @param[in] x_d Pointer to a vector
* @param[in] x_shape[] Two-dimensional array, which stores the number of rows and columns of vectors.
* @param[in] x_shape[] Two-dimensional array, which stores the number of rows
* and columns of vectors.
* @param[out] x_tensor Stores the initialized DLManagedTensor.
*/
void tensor_initialize(float* x_d, int64_t x_shape[2], DLManagedTensor* x_tensor) {
x_tensor->dl_tensor.data = x_d;
void tensor_initialize(float* x_d, int64_t x_shape[2], DLManagedTensor* x_tensor)
{
x_tensor->dl_tensor.data = x_d;
x_tensor->dl_tensor.device.device_type = kDLCUDA;
x_tensor->dl_tensor.ndim = 2;
x_tensor->dl_tensor.dtype.code = kDLFloat;
x_tensor->dl_tensor.dtype.bits = 32;
x_tensor->dl_tensor.dtype.lanes = 1;
x_tensor->dl_tensor.shape = x_shape;
x_tensor->dl_tensor.strides = NULL;
x_tensor->dl_tensor.ndim = 2;
x_tensor->dl_tensor.dtype.code = kDLFloat;
x_tensor->dl_tensor.dtype.bits = 32;
x_tensor->dl_tensor.dtype.lanes = 1;
x_tensor->dl_tensor.shape = x_shape;
x_tensor->dl_tensor.strides = NULL;
}

/**
Expand All @@ -66,16 +71,17 @@ void tensor_initialize(float* x_d, int64_t x_shape[2], DLManagedTensor* x_tensor
* @param[in] y[] Pointer to another vector
* @param[out] ret will store the result about the euclidean distance
*/
void l2_distance_calc(int64_t n_cols,float x[], float y[], float *ret) {
void l2_distance_calc(int64_t n_cols, float x[], float y[], float* ret)
{
float *x_d, *y_d;
float *distance_d;
cuvsRMMAlloc(res, (void**) &x_d, sizeof(float) * N_ROWS * n_cols);
cuvsRMMAlloc(res, (void**) &y_d, sizeof(float) * N_ROWS * n_cols);
cuvsRMMAlloc(res, (void**) &distance_d, sizeof(float) * N_ROWS * N_ROWS);
float* distance_d;
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&x_d, sizeof(float) * N_ROWS * n_cols));
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&y_d, sizeof(float) * N_ROWS * n_cols));
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&distance_d, sizeof(float) * N_ROWS * N_ROWS));

// Use DLPack to represent x[] and y[] as tensors
cudaMemcpy(x_d, x, sizeof(float) * N_ROWS * n_cols, cudaMemcpyDefault);
cudaMemcpy(y_d, y, sizeof(float) * N_ROWS * n_cols, cudaMemcpyDefault);
CHECK_CUDA(cudaMemcpy(x_d, x, sizeof(float) * N_ROWS * n_cols, cudaMemcpyDefault));
CHECK_CUDA(cudaMemcpy(y_d, y, sizeof(float) * N_ROWS * n_cols, cudaMemcpyDefault));

DLManagedTensor x_tensor;
int64_t x_shape[2] = {N_ROWS, n_cols};
Expand All @@ -90,34 +96,35 @@ void l2_distance_calc(int64_t n_cols,float x[], float y[], float *ret) {
tensor_initialize(distance_d, distances_shape, &dist_tensor);

// metric_arg default value is 2.0,used for Minkowski distance
cuvsPairwiseDistance(res, &x_tensor, &y_tensor, &dist_tensor, L2SqrtUnexpanded, 2.0);

cudaMemcpy(ret, distance_d, sizeof(float) * N_ROWS * N_ROWS, cudaMemcpyDefault);
CHECK_CUVS(cuvsPairwiseDistance(res, &x_tensor, &y_tensor, &dist_tensor, L2SqrtUnexpanded, 2.0));

cuvsRMMFree(res, distance_d, sizeof(float) * N_ROWS * N_ROWS);
cuvsRMMFree(res, x_d, sizeof(float) * N_ROWS * n_cols);
cuvsRMMFree(res, y_d, sizeof(float) * N_ROWS * n_cols);
CHECK_CUDA(cudaMemcpy(ret, distance_d, sizeof(float) * N_ROWS * N_ROWS, cudaMemcpyDefault));

CHECK_CUVS(cuvsRMMFree(res, distance_d, sizeof(float) * N_ROWS * N_ROWS));
CHECK_CUVS(cuvsRMMFree(res, x_d, sizeof(float) * N_ROWS * n_cols));
CHECK_CUVS(cuvsRMMFree(res, y_d, sizeof(float) * N_ROWS * n_cols));
}

int euclidean_distance_calculation_example() {
int euclidean_distance_calculation_example()
{
// Create a cuvsResources_t object
cuvsResourcesCreate(&res);

outputVector((float *)PointA);
outputVector((float *)PointB);
outputVector((float*)PointA);
outputVector((float*)PointB);

float ret;

l2_distance_calc(DIM, (float *)PointA, (float *)PointB, &ret);
l2_distance_calc(DIM, (float*)PointA, (float*)PointB, &ret);
printf("L2 distance is %f.\n", ret);

cuvsResourcesDestroy(res);
CHECK_CUVS(cuvsResourcesDestroy(res));

return 0;
}

int main() {
euclidean_distance_calculation_example();
return 0;
int main()
{
euclidean_distance_calculation_example();
return 0;
}
136 changes: 68 additions & 68 deletions examples/c/src/cagra_c_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <stdio.h>
#include <stdlib.h>

#include "common.h"

float dataset[4][2] = {{0.74021935, 0.9209938},
{0.03902049, 0.9689629},
{0.92514056, 0.4463501},
Expand All @@ -32,121 +34,119 @@ float queries[4][2] = {{0.48216683, 0.0428398},
{0.51260436, 0.2643005},
{0.05198065, 0.5789965}};

void cagra_build_search_simple() {

int64_t n_rows = 4;
int64_t n_cols = 2;
int64_t topk = 2;
void cagra_build_search_simple()
{
int64_t n_rows = 4;
int64_t n_cols = 2;
int64_t topk = 2;
int64_t n_queries = 4;

// Create a cuvsResources_t object
cuvsResources_t res;
cuvsResourcesCreate(&res);
CHECK_CUVS(cuvsResourcesCreate(&res));

// Use DLPack to represent `dataset` as a tensor
DLManagedTensor dataset_tensor;
dataset_tensor.dl_tensor.data = dataset;
dataset_tensor.dl_tensor.data = dataset;
dataset_tensor.dl_tensor.device.device_type = kDLCPU;
dataset_tensor.dl_tensor.ndim = 2;
dataset_tensor.dl_tensor.dtype.code = kDLFloat;
dataset_tensor.dl_tensor.dtype.bits = 32;
dataset_tensor.dl_tensor.dtype.lanes = 1;
int64_t dataset_shape[2] = {n_rows, n_cols};
dataset_tensor.dl_tensor.shape = dataset_shape;
dataset_tensor.dl_tensor.strides = NULL;
dataset_tensor.dl_tensor.ndim = 2;
dataset_tensor.dl_tensor.dtype.code = kDLFloat;
dataset_tensor.dl_tensor.dtype.bits = 32;
dataset_tensor.dl_tensor.dtype.lanes = 1;
int64_t dataset_shape[2] = {n_rows, n_cols};
dataset_tensor.dl_tensor.shape = dataset_shape;
dataset_tensor.dl_tensor.strides = NULL;

// Build the CAGRA index
cuvsCagraIndexParams_t index_params;
cuvsCagraIndexParamsCreate(&index_params);
CHECK_CUVS(cuvsCagraIndexParamsCreate(&index_params));

cuvsCagraIndex_t index;
cuvsCagraIndexCreate(&index);
CHECK_CUVS(cuvsCagraIndexCreate(&index));

cuvsCagraBuild(res, index_params, &dataset_tensor, index);
CHECK_CUVS(cuvsCagraBuild(res, index_params, &dataset_tensor, index));

// Allocate memory for `queries`, `neighbors` and `distances` output
uint32_t *neighbors;
uint32_t* neighbors;
float *distances, *queries_d;
cuvsRMMAlloc(res, (void **)&queries_d, sizeof(float) * n_queries * n_cols);
cuvsRMMAlloc(res, (void **)&neighbors, sizeof(uint32_t) * n_queries * topk);
cuvsRMMAlloc(res, (void **)&distances, sizeof(float) * n_queries * topk);
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&queries_d, sizeof(float) * n_queries * n_cols));
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&neighbors, sizeof(uint32_t) * n_queries * topk));
CHECK_CUVS(cuvsRMMAlloc(res, (void**)&distances, sizeof(float) * n_queries * topk));

// Use DLPack to represent `queries`, `neighbors` and `distances` as tensors
cudaMemcpy(queries_d, queries, sizeof(float) * 4 * 2, cudaMemcpyDefault);
CHECK_CUDA(cudaMemcpy(queries_d, queries, sizeof(float) * 4 * 2, cudaMemcpyDefault));

DLManagedTensor queries_tensor;
queries_tensor.dl_tensor.data = queries_d;
queries_tensor.dl_tensor.data = queries_d;
queries_tensor.dl_tensor.device.device_type = kDLCUDA;
queries_tensor.dl_tensor.ndim = 2;
queries_tensor.dl_tensor.dtype.code = kDLFloat;
queries_tensor.dl_tensor.dtype.bits = 32;
queries_tensor.dl_tensor.dtype.lanes = 1;
int64_t queries_shape[2] = {n_queries, n_cols};
queries_tensor.dl_tensor.shape = queries_shape;
queries_tensor.dl_tensor.strides = NULL;
queries_tensor.dl_tensor.ndim = 2;
queries_tensor.dl_tensor.dtype.code = kDLFloat;
queries_tensor.dl_tensor.dtype.bits = 32;
queries_tensor.dl_tensor.dtype.lanes = 1;
int64_t queries_shape[2] = {n_queries, n_cols};
queries_tensor.dl_tensor.shape = queries_shape;
queries_tensor.dl_tensor.strides = NULL;

DLManagedTensor neighbors_tensor;
neighbors_tensor.dl_tensor.data = neighbors;
neighbors_tensor.dl_tensor.data = neighbors;
neighbors_tensor.dl_tensor.device.device_type = kDLCUDA;
neighbors_tensor.dl_tensor.ndim = 2;
neighbors_tensor.dl_tensor.dtype.code = kDLUInt;
neighbors_tensor.dl_tensor.dtype.bits = 32;
neighbors_tensor.dl_tensor.dtype.lanes = 1;
int64_t neighbors_shape[2] = {n_queries, topk};
neighbors_tensor.dl_tensor.shape = neighbors_shape;
neighbors_tensor.dl_tensor.strides = NULL;
neighbors_tensor.dl_tensor.ndim = 2;
neighbors_tensor.dl_tensor.dtype.code = kDLUInt;
neighbors_tensor.dl_tensor.dtype.bits = 32;
neighbors_tensor.dl_tensor.dtype.lanes = 1;
int64_t neighbors_shape[2] = {n_queries, topk};
neighbors_tensor.dl_tensor.shape = neighbors_shape;
neighbors_tensor.dl_tensor.strides = NULL;

DLManagedTensor distances_tensor;
distances_tensor.dl_tensor.data = distances;
distances_tensor.dl_tensor.data = distances;
distances_tensor.dl_tensor.device.device_type = kDLCUDA;
distances_tensor.dl_tensor.ndim = 2;
distances_tensor.dl_tensor.dtype.code = kDLFloat;
distances_tensor.dl_tensor.dtype.bits = 32;
distances_tensor.dl_tensor.dtype.lanes = 1;
int64_t distances_shape[2] = {n_queries, topk};
distances_tensor.dl_tensor.shape = distances_shape;
distances_tensor.dl_tensor.strides = NULL;
distances_tensor.dl_tensor.ndim = 2;
distances_tensor.dl_tensor.dtype.code = kDLFloat;
distances_tensor.dl_tensor.dtype.bits = 32;
distances_tensor.dl_tensor.dtype.lanes = 1;
int64_t distances_shape[2] = {n_queries, topk};
distances_tensor.dl_tensor.shape = distances_shape;
distances_tensor.dl_tensor.strides = NULL;

// Search the CAGRA index
cuvsCagraSearchParams_t search_params;
cuvsCagraSearchParamsCreate(&search_params);
CHECK_CUVS(cuvsCagraSearchParamsCreate(&search_params));

cuvsFilter filter;
filter.type = NO_FILTER;
filter.addr = (uintptr_t)NULL;

cuvsCagraSearch(res, search_params, index, &queries_tensor, &neighbors_tensor,
&distances_tensor, filter);
CHECK_CUVS(cuvsCagraSearch(
res, search_params, index, &queries_tensor, &neighbors_tensor, &distances_tensor, filter));

// print results
uint32_t *neighbors_h =
(uint32_t *)malloc(sizeof(uint32_t) * n_queries * topk);
float *distances_h = (float *)malloc(sizeof(float) * n_queries * topk);
cudaMemcpy(neighbors_h, neighbors, sizeof(uint32_t) * n_queries * topk,
cudaMemcpyDefault);
cudaMemcpy(distances_h, distances, sizeof(float) * n_queries * topk,
cudaMemcpyDefault);
printf("Query 0 neighbor indices: =[%d, %d]\n", neighbors_h[0],
neighbors_h[1]);
printf("Query 0 neighbor distances: =[%f, %f]\n", distances_h[0],
distances_h[1]);
uint32_t* neighbors_h = (uint32_t*)malloc(sizeof(uint32_t) * n_queries * topk);
float* distances_h = (float*)malloc(sizeof(float) * n_queries * topk);
CHECK_CUDA(
cudaMemcpy(neighbors_h, neighbors, sizeof(uint32_t) * n_queries * topk, cudaMemcpyDefault));
CHECK_CUDA(
cudaMemcpy(distances_h, distances, sizeof(float) * n_queries * topk, cudaMemcpyDefault));
printf("Query 0 neighbor indices: =[%d, %d]\n", neighbors_h[0], neighbors_h[1]);
printf("Query 0 neighbor distances: =[%f, %f]\n", distances_h[0], distances_h[1]);

// Free or destroy all allocations
free(neighbors_h);
free(distances_h);

cuvsCagraSearchParamsDestroy(search_params);
CHECK_CUVS(cuvsCagraSearchParamsDestroy(search_params));

cuvsRMMFree(res, distances, sizeof(float) * n_queries * topk);
cuvsRMMFree(res, neighbors, sizeof(uint32_t) * n_queries * topk);
cuvsRMMFree(res, queries_d, sizeof(float) * n_queries * n_cols);
CHECK_CUVS(cuvsRMMFree(res, distances, sizeof(float) * n_queries * topk));
CHECK_CUVS(cuvsRMMFree(res, neighbors, sizeof(uint32_t) * n_queries * topk));
CHECK_CUVS(cuvsRMMFree(res, queries_d, sizeof(float) * n_queries * n_cols));

cuvsCagraIndexDestroy(index);
cuvsCagraIndexParamsDestroy(index_params);
cuvsResourcesDestroy(res);
CHECK_CUVS(cuvsCagraIndexDestroy(index));
CHECK_CUVS(cuvsCagraIndexParamsDestroy(index_params));
CHECK_CUVS(cuvsResourcesDestroy(res));
}

int main() {
int main()
{
// Simple build and search example.
cagra_build_search_simple();
}
Loading