# FeatureRetrieve **Repository Path**: wolfworld6/FeatureRetrieve ## Basic Information - **Project Name**: FeatureRetrieve - **Description**: No description available - **Primary Language**: C++ - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-03-25 - **Last Updated**: 2024-06-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [EN](README.en.md)|CN ## 长特征检索demo 该长特征检索Demo主要运行于Atlas 500和Atlas 300产品。主要是根据人脸检测模型提取的长特征与用户数十万或百万底库特征进行计算相似度,然后对内积结果进行排序,选取出相似度最高的Top K个结果。Demo包含以下主要的功能:检索功能、特征底库更新/修改功能、底库保存功能。本文主要介绍Demo运行所依赖的环境配置和流程。 [TOC] ### 支持的产品 Atlas 300 (Model 3010),Atlas 300 (Model 3000),Atlas 500 ### 支持的版本 1.32.T5.B050 Atlas 300 (Model 3010)和Atlas 500版本获取可以通过以下命令: ```shell npu-smi info ``` 或者在相应的驱动安装路径下获取版本信息。 ### 运行环境 Ubuntu X86 16.04、Ubuntu ARM 18.04或Atlas500 ### 目录结构 本demo源代码的目录结构如下: ```shell ├── src │   ├── cc_rule.mk │   ├── inc │   │   ├── common.h │   │   ├── data_sear.h │   │   ├── dest_engine.h │   │   ├── error_code.h │   │   ├── inference_engine.h │   │   ├── parse_config.h │   │   ├── retrieve_query.h │   │   ├── retrieve_save_base.h │   │   └── retrieve_update_base.h │   ├── main.cpp │   ├── Makefile_device │   ├── Makefile_main │   ├── out │   │   └── test_data │   │   ├── config │   │   │   ├── graph.config │   │   │   └── setup.config │   │   ├── data │   │   └── model │   ├── shmake.sh │   ├── src │   │   ├── data_sear.cpp │   │   ├── dest_engine.cpp │   │   ├── inference_engine.cpp │   │   ├── parse_config.cpp │   │   ├── retrieve_query.cpp │   │   ├── retrieve_save_base.cpp │   │   └── retrieve_update_base.cpp │   └── tools │   ├── creat_model.py │   ├── env_te │   └── fc_feature_retrieve.prototxt ├── README.en.md ├── README.zh.md ``` 文件夹、路径和重要文件说明: (1)src:所有源文件位于src目录。 (2)out:可执行文件和依赖库、依赖文件的目录。 (3)inc:函数声明和参数宏定义等。 (4)tools:存放将用户特征转换为om文件的脚本工具。 (5)out/test_data/config:文件夹下包含graph配置文件和用户参数配置文件。 (6)out/test_data/data:输入特征向量数据。 (7)out/test_data/model:存放用户特征底库om文件。 (8)main.cpp:长特征检索Demo检索、权值更新、底库保存等接口调用等。 (9)shmake.sh、Makefile_device、Makefile_main、cc_rule.mk:编译makefile文件和脚本。 ### 环境依赖 (1)caffe 底库生成依赖caffe环境,请参考caffe开源工程进行编译和安装pycaffe,并确保环境变量配置正确: ```shell export PYTHONPATH=/home/caffe/python ``` ### 环境配置 #### Atlas 300 (Model 3010) 系统环境变量$DDK_HOME的路径为ddk的安装目录。代码默认是在Atlas 300上且系统环境为Ubuntu X86 16.04上编译和执行的,用户需要修改./tools/env_te文件中DDK_HOME环境变量为DDK的安装路径,也可以自行修改makefile文件。 ```SHELL export DDK_HOME=/DDK/SETUP/PATH/ddk/ ``` 修改完成后执行以下命令使环境变量生效: ```shell source tools/env_te ``` #### Atlas 300 (Model 3000) 配置方法基本同Atlas 300 (Model 3010),需要修改DDK_HOME为ddk的安装目录。 #### Atlas 500 如果用户环境是Atlas 500,请先进行如下操作: * 配置环境变量 打开env_te文件,进行以下修改,$HOST_PATH是用户交叉编译环境的路径。 ```shell export DDK_HOME=/ATLAS500/DDK/SETUP/PAH/ddk/ export HOST_PATH=/home/ddkuser/Euler_compile_env/Euler_compile_env_cross export PATH=$DDK_HOME/toolchains/ccec-linux/bin:$PATH export LD_LIBRARY_PATH=$DDK_HOME/lib/x86_64-linux-gcc5.4:$LD_LIBRARY_PATH export TVM_AICPU_LIBRARY_PATH=$DDK_HOME/lib/x86_64-linux-gcc5.4/:$DDK_HOME/toolchains/ccec-linux/aicpu_lib export TVM_AICPU_INCLUDE_PATH=$DDK_HOME/include/inc/tensor_engine export PYTHONPATH=$DDK_HOME/site-packages/:$PYTHONPATH export TVM_AICPU_OS_SYSROOT=$DDK_HOME/toolchains/aarch64-linux-gcc6.3/sysroot export NPU_HOST_LIB=$DDK_HOME/lib64 export NPU_DEVICE_LIB=$DDK_HOME/device/lib export PATH=/usr/local/HiAI/driver/lib64:$PATH export LD_LIBRARY_PATH=$DDK_HOME/EP/host-x86_64_ubuntu16.04/lib/:$LD_LIBRARY_PATH ``` 修改完成后执行以下命令使环境变量生效: ```shell source tools/env_te ``` * 修改`./cc_rule.mk`文件 ```makefile ifeq ($(CC_PATTERN),Atlas) CPP := /usr/bin/aarch64-linux-gnu-g++ else ifeq ($(CC_SIDE), host) # 替换成交叉编译环境下的g++编译器,替换结果如下 CPP := ${HOST_PATH}/arm/cross_compile/install/bin/aarch64-linux-gnu-g++ else CPP := $(DDK_HOME)/toolchains/aarch64-linux-gcc6.3/bin/aarch64-linux-gnu-g++ endif endif ``` ### 使用方法 #### 1.特征检索 (1)生成底库权值文件: 修改产生单算子模型的脚本文件creat_model.py,进行检索特征维度、并发数和底库特征维度等配置。具体配置项如下: | 配置项 | 类型 | 说明 | | -------------- | ------ | ------------------------------------------------ | | batch | 整数 | 单次检索并发数,必选配置 | | dims | 整数 | 特征向量的维度,必选配置 | | base_num | 整数 | 特征底库的大小,必选配置 | | caffemodel_dir | 字符串 | 单算子prototxt文件目录,必选配置 | | gen_type | 字符串 | 配置为生成固定值测试数据或者采用特征库数据,必选配置。'const':生成固定值特征向量和底库;'random':生成随机特征向量和底库;'database':加载用户指定的数据库和检索向量,生成用户指定的特征向量和底库| | l2_enable | bool | L2归一化使能配置,默认配置为False,如果用户没有进行过归一化处理,则需要开启使能配置 | | layer_name | 字符串 | 单算子layer名称,默认为‘fc_layer' | | out_blob | 字符串 | 输出数据blob名称,默认为'ouput' | | query_data_save_path | 字符串 | 保存检索特征向量的路径 | | weight_save_path | 字符串 | 保存om模型文件的路径 | | usr_base_data_dir | 字符串 | 用户检索特征库目录,默认为空,如果用户需要使用自己提供的特征库生成模型,需要指定文件路径 | | usr_query_data_dir | 字符串 | 用户检索特征向量目录,默认为空,如果用户需要使用自己提供的检索特征向量,需要指定文件路径 | creat_model.py首先把特征底库数据写入到caffemodel的params中,然后把检索向量换成二进制文件,最后根据单算子网络文件prototxt和权值文件caffemodel进行模型转换,生成om模型文件。用户需要把生成的om文件拷贝至src/out/test_data/model文件夹下,把bin文件放在src/out/test_data/data文件夹下。用户可根据需求修改该文件。 (2)修改参数配置文件src/out/test_data/config/setup.config,包括底库大小、并发数、特征维度等。 | 字段 | 类型 | 说明 | | ----------------------- | ------ | ------------------------------------------------------------ | | input_data_file | 字符串 | 输入检索特征向量数据文件,需要注意的是:如果用户单次检索特征条数小于模型batch时,分配的输入数据内存大小也要为模型的输入batch * dim * 4字节。 | | output_data_file | 字符串 | 推理结果,host侧进行结果保存 | | graph_config_proto_file | 字符串 | Graph配置文件 | | graph_model_file | 字符串 | 推理的模型文件(底库特征向量) | | dim_num | 数字 | 特征向量维度,设置值可选256和512 | | fc_lib_num | 数字 | 底库特征条数,若特征向量维度为256,底库特征条数范围为1万到200万;若特征向量维度为512,底库特征条数范围为1万到100万 | | batch_num | 数字 | 特征检索并发数目,支持1,2,4,8,16,32这6种并发数 | | topk_num | 数字 | TopK设置值,取值范围[0, 5000] | (3)修改out/test_data/config文件下graph配置文件graph.config,配置正确的模型。 | 字段 | 类型 | 说明 | | ---------- | ------ | ------------------------------ | | model_path | 字符串 | 推理的模型文件(底库特征向量) | | topk_value | 数字 | TopK设置值,取值范围[0, 5000] | (4)执行编译 由于安全限制,执行本demo的Linux用户必须属于HwHiAiUser组。运行前,请确保当前用户已切换到HwHiAiUser组。执行以下命令进行编译,进入编译时自动进入out目录,并带参数执行编译结果可执行文件,结果会保存在 `out` 目录下 ```shell cd src/ sh ./shmake.sh ``` (5)文件拷贝 topk排序采用openmp进行多线程处理,所以需要把ddk安装目录下的线程库文件libgomp.so拷贝至out目录下。 ```shell cp $DDK_HOME/toolchains/aarch64-linux-gcc6.3/sysroot/usr/lib64/libgomp.so ./out ``` (6)运行可执行文件 进入 `out` 文件夹下运行可执行程序,指令格式为: ``` ./FeatureRetrieve [-c ] [用户参数配置文件] [-d] [设备的device_id] ``` 如果是Atlas500环境,用户需要从交叉编译环境中把编译结果的out文件夹拷贝到Atlas 500环境中。 具体如下所示: ```shell ./FeatureRetrieve -c test_data/config/setup.config -d 0 # test_data 文件夹下生成 matrix__test_result ``` (7)检验结果。 查看src/out/test_data/matrix_test_data文件,检验结果是否正确,结果文件中包含的是循环16次检索的结果,每次检索输出batchsize*topk个结果。Topk排序后结果,最下面的最大值表示相似度最高,如下所示为Top10结果排列。matrix_test_data在demo中默认是追加方式打开保存的。 > id:53 distance: 0.8712 > id:221 distance: 1.2341 > id:215 distance: 1.6122 > id:561 distance: 2.1023 > id:12 distance: 2.23741 > id:128 distance: 2.25781 > id:24 distance: 2.3781 > id:18 distance: 2.54723 > id:61 distance: 2.73730 > id:41 distance: 2.75781 #### 2.底库更新 主程序中调用RetrieveUpdateBase接口,并完成以下流程。 (1)读取准备更新到底库中的特征数据。 (2)绑定初始化graph。 (3)输入的特征数据指针绑定。 (4)配置底库更新条数与是否DMalloc预分配内存。 | 字段 | 类型 | 说明 | | ---------- | ---- | ------------------------------------------------------------ | | graph | 指针 | 初始化graph句柄指针 | | inFeature | 指针 | 输入的特征数据 | | inFeatNum | 整型 | 更新到底库中的特征条数 | | isDMalloc | bool | 是否DMalloc预分配内存,默认为False | | baseBuffer | 指针 | 转换后的特征数据在内存中的地址,主要作用是供底库保存模块读取转换后的底库特征数据,进而把特征固化保存在om文件中 | #### 3.底库保存 主程序中调用RetrieveSaveBase接口,并完成以下输入参数配置。 (1)指定要保存的om文件目录。 (2)把底库更新的baseBuffer指针与updateFeature指针绑定。 (3)配置待更新的权值个数,要与RetrieveUpdateBase接口的inFeatNum一致。 (4)配置特征向量的维度。 | 字段 | 类型 | 说明 | | ------------- | ------ | ------------------------------------------------------------ | | modelPath | 字符串 | 保存的om文件目录,Demo中配置的是setup.config中graph_model_file字段 | | updateFeature | 指针 | 权值更新中与发送接口绑定的数据文件指针 | | inFeatureNum | 整型 | 待更新的权值个数 | | inFeatureDim | 整型 | 特征向量的维度 | 注意:底库保存必须在底库更新之后同步调用,以保证设备端特征库与本地同步。 ### FAQ 本demo主要是为用户提供基于Atlas产品相关软件接口使用实例和方法,相关接口调用和功能实例仅供用户参考,demo使用过程中可能会出现以下问题,需知悉。 1. 执行编译时目标文件没有进行clean,所以如果生成相关目标文件需要用户手动clean,删除out目录下相关编译目标文件。 2. 本demo中底库更新和保存涉及内存拷贝相关操作,如果底库更新和保存过程中数据偏移超过底库数据大小,可能会导致系统挂死现象。 3. 异常中断、掉电等程序会异常退出,请等待device端进程退出后重新启动。异常中断可能会导致底库保存失败,需要用户重新更新底库文件。 4. 如果用户输入数据错误或其他异常导致无法输出检索结果,系统会等待一个超时时间MAX_SLEEP_TIMER,期间终端打印信息如下,超时后程序会退出。 ```shell Wait for inference... Wait for inference... Wait for inference... Wait for inference... ``` 5. 本demo目前仅支持用户每次检索输入数据和om模型输入一致的数据大小,检索数据维度是否与模型一致系统无法校验,所以需要用户来保证。 6. 多次检索间隔约0.5ms左右使结果同步到host端;底库更新每次最多支持32条特征更新。 7. 系统告警信息会打印在终端或/var/dlog/日志中,如果使用过程发现异常,可根据相关告警提示定位。