IndexILFlat

IndexILFlat is a retrieval solution only used on the device. It uses resources such as the Ascend AI Processor and AI Cores to enable each API. Programs need to be compiled on the host to generate binary files, and the binary files and related runtime dependencies are deployed on the device. For details about the deployment mode, see the following instructions. For details about the API restrictions, see IndexILFlat.

Sample Code

#include "IndexILFlat.h"

#include <iostream>
#include <numeric>
#include <vector>

#include "acl/acl.h"
#include "arm_fp16.h"

APP_ERROR TestComputeDistance(ascend::IndexILFlat& index, int queryN, int baseSize, float16_t* queryData)
{
std::vector<float> distances(queryN * baseSize);
auto ret = index.ComputeDistance(queryN, queryData, distances.data());
return ret;
}

APP_ERROR TestSearchByThreshold(ascend::IndexILFlat& index, int queryN, float16_t* queryData)
{
int topK = 10;
float threshold = 0.6;
std::vector<int> num(queryN);
std::vector<float> distances(queryN * topK);
std::vector<ascend::idx_t> idxs(queryN * topK);
auto ret = index.SearchByThreshold(queryN, queryData, topK, threshold,
num.data(), idxs.data(), distances.data());
return ret;
}

int main(int argc, char **argv)
{
// 0.1 Remember to set device first, please refer to CANN Application
// Software Development Guide (C&C++, Inference)
aclError aclSet = aclrtSetDevice(0);
if (aclSet) {
printf("Set device failed ,error code:%d\n", aclSet);
return 0;
}

// 0.2 construct index
const int dim = 512;
const int baseSize = 100000;
const int queryN = 64;
const int capacity = 100000;
const int resourceSize = -1;
auto metricType = ascend::AscendMetricType::ASCEND_METRIC_INNER_PRODUCT;
std::vector<float16_t> base(baseSize * dim);
std::vector<ascend::idx_t> ids(baseSize);

for (size_t j = 0; j < base.size(); j++) {
base[j] = drand48();
}
std::iota(ids.begin(), ids.end(), 0);

// 1. build Index and initialize
ascend::IndexILFlat indexFlat;
auto ret = indexFlat.Init(dim, capacity, metricType, resourceSize);
if (ret) {
printf("Index initialize failed ,error code:%d\n", ret);
return 0;
}

// 2. add base vectors
ret = indexFlat.AddFeatures(baseSize, base.data(), ids.data());
if (ret) {
printf("Add features failed ,error code:%d\n", ret);
return 0;
}

// 3.1 Test ComputeDistance
std::vector<float16_t> queries(queryN * dim);
for (size_t i = 0; i < queries.size(); i++) {
queries[i] = drand48();
}
ret = TestComputeDistance(indexFlat, queryN, baseSize, queries.data());
if (ret) {
printf("Compute distance failed ,error code:%d\n", ret);
return 0;
}

// 3.2 Test SearchByThreshold
ret = TestSearchByThreshold(indexFlat, queryN, queries.data());
if (ret) {
printf("Search by threshold failed ,error code:%d\n", ret);
return 0;
}

// 4. release resource
indexFlat.Finalize();
aclrtResetDevice(0);

printf("------------Demo correct--------------\n");
return 0;
}

Instructions

  1. Find the IndexILFlat release package in the installation directory after the mxIndex software package is installed.
    • Header file: mxIndex/device/include/IndexILFlat.h
    • Dynamic library: mxIndex/device/lib/libascendfaiss_minios.so
  2. Compile code using the CANN built-in HCC compiler and deploy the compiled code on the device by referring to File System Customization in the CANN Software Installation (Open Form, Atlas inference products). The HCC compiler is stored in /usr/local/Ascend/ascend-toolkit/latest/toolkit/toolchain/hcc/bin/aarch64-target-linux-gnu-g++.

    To copy dependencies to the device through the SSH service or run the test case on the device through SSH login, enable the SSH service by referring to Appendix > Enabling the SSH Service Using the DSMI API in the CANN Software Installation (Open Form, Atlas inference products) and remove the 50 MB memory usage limit of the SSH service. Otherwise, all dependency files cannot be sent and the test case cannot be executed.

  3. Generate the operator OM file.
    After the following commands are executed, operator files are generated in the mxIndex/modelpath directory on the host. The operators also need to be deployed on the device.
    cd mxIndex
    ./ops/custom*
    cd tools
    python3.7 flat_generate_model.py -d 512 --cores 8 -pool 16
    mv op_models/*.om ../modelpath
  4. Compile the test case code.
    Create the mxIndex/test directory in the mxIndex project, create the IndexILDemo.cpp source file in the test directory, and copy Sample Code. The compilation command is as follows:
    /usr/local/Ascend/ascend-toolkit/latest/toolkit/toolchain/hcc/bin/aarch64-target-linux-gnu-g++ -fPIC -fPIE -fstack-protector-all \
    -o IndexILDemo IndexILDemo.cpp \
    -fopenmp -O3 -frename-registers -fpeel-loops -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -pie -s \
    -I/usr/local/AscendMiniOs/acllib/include/ \
    -I../include \
    -I../device/include \
    -L../device/lib \
    -L/usr/local/AscendMiniOs/acllib/lib64/stub \
    -L/usr/local/Ascend/driver/lib64/common \
    -lascendcl -lascend_hal -lc_sec -lascendfaiss_minios
  5. Deploy dependencies.
    • In the same path as the executable binary file, configure modelpath to store the operator file generated in step 3.
    • To deploy CANN-related library dependency, deploy /usr/local/AscendMiniOs/aarch64-linux/lib64 on the device and add it to LD_LIBRARY_PATH.
    • Deploy the dynamic library (mxIndex/device/lib/libascendfaiss_minios.so) on the device and add it to LD_LIBRARY_PATH.