快速入门
- 本教程以 Flat 索引类型为例,帮助您通过 Docker 容器快速掌握 Index SDK 的基本使用方法。
- 当前步骤1和步骤2默认是在物理机上执行,如果已经在容器中且未装相关依赖,可根据对应操作系统参考一键安装脚本进行依赖安装openEuler 脚本、Ubuntu 脚本,然后跳到步骤3继续执行。
前置条件
开始之前请确认:
- 硬件:支持 Atlas 推理系列产品、Atlas 800I A2、Atlas 800I A3。可参见“支持的硬件和操作系统”。
- Docker:已安装并正确配置 Docker 环境,且当前用户可运行容器。
- Ascend 驱动:已安装并配置好 Ascend 驱动。
步骤 1:拉取镜像
1.1 选择匹配版本
- 根据当前硬件型号选择对应的镜像版本,注意区分昇腾芯片型号。
- 根据芯片型号选择对应的镜像拉取命令:
对于 Atlas 推理系列产品,可在安装昇腾 AI 处理器的服务器执行 npu-smi info 命令进行查询,将查询到的"Name"最后一位数字删除,即是npu_type的取值
对于 Atlas 800I A2 推理服务器,可在安装昇腾 AI 处理器的服务器执行 npu-smi info 命令进行查询,查询到的"Name"即是npu_type的取值。
对于 Atlas 800I A3 超节点服务器,可以通过 npu-smi info -t board -i 0 -c 0 命令进行查询,获取NPU Name信息,910_NPU Name即是npu_type的取值。
| 服务器型号 | 拉取命令 |
|---|---|
| Atlas 推理系列产品 | docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/indexsdk:26.1.0-cann9.1.0-310p-ubuntu22.04-py3.12 |
| Atlas 800I A3 | docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/indexsdk:26.1.0-cann9.1.0-a3-ubuntu22.04-py3.12 |
| Atlas 800I A2 | docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/indexsdk:26.1.0-cann9.1.0-910b-ubuntu22.04-py3.12 |
1.2 环境预检查
- 使用
npu-smi info命令验证 NPU 驱动状态。 - 检查驱动版本与镜像 CANN 版本匹配性(参考《固件与驱动》文档),如果和当前环境安装的驱动版本不配套,请更新NPU驱动至对应版本,NPU驱动更新指导详见《驱动和固件安装指南》。
步骤 2:运行容器
2.1 手动挂载设备
-
设备挂载:通过--device参数将宿主机的设备文件映射到容器中,确保容器能够访问指定的硬件资源。/dev/davinci为NPU加速卡(按需挂载),/dev/davinci_manager, /dev/devmm_svm, /dev/hisi_hdc为NPU管理设备(全部挂载)。
-
驱动与工具链挂载:将宿主机上的驱动文件和工具链目录(如 /usr/local/Ascend/driver 和 /usr/local/bin/npu-smi)以只读方式挂载到容器中,保证容器内的运行环境与宿主机一致。以下样例代码中,/dev/davinci0 表示挂载0号设备。
-
说明:-ti 后接对应的镜像标签,例如:-it swr.cn-south-1.myhuaweicloud.com/ascendhub/indexsdk:26.1.0-cann9.1.0-910b-ubuntu22.04-py3.12
docker run \
--name index_container \
--device /dev/davinci0 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-it swr.cn-south-1.myhuaweicloud.com/ascendhub/indexsdk:26.1.0-cann9.1.0-910b-ubuntu22.04-py3.12 bash
2.2 容器中执行npu-smi info命令检查驱动是否挂载正常
npu-smi info #正常显示npu卡信息无报错
步骤 3:算子生成
如果是容器环境通过一键安装脚本安装依赖请先执行:
source /etc/profile
- 生成 512 维 flat 算子:
cd /usr/local/Ascend/mxIndex/ops && ./custom_opp_*.run
cd /usr/local/Ascend/mxIndex/tools
python3 aicpu_generate_model.py -t <npu_type>
python3 flat_generate_model.py -d 512 -t <npu_type>
# 以 Atlas 800I A2 服务器上,910B4 为例:
# python3 aicpu_generate_model.py -t 910B4
# python3 flat_generate_model.py -d 512 -t 910B4
# MX_INDEX_MODELPATH 为存放算子的路径,当前以/home/Ascend/modelpath为例
export MX_INDEX_MODELPATH=/home/Ascend/modelpath
mkdir -p ${MX_INDEX_MODELPATH}
# 将算子模型移动到MX_INDEX_MODELPATH目录
mv op_models/* $MX_INDEX_MODELPATH
步骤 4:用例测试
-
使用 Flat 算法进行示例测试:底库大小 100 万条,特征维度 512 维,检索向量数 128 个,TopK 为 10。创建 demo.cpp 文件,内容如下:
#include <faiss/ascend/AscendIndexFlat.h> #include <sys/time.h> #include <random> // 获取当前时间 inline double GetMillisecs() { struct timeval tv = {0, 0}; gettimeofday(&tv, nullptr); return tv.tv_sec * 1e3 + tv.tv_usec * 1e-3; } // 使用随机数构造底库数据 void Generate(size_t ntotal, std::vector<float> &data, int seed = 5678) { std::default_random_engine e(seed); std::uniform_real_distribution<float> rCode(0.0f, 1.0f); data.resize(ntotal); for (size_t i = 0; i < ntotal; ++i) { data[i] = static_cast<float>(255 * rCode(e) - 128); } } // 底库数据归一化 void Norm(size_t total, std::vector<float> &data, int dim) { for (size_t i = 0; i < total; ++i) { float mod = 0; for (int j = 0; j < dim; ++j) { mod += data[i * dim + j] * data[i * dim + j]; } mod = sqrt(mod); for (int j = 0; j < dim; ++j) { data[i * dim + j] = data[i * dim + j] / mod; } } } int main() { int dim = 512; std::vector<int> device{0}; size_t ntotal = 1000000; int searchnum = 128; std::vector<float> features(dim * ntotal); int64_t resourceSize = static_cast<int64_t>(1024) * 1024 * 1024; int topK = 10; printf("Generating random numbers start!\r\n"); Generate(ntotal, features); Norm(ntotal, features, dim); try { // index初始化 faiss::ascend::AscendIndexFlatConfig conf(device, resourceSize); auto metricType = faiss::METRIC_INNER_PRODUCT; faiss::ascend::AscendIndexFlat index(dim, metricType, conf); index.reset(); // add底库 printf("add start!\r\n"); index.add(ntotal, features.data()); size_t tmpTotal = index.getBaseSize(0); if (tmpTotal != ntotal) { printf("------- Error -----------------\n"); return -1; } // search printf("search start!\r\n"); int loopTimes = 1; std::vector<float> dist(searchnum * topK, 0); std::vector<faiss::idx_t> label(searchnum * topK, 0); auto ts = GetMillisecs(); for (int i = 0; i < loopTimes; i++) { index.search(searchnum, features.data(), topK, dist.data(), label.data()); } auto te = GetMillisecs(); printf("search end!\r\n"); printf("flat, base:%lu, dim:%d, searchnum:%d, topk:%d, duration:%.3lf, QPS:%.4f\n", ntotal, dim, searchnum, topK, te - ts, 1000 * searchnum * loopTimes / (te - ts)); return 0; } catch(...) { printf("Exception caught! \r\n"); return -1; } } -
编译 demo.cpp:
export MX_INDEX_INSTALL_PATH=/usr/local/Ascend/mxIndex export ASCEND_HOME_PATH=/usr/local/Ascend/cann g++ --std=c++11 -fPIC -fPIE -fstack-protector-all -Wall -D_FORTIFY_SOURCE=2 -O3 -Wl,-z,relro,-z,now,-z,noexecstack -s -pie \ -o demo demo.cpp \ -I$MX_INDEX_INSTALL_PATH/include \ -I/usr/local/faiss/include \ -I/usr/local/Ascend/driver/include \ -I/opt/OpenBLAS/include \ -L$MX_INDEX_INSTALL_PATH/host/lib \ -L/usr/local/faiss/lib \ -L/usr/local/Ascend/driver/lib64 \ -L/usr/local/Ascend/driver/lib64/driver \ -L/opt/OpenBLAS/lib \ -L$ASCEND_HOME_PATH/lib64 \ -lfaiss -lascendfaiss -lopenblas -lc_sec -lascendcl -lascend_hal -lascendsearch -lock_hmm -
运行 demo:
./demo # 出现以下信息,说明运行成功 ... search end!