2. 快速入门
2.1. 软件包
2.1.1. 软件包信息
如果使用离线镜像文件,可以忽略本节。
软件包类型 |
文件名示例 |
说明 |
|---|---|---|
C++库 |
librmm-x.y.z+bu.v.w.m-py3-none-linux_x86_64.whl |
提供RMM头文件和so文件 |
Python wheel包 |
rmmx-x.y.z+bu.v.w.m-cp310-cp310-linux_x86_64.whl |
RMM的Python扩展包,适用于Python3.10 |
Python wheel包 |
rmmx-x.y.z+bu.v.w.m-cp312-cp312-linux_x86_64.whl |
RMM的Python扩展包,适用于Python3.12 |
C++库 |
libraft-x.y.z+bu.v.w.m-py3-none-linux_x86_64.whl |
提供RAFT头文件和so文件 |
Python wheel包 |
pylibraft-x.y.z+bu.v.w.m-cp310-cp310-linux_x86_64.whl |
RAFT的Python扩展包,适用于Python3.10 |
Python wheel包 |
pylibraft-x.y.z+bu.v.w.m-cp312-cp312-linux_x86_64.whl |
RAFT的Python扩展包,适用于Python3.12 |
C++库 |
libmcvs-x.y.z+bu.v.w.m-py3-none-linux_x86_64.whl |
提供mcVS头文件和so文件 |
Python wheel包 |
mcvs-x.y.z+bu.v.w.m-cp310-cp310-linux_x86_64.whl |
mcVS的Python扩展包,适用于Python3.10 |
Python wheel包 |
mcvs-x.y.z+bu.v.w.m-cp312-cp312-linux_x86_64.whl |
mcVS的Python扩展包,适用于Python3.12 |
Python wheel包 |
mcvs_bench-x.y.z+bu.v.w.m-py3-none-any.whl |
mcVS的Python扩展包 |
Python wheel包 |
mcpy-x.y.z+bu.v.w.m-cp310-cp310-linux_x86_64.whl |
mcpy的Python扩展包,适用于Python3.10 |
Python wheel包 |
mcpy-x.y.z+bu.v.w.m-cp312-cp312-linux_x86_64.whl |
mcpy的Python扩展包,适用于Python3.12 |
备注
x.y.z表示对应模块的开源版本号,u.v.w.m表示构建版本号。
x86_64表示CPU架构。
2.1.2. 软件包内容
安装libmcvs会在python安装第三方包的目录下 /path/to/site-packages/libcuvs 安装相关的二进制开发库和头文件。以 /path/to/site-packages/libcuvs 为起始路径,可得到如下文件内容:
├─include/
│ └─cuvs/
│ ├─neighbors
│ │ ├─all_neighbors.h
│ │ ├─bruef_force.h
│ │ ├─ivf_flat.h
│ │ └─......
│ ├─distance
│ │ ├─distance.h
│ │ └─......
│ └─...
├─lib/
│ ├─cmake
│ │ └─cuvs
│ │ ├─cuvs-config.cmake
│ │ ├─cuvs-targets.cmake
│ │ └─......
│ ├─libcuvs.so
│ └─libcuvs_c.so
目录 include/cuvs/ 包含了mcVS所有的头文件
目录 lib/cmake/cuvs/ 包含了cmake config文件
文件 lib/libfcuvs.so、lib/libcuvs_c.so 是动态链接库
2.2. 离线镜像文件部署方式
执行以下命令进入容器:
sudo docker load -i mcvs_mcdf_25.12_macax.y.z.n_py312_ubuntu24.04_amd64.tar.gz
sudo docker run -it --device=/dev/mxcd --device=/dev/dri --group-add video mxcr.io/dc-release/c500/mcvs_mcdf_25.12:x.y.z.n-ubuntu2404-x86_64 /bin/bash
2.3. 软件包安装部署方式
如果使用离线镜像文件,可以忽略本节。
2.3.1. 操作系统及依赖
mcVS 的libmcvs和mcvs 二进制包支持的操作系统及相关依赖,参见表 2.2。
操作系统 |
相关依赖 |
说明 |
|---|---|---|
Ubuntu 20.04 |
依赖版本的MXMACA Runtime |
|
cu-bridge |
||
Python3.12 |
||
Ubuntu 22.04 |
同Ubuntu 20.04 |
|
Ubuntu 24.04 |
同Ubuntu 20.04 |
请参考 cu-bridge 的使用指南安装并配置cu-bridge环境,建议安装到 /opt/maca/tools/ 目录下。
可以检查以下文件是否存在,并确认cu-bridge环境是否准备完毕:
/opt/maca/tools/cu-bridge/bin/cucc
/opt/maca/tools/cu-bridge/tools/cmake_maca
2.3.2. mcVS安装
Python wheel包
在支持的Linux系统中,可以使用pip进行安装(这里以python3.10环境为例)。
安装librmm和rmmx
$ pip install librmm-x.y.z.n+bu.v.w.m-py3-none-linux_x86_64.whl $ pip install rmmx-x.y.z.n+bu.v.w.m-cp310-cp310-linux_x86_64.whl
安装libraft和pylibraft
$ pip install libraft-x.y.z.n+bu.v.w.m-py3-none-linux_x86_64.whl $ pip install pylibraft-x.y.z.n+bu.v.w.m-cp310-cp310-linux_x86_64.whl
安装libmcvs和mcvs
$ pip install libmcvs-x.y.z.n+bu.v.w.m-py3-none-linux_x86_64.whl $ pip install mcvs-x.y.z.n+bu.v.w.m-cp310-cp310-linux_x86_64.whl
安装mcpy
$ pip install mcpy-x.y.z.n+bu.v.w.m-cp310-cp310-linux_x86_64.whl
2.4. mcVS使用
mcVS提供C++和Python两种语言的接口,mcVS的C++/Python接口和cuVS提供的接口完全一致。
2.4.1. 环境变量设置
mcVS 编译运行依赖如下环境变量:
MACA_PATH : 指向 MXMACA 包的安装路径, 比如 /opt/maca
CUDA_PATH : 指向 cu-bridge 安装路径, 比如 $MACA_PATH/tools/cu-bridge
2.4.2. 代码示例(C++)
使用C++进行brute_force索引完成向量添加、搜索,代码brute_force_example.cu示例如下:
#include <raft/core/resources.hpp>
#include <raft/core/device_mdspan.hpp>
#include <raft/core/device_resources.hpp>
#include <cuvs/neighbors/brute_force.hpp>
#include <rmm/device_uvector.hpp>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
using namespace cuvs::neighbors;
int main() {
raft::device_resources res;
int64_t n_rows = 10, dim = 4, n_queries = 2, k = 3;
// 1. Generate deterministic data on CPU
std::vector<float> h_dataset(n_rows * dim);
std::vector<float> h_queries(n_queries * dim);
std::mt19937 gen(42); // Fixed seed
std::uniform_real_distribution<float> dis(0.0, 1.0);
auto rand_func = [&]() { return dis(gen); };
std::generate(h_dataset.begin(), h_dataset.end(), rand_func);
std::generate(h_queries.begin(), h_queries.end(), rand_func);
// 2. Move data to GPU
rmm::device_uvector<float> d_dataset(n_rows * dim, res.get_stream());
rmm::device_uvector<float> d_queries(n_queries * dim, res.get_stream());
raft::update_device(d_dataset.data(), h_dataset.data(), h_dataset.size(), res.get_stream());
raft::update_device(d_queries.data(), h_queries.data(), h_queries.size(), res.get_stream());
// 3. Setup views and Search
auto dataset_view = raft::make_device_matrix_view<const float, int64_t>(d_dataset.data(), n_rows, dim);
auto queries_view = raft::make_device_matrix_view<float, int64_t>(d_queries.data(), n_queries, dim);
rmm::device_uvector<int64_t> d_indices(n_queries * k, res.get_stream());
rmm::device_uvector<float> d_distances(n_queries * k, res.get_stream());
auto out_idx_view = raft::make_device_matrix_view<int64_t, int64_t>(d_indices.data(), n_queries, k);
auto out_dist_view = raft::make_device_matrix_view<float, int64_t>(d_distances.data(), n_queries, k);
brute_force::index_params idx_p;
idx_p.metric = cuvs::distance::DistanceType::L2Expanded;
auto index = brute_force::build(res, idx_p, dataset_view);
brute_force::search(res, brute_force::search_params{}, index, queries_view, out_idx_view, out_dist_view);
// 4. Copy results back to CPU to print
std::vector<int64_t> h_indices(n_queries * k);
std::vector<float> h_distances(n_queries * k);
raft::update_host(h_indices.data(), d_indices.data(), d_indices.size(), res.get_stream());
raft::update_host(h_distances.data(), d_distances.data(), d_distances.size(), res.get_stream());
res.sync_stream();
// 5. Print results
for (int i = 0; i < n_queries; ++i) {
std::cout << "Query " << i << ":\n";
for (int j = 0; j < k; ++j) {
std::cout << " Neighbor " << j << ": Index " << h_indices[i * k + j]
<< ", Distance " << h_distances[i * k + j] << "\n";
}
}
return 0;
}
如果需要在曦云系列GPU上编译并运行上述示例,需要使用mxcc进行编译。
$ export CUDA_PATH=$MACA_PATH/tools/cu-bridge
$ export PY_SITE_PKG=<path/to/site_pakages>
$ mxcc -o brute_force_example brute_force_example.cu \
-std=c++17 \
-DLIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE \
-I${CUDA_PATH}/include/cccl \
-I${CUDA_PATH}/include \
-I${MACA_PATH}/tools/cu-bridge/include \
-I${MACA_PATH}/include/mcblas \
-I${MACA_PATH}/include/mcsolver \
-I${MACA_PATH}/include/mcsparse \
-I${PY_SITE_PKG}/libcuvs/include \
-I${PY_SITE_PKG}/libraft/include \
-I${PY_SITE_PKG}/librmm/include \
-L${PY_SITE_PKG}/libcuvs/lib \
-L${PY_SITE_PKG}/librmm/lib \
-lcuvs -lrmm -lruntime_cu
编译成功后,运行 brute_force_example 程序,可以得到如下的输出:
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PY_SITE_PKG/libcuvs/lib:$LD_LIBRARY_PATH:$PY_SITE_PKG/librmm/lib ./ brute_force_example
Query 0:
Neighbor 0: Index 2, Distance 0.213012
Neighbor 1: Index 8, Distance 0.289476
Neighbor 2: Index 6, Distance 0.346261
Query 1:
Neighbor 0: Index 7, Distance 0.193986
Neighbor 1: Index 8, Distance 0.207296
Neighbor 2: Index 2, Distance 0.359122
2.4.3. 代码示例(Python)
使用Python进行IVFFlat索引完成向量添加、搜索,代码示例如下:
import cupy as cp
import numpy as np
from cuvs.neighbors import ivf_flat
d = 4
nb = 100
nq = 10
topk = 3
xb = cp.asarray(np.random.rand(nb, d).astype(np.float32))
xq = cp.asarray(np.random.rand(nq, d).astype(np.float32))
build_params = ivf_flat.IndexParams(n_lists=2)
index = ivf_flat.build(build_params, xb)
search_params = ivf_flat.SearchParams(n_probes=2)
distances, neighbors = ivf_flat.search(
search_params,
index,
xq,
topk
)
neighbors_cpu = cp.asnumpy(neighbors)
for i in range(nq):
print(f"query {i}: {neighbors_cpu[i]}")
使用Python来运行上述脚本,可以得到类似如下的输出:
$ python example.py
query 0: [30 1 81]
query 1: [14 0 52]
query 2: [69 22 14]
query 3: [43 25 8]
query 4: [31 79 83]
query 5: [65 55 84]
query 6: [59 0 99]
query 7: [12 90 68]
query 8: [53 60 73]
query 9: [94 4 73]
2.5. 已知问题
向量搜索的召回率在不同环境有差异是正常现象, 因为浮点数计算不满足结合律
BruteForce 索引类型的 filter 功能在部分场景下结果不正确,原因是依赖的cusparse接口还在完善中