快速入门
本章节提供了一个简单的样例,帮助用户快速体验运用mxIndex进行检索的流程。
假定有业务需要使用到暴搜(Flat)算法,底库大小为100w,维度是512维,需要检索的向量是128个,topk是10,编写一个Demo调用Index接口大致步骤如下:
- 已完成mxIndex的安装部署。
安装部署完成后,再检查以下环境变量是否都配置完成;根据个人安装目录不同,环境变量路径不同,以下为默认安装路径配置的环境变量:
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/work/FeatureRetrieval/mxIndex/host/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/faiss/faiss1.7.1/lib/:$LD_LIBRARY_PATH
export MX_INDEX_MODELPATH=/home/work/FeatureRetrieval/mxIndex/modelpath/
source /usr/local/Ascend/ascend-toolkit/set_env.sh
- 生成Flat和AICPU算子。
- 按照如下方法生成Flat算子:
用法
python3 flat_generate_model.py -d <dim> --cores <core_num> -p <process_id> -pool <pool_size> -t <npu_type>
参数名称
<dim>:特征向量维度D。
<core_num>:昇腾AI处理器AI Core的个数,默认值为“2”。不指定该值时,根据<npu_type>配置:当npu_type配置为310时,<core_num>配置为2;当npu_type配置为310P时,<core_num>配置为8。
<process_id>:批量生成算子多进程调度的进程ID,默认值为“0”,无需设置。
<pool_size>:批量生成算子多进程调度的进程池大小,默认值为“10”。
<npu_type>:硬件形态,当前<npu_type>支持Atlas 200/300/500 推理产品以及Atlas 推理系列产品,取值范围分别为:310、310P,默认为“310”。
说明
执行此命令,用户可以得到一组距离计算算子模型文件,用户需要自行修改命令中参数。
约束说明
- dim ∈ {32, 64, 128, 256, 384, 512, 1024, 2048}(2048只支持L2距离)
- 0 ≤ pool_size ≤ 32
- 按照如下方法生成AICPU算子:
用法
python3 aicpu_generate_model.py --cores <core_num> -p <process_id> -t <npu_type>
参数名称
<core_num>:昇腾AI处理器AI Core的个数,默认为“2”。(预留参数,暂不使用)
<process_id>:批量生成算子多进程调度的进程ID,默认值为“0”,无需设置。
<npu_type>:硬件形态,当前<npu_type>支持Atlas 200/300/500 推理产品以及Atlas 推理系列产品,取值范围分别为:310、310P,默认为“310”。
说明
执行此命令,用户可以得到一组算子模型文件。
AICPU算子模型文件只需生成一次,会全部生成所有算法的算子。
- 按照如下方法生成Flat算子:
- 构造demo,过程包括:
- Demo中引入暴搜(Flat)的头文件。
- 构造底库向量数据,这里用随机数生成代替。
- 归一化底库数据。
- 初始化Flat的Index。
- 调用接口添加底库。
- 调用接口进行检索。
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::Index::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
# XXX替换为环境上index组件的安装目录 g++ -std=c++11 -march=armv8-a -fopenmp -fPIE -fstack-protector-all -Wno-sign-compare -D_FORTIFY_SOURCE=2 -D_GLIBCXX_USE_CXX11_ABI=1 -O0 -Wall -DFINTEGER=int -fopenmp \ -o demo demo.cpp \ -I/home/XXX/mxIndex/include \ -I/usr/local/faiss/faiss1.7.1/include \ -I/usr/local/Ascend/driver/include \ -I/opt/OpenBLAS/include \ -L/home/XXX/mxIndex/host/lib \ -L/usr/local/faiss/faiss1.7.1/lib \ -L/usr/local/Ascend/driver/lib64 \ -L/usr/local/Ascend/driver/lib64/driver \ -L/opt/OpenBLAS/lib/include \ -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \ -lfaiss -lascendfaiss -lopenblas -lc_sec -lascendcl -lascend_hal
- 运行Demo,能看到search end!即表示Demo运行成功。
./demo ... search end!