IndexILFlat

IndexILFlat is a retrieval solution only used on the device. It uses resources such as Ascend AI Processors 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"
int TestComputeDistance(ascend::IndexILFlat &index, int queryN, int baseSize, float16_t *queryData)
{
    int baseSizeAlign = (baseSize + 15) / 16 * 16;
    std::vector<float> distances(queryN * baseSizeAlign);
    auto ret = index.ComputeDistance(queryN, queryData, distances.data());
    return ret;
}
int 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, threshold, topK, 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 != 0) {
        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 != 0) {
        printf("Index initialize failed ,error code:%d\n", ret);
        aclrtResetDevice(0);
        return 0;
    }
    // 2. add base vectors
    ret = indexFlat.AddFeatures(baseSize, base.data(), ids.data());
    if (ret != 0) {
        printf("Add features failed ,error code:%d\n", ret);
        indexFlat.Finalize();
        aclrtResetDevice(0);
        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 != 0) {
        printf("Compute distance failed ,error code:%d\n", ret);
        indexFlat.Finalize();
        aclrtResetDevice(0);
        return 0;
    }
    // 3.2 Test SearchByThreshold
    ret = TestSearchByThreshold(indexFlat, queryN, queries.data());
    if (ret != 0) {
        printf("Search by threshold failed ,error code:%d\n", ret);
        indexFlat.Finalize();
        aclrtResetDevice(0);
        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 Index SDK package is installed.
    • Header file: mxIndex/device/include/IndexILFlat.h
    • Dynamic library: mxIndex/device/lib/libascendfaiss_minios.so
  2. Compile code using the CANN's built-in HCC and deploy the compiled code on the device by referring to "File System Customization" in CANN Software Installation Guide (Open Form, Atlas Inference Products). The HCC 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, remove the 50 MB memory usage limit of the SSH service by referring to "Enabling the SSH Service Using the DSMI API" in CANN Software Installation Guide (Open Form, Atlas Inference Products). Otherwise, not all dependency files can 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.
    1
    2
    3
    4
    5
    cd mxIndex
    ./ops/custom*
    cd tools
    python3.7 flat_generate_model.py -d 512 --cores 8 -pool 16 -t 310P
    mv op_models/*.om ../modelpath
    
  4. Compile the test case code.
    Create the mxIndex/test directory in the Index SDK project, create the IndexILDemo.cpp source file in the test directory, and copy Sample Code. The compile command is as follows:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    /usr/local/Ascend/ascend-toolkit/latest/toolkit/toolchain/hcc/bin/aarch64-target-linux-gnu-g++ -fPIC -fPIE -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 \ 
    -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.