From 428840178cc248c38400a46a8e7e25a64864596c Mon Sep 17 00:00:00 2001 From: xige-16 Date: Wed, 21 Sep 2022 20:16:51 +0800 Subject: [PATCH] Support diskann index for vector field (#19093) Signed-off-by: xige-16 Signed-off-by: xige-16 --- .github/workflows/code-checker.yaml | 3 +- build/docker/milvus/ubuntu18.04/Dockerfile | 2 +- build/docker/milvus/ubuntu20.04/Dockerfile | 5 +- configs/milvus.yaml | 4 + docker-compose.yml | 1 + internal/core/CMakeLists.txt | 4 + internal/core/build.sh | 189 +++++++ internal/core/src/common/CDataType.h | 4 - internal/core/src/common/CMakeLists.txt | 9 +- internal/core/src/common/Consts.h | 4 + internal/core/src/common/LoadInfo.h | 7 - internal/core/src/common/QueryInfo.h | 34 ++ internal/core/src/common/Types.h | 17 +- internal/core/src/common/Utils.h | 35 ++ .../{vector_index_c.cpp => binary_set_c.cpp} | 2 +- .../{vector_index_c.h => binary_set_c.h} | 0 internal/core/src/common/init_c.cpp | 66 +++ internal/core/src/common/init_c.h | 51 ++ .../core/src/config/ConfigChunkManager.cpp | 56 ++- internal/core/src/config/ConfigChunkManager.h | 16 +- internal/core/src/index/BoolIndex.h | 39 +- internal/core/src/index/CMakeLists.txt | 22 +- internal/core/src/index/Index.h | 58 ++- internal/core/src/index/IndexFactory-inl.h | 38 +- internal/core/src/index/IndexFactory.cpp | 118 +++-- internal/core/src/index/IndexFactory.h | 50 +- internal/core/src/index/IndexInfo.h | 51 ++ internal/core/src/index/IndexStructure.h | 23 +- internal/core/src/index/IndexType.h | 16 - internal/core/src/index/Meta.h | 70 ++- internal/core/src/index/ScalarIndex-inl.h | 87 +++- internal/core/src/index/ScalarIndex.h | 40 +- internal/core/src/index/ScalarIndexSort-inl.h | 54 +- internal/core/src/index/ScalarIndexSort.h | 48 +- internal/core/src/index/StringIndex.h | 43 +- internal/core/src/index/StringIndexMarisa.cpp | 25 +- internal/core/src/index/StringIndexMarisa.h | 28 +- internal/core/src/index/StringIndexSort.h | 43 +- internal/core/src/index/Utils.cpp | 205 ++++++++ internal/core/src/index/Utils.h | 124 ++++- internal/core/src/index/VectorDiskIndex.cpp | 263 ++++++++++ internal/core/src/index/VectorDiskIndex.h | 84 ++++ internal/core/src/index/VectorIndex.h | 85 ++++ internal/core/src/index/VectorMemIndex.cpp | 218 +++++++++ internal/core/src/index/VectorMemIndex.h | 68 +++ internal/core/src/index/milvus_index.pc.in | 9 + internal/core/src/indexbuilder/CMakeLists.txt | 4 - .../core/src/indexbuilder/IndexCreatorBase.h | 13 +- internal/core/src/indexbuilder/IndexFactory.h | 34 +- .../src/indexbuilder/ScalarIndexCreator.cpp | 40 +- .../src/indexbuilder/ScalarIndexCreator.h | 16 +- .../core/src/indexbuilder/VecIndexCreator.cpp | 334 ++----------- .../core/src/indexbuilder/VecIndexCreator.h | 91 +--- internal/core/src/indexbuilder/helper.h | 38 -- internal/core/src/indexbuilder/index_c.cpp | 143 +----- internal/core/src/indexbuilder/index_c.h | 39 +- internal/core/src/indexbuilder/utils.cpp | 83 ---- internal/core/src/indexbuilder/utils.h | 54 -- internal/core/src/query/CMakeLists.txt | 2 +- internal/core/src/query/PlanNode.h | 11 +- internal/core/src/query/ScalarIndex.h | 10 +- internal/core/src/query/SearchOnGrowing.cpp | 12 +- internal/core/src/query/SearchOnGrowing.h | 2 +- internal/core/src/query/SearchOnIndex.cpp | 13 +- internal/core/src/query/SearchOnIndex.h | 6 +- internal/core/src/query/SearchOnSealed.cpp | 21 +- internal/core/src/query/SubSearchResult.h | 6 +- .../src/query/visitors/ExecExprVisitor.cpp | 16 +- .../query/visitors/VerifyPlanNodeVisitor.cpp | 10 +- internal/core/src/segcore/CMakeLists.txt | 2 - internal/core/src/segcore/FieldIndexing.cpp | 18 +- internal/core/src/segcore/FieldIndexing.h | 12 +- .../core/src/segcore/SealedIndexingRecord.h | 10 +- internal/core/src/segcore/SegcoreConfig.h | 6 +- .../core/src/segcore/SegmentGrowingImpl.cpp | 5 +- .../core/src/segcore/SegmentGrowingImpl.h | 4 +- internal/core/src/segcore/SegmentInterface.h | 10 +- internal/core/src/segcore/SegmentSealed.h | 2 +- .../core/src/segcore/SegmentSealedImpl.cpp | 49 +- internal/core/src/segcore/SegmentSealedImpl.h | 13 +- .../core/src/segcore/SimilarityCorelation.h | 4 +- internal/core/src/segcore/Utils.cpp | 18 +- internal/core/src/segcore/Utils.h | 4 +- internal/core/src/segcore/load_index_c.cpp | 161 ++++-- internal/core/src/segcore/load_index_c.h | 19 +- internal/core/src/segcore/segment_c.cpp | 3 +- internal/core/src/storage/CMakeLists.txt | 19 +- ...anagerImpl.cpp => DiskFileManagerImpl.cpp} | 36 +- ...ileManagerImpl.h => DiskFileManagerImpl.h} | 12 +- internal/core/src/storage/LocalChunkManager.h | 2 +- .../core/src/storage/MinioChunkManager.cpp | 22 +- internal/core/src/storage/MinioChunkManager.h | 5 +- internal/core/src/storage/Util.cpp | 41 +- internal/core/src/storage/Util.h | 17 +- internal/core/src/storage/storage_c.cpp | 41 ++ internal/core/src/storage/storage_c.h | 29 ++ internal/core/thirdparty/CMakeLists.txt | 6 +- .../core/thirdparty/knowhere/CMakeLists.txt | 11 +- internal/core/unittest/CMakeLists.txt | 15 +- .../unittest/bench/bench_indexbuilder.cpp | 13 +- internal/core/unittest/bench/bench_search.cpp | 4 +- internal/core/unittest/test_bitmap.cpp | 2 +- internal/core/unittest/test_bool_index.cpp | 74 +-- internal/core/unittest/test_c_api.cpp | 413 +++++++--------- ...st.cpp => test_disk_file_manager_test.cpp} | 15 +- internal/core/unittest/test_expr.cpp | 66 +-- internal/core/unittest/test_index_c_api.cpp | 1 - internal/core/unittest/test_index_wrapper.cpp | 378 ++------------ internal/core/unittest/test_indexing.cpp | 462 +++++++++++------- .../unittest/test_local_chunk_manager.cpp | 3 +- .../unittest/test_minio_chunk_manager.cpp | 16 + internal/core/unittest/test_scalar_index.cpp | 76 ++- .../unittest/test_scalar_index_creator.cpp | 9 +- internal/core/unittest/test_sealed.cpp | 208 ++++---- internal/core/unittest/test_segcore.cpp | 10 +- internal/core/unittest/test_string_index.cpp | 158 ++++-- .../core/unittest/test_utils/AssertUtils.h | 22 +- internal/core/unittest/test_utils/DataGen.h | 24 +- .../test_utils/indexbuilder_test_utils.h | 145 +++--- internal/indexcoord/index_coord.go | 1 + internal/indexnode/indexnode.go | 4 + internal/indexnode/task.go | 165 ++++++- internal/proto/index_coord.proto | 1 + internal/proto/indexpb/index_coord.pb.go | 265 +++++----- internal/proto/query_coord.proto | 1 + internal/proto/querypb/query_coord.pb.go | 449 ++++++++--------- internal/proxy/task.go | 8 +- internal/querycoord/global_meta_broker.go | 1 + internal/querycoord/util.go | 21 +- .../querycoordv2/meta/coordinator_broker.go | 1 + internal/querycoordv2/task/executor.go | 2 +- internal/querycoordv2/utils/types.go | 16 +- internal/querynode/cgo_helper.go | 16 +- internal/querynode/load_index_info.go | 66 ++- internal/querynode/load_index_info_test.go | 9 +- internal/querynode/query_node.go | 9 +- internal/querynode/segment.go | 7 +- internal/querynode/segment_loader.go | 175 +++++-- internal/querynode/task_test.go | 11 +- internal/util/constant.go | 5 + internal/util/funcutil/func.go | 18 +- internal/util/indexcgowrapper/helper.go | 25 +- internal/util/indexcgowrapper/index.go | 45 ++ internal/util/indexcgowrapper/index_test.go | 5 +- internal/util/indexparamcheck/conf_adapter.go | 36 ++ .../util/indexparamcheck/conf_adapter_mgr.go | 1 + internal/util/indexparamcheck/index_type.go | 1 + internal/util/initcore/init_storage_config.go | 70 +++ internal/util/paramtable/component_param.go | 95 +++- scripts/core_build.sh | 10 + 150 files changed, 4747 insertions(+), 2903 deletions(-) create mode 100755 internal/core/build.sh create mode 100644 internal/core/src/common/QueryInfo.h rename internal/core/src/common/{vector_index_c.cpp => binary_set_c.cpp} (99%) rename internal/core/src/common/{vector_index_c.h => binary_set_c.h} (100%) create mode 100644 internal/core/src/common/init_c.cpp create mode 100644 internal/core/src/common/init_c.h create mode 100644 internal/core/src/index/IndexInfo.h delete mode 100644 internal/core/src/index/IndexType.h create mode 100644 internal/core/src/index/Utils.cpp create mode 100644 internal/core/src/index/VectorDiskIndex.cpp create mode 100644 internal/core/src/index/VectorDiskIndex.h create mode 100644 internal/core/src/index/VectorIndex.h create mode 100644 internal/core/src/index/VectorMemIndex.cpp create mode 100644 internal/core/src/index/VectorMemIndex.h create mode 100644 internal/core/src/index/milvus_index.pc.in delete mode 100644 internal/core/src/indexbuilder/helper.h delete mode 100644 internal/core/src/indexbuilder/utils.cpp delete mode 100644 internal/core/src/indexbuilder/utils.h rename internal/core/src/storage/{DiskANNFileManagerImpl.cpp => DiskFileManagerImpl.cpp} (88%) rename internal/core/src/storage/{DiskANNFileManagerImpl.h => DiskFileManagerImpl.h} (87%) create mode 100644 internal/core/src/storage/storage_c.cpp create mode 100644 internal/core/src/storage/storage_c.h rename internal/core/unittest/{test_diskann_filemanager_test.cpp => test_disk_file_manager_test.cpp} (93%) create mode 100644 internal/util/initcore/init_storage_config.go diff --git a/.github/workflows/code-checker.yaml b/.github/workflows/code-checker.yaml index 285095ca8194f..be56392532504 100644 --- a/.github/workflows/code-checker.yaml +++ b/.github/workflows/code-checker.yaml @@ -59,7 +59,8 @@ jobs: restore-keys: ubuntu20.04-go-mod- - name: Code Check env: - CHECK_BUILDER: "1" +# CHECK_BUILDER: "1" + OS_NAME: "ubuntu20.04" run: | ./build/builder.sh /bin/bash -c "make check-proto-product && make verifiers" centos: diff --git a/build/docker/milvus/ubuntu18.04/Dockerfile b/build/docker/milvus/ubuntu18.04/Dockerfile index df5800cb70db6..484165704fa6c 100644 --- a/build/docker/milvus/ubuntu18.04/Dockerfile +++ b/build/docker/milvus/ubuntu18.04/Dockerfile @@ -15,7 +15,7 @@ FROM milvusdb/openblas:ubuntu18.04-20210428 AS openblas FROM ubuntu:bionic-20200921 RUN apt-get update && \ - apt-get install -y --no-install-recommends libtbb-dev libzstd-dev gfortran netcat iputils-ping ca-certificates && \ + apt-get install -y --no-install-recommends libtbb-dev libzstd-dev gfortran netcat iputils-ping ca-certificates uuid-dev libaio-dev libboost-program-options-dev && \ apt-get remove --purge -y && \ rm -rf /var/lib/apt/lists/* diff --git a/build/docker/milvus/ubuntu20.04/Dockerfile b/build/docker/milvus/ubuntu20.04/Dockerfile index 028931cf9398c..5a8e5802d03eb 100644 --- a/build/docker/milvus/ubuntu20.04/Dockerfile +++ b/build/docker/milvus/ubuntu20.04/Dockerfile @@ -14,8 +14,11 @@ FROM milvusdb/openblas:ubuntu20.04-20220914-179ea77 AS openblas #FROM alpine FROM ubuntu:focal-20220426 +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC + RUN apt-get update && \ - apt-get install -y --no-install-recommends libtbb-dev gfortran netcat iputils-ping ca-certificates liblapack3 && \ + apt-get install -y --no-install-recommends curl libtbb-dev gfortran netcat iputils-ping ca-certificates liblapack3 libzstd-dev uuid-dev libaio-dev libboost-program-options-dev libboost-filesystem-dev && \ apt-get remove --purge -y && \ rm -rf /var/lib/apt/lists/* diff --git a/configs/milvus.yaml b/configs/milvus.yaml index a92801e144648..acadb8e87c51f 100644 --- a/configs/milvus.yaml +++ b/configs/milvus.yaml @@ -193,6 +193,8 @@ queryNode: cacheSize: 32 # GB, default 32 GB, `cacheSize` is the memory used for caching data for faster query. The `cacheSize` must be less than system memory size. port: 21123 loadMemoryUsageFactor: 3 # The multiply factor of calculating the memory usage while loading segments + enableDisk: true # enable querynode load disk index, and search on disk index + maxDiskUsagePercentage: 95 stats: publishInterval: 1000 # Interval for querynode to report node information (milliseconds) @@ -238,6 +240,8 @@ indexCoord: indexNode: port: 21121 + enableDisk: true # enable index node build disk vector index + maxDiskUsagePercentage: 95 scheduler: buildParallel: 1 diff --git a/docker-compose.yml b/docker-compose.yml index b9f70c165223b..b66c9d3126a83 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,7 @@ services: # - "19530:19530" environment: <<: *ccache + OS_NAME: ${OS_NAME} PULSAR_ADDRESS: ${PULSAR_ADDRESS} ETCD_ENDPOINTS: ${ETCD_ENDPOINTS} MINIO_ADDRESS: ${MINIO_ADDRESS} diff --git a/internal/core/CMakeLists.txt b/internal/core/CMakeLists.txt index 37d8063c2004c..c3d87fc7f50de 100644 --- a/internal/core/CMakeLists.txt +++ b/internal/core/CMakeLists.txt @@ -234,6 +234,10 @@ if ( BUILD_UNIT_TEST STREQUAL "ON" AND BUILD_COVERAGE STREQUAL "ON" ) ) endif () +if ( BUILD_DISK_ANN STREQUAL "ON" ) + ADD_DEFINITIONS(-DBUILD_DISK_ANN=${BUILD_DISK_ANN}) +endif () + # Warning: add_subdirectory(src) must be after append_flags("-ftest-coverage"), # otherwise cpp code coverage tool will miss src folder add_subdirectory( thirdparty ) diff --git a/internal/core/build.sh b/internal/core/build.sh new file mode 100755 index 0000000000000..ec918b78a67f2 --- /dev/null +++ b/internal/core/build.sh @@ -0,0 +1,189 @@ +#!/bin/bash + +# Compile jobs variable; Usage: $ jobs=12 ./build.sh ... +if [[ ! ${jobs+1} ]]; then + if command -v nproc &> /dev/null + # For linux + then + jobs=$(nproc) + elif command -v sysctl &> /dev/null + # For macOS + then + jobs=$(sysctl -n hw.logicalcpu) + else + jobs=4 + fi +fi + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +SCRIPTS_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +BUILD_OUTPUT_DIR="./cmake_build" +BUILD_TYPE="Release" +BUILD_UNITTEST="OFF" +INSTALL_PREFIX="${SCRIPTS_DIR}/output" +MAKE_CLEAN="OFF" +BUILD_COVERAGE="OFF" +PROFILING="OFF" +RUN_CPPLINT="OFF" +CUDA_COMPILER=/usr/local/cuda/bin/nvcc +GPU_VERSION="OFF" #defaults to CPU version +WITH_PROMETHEUS="ON" +CUDA_ARCH="DEFAULT" +CUSTOM_THIRDPARTY_PATH="" +BUILD_DISK_ANN="OFF" + +while getopts "p:t:s:f:o:ulrcghzme" arg; do + case $arg in + f) + CUSTOM_THIRDPARTY_PATH=$OPTARG + ;; + p) + INSTALL_PREFIX=$OPTARG + ;; + o) + BUILD_OUTPUT_DIR=$OPTARG + ;; + t) + BUILD_TYPE=$OPTARG # BUILD_TYPE + ;; + u) + echo "Build and run unittest cases" + BUILD_UNITTEST="ON" + ;; + l) + RUN_CPPLINT="ON" + ;; + r) + if [[ -d ${BUILD_OUTPUT_DIR} ]]; then + MAKE_CLEAN="ON" + fi + ;; + c) + BUILD_COVERAGE="ON" + ;; + z) + PROFILING="ON" + ;; + g) + GPU_VERSION="ON" + ;; + e) + WITH_PROMETHEUS="OFF" + ;; + s) + CUDA_ARCH=$OPTARG + ;; + n) + BUILD_DISK_ANN="OFF" + ;; + h) # help + echo " +parameter: +-f: custom paths of thirdparty downloaded files(default: NULL) +-p: install prefix(default: $(pwd)/milvus) +-d: db data path(default: /tmp/milvus) +-t: build type(default: Debug) +-u: building unit test options(default: OFF) +-l: run cpplint, clang-format and clang-tidy(default: OFF) +-r: remove previous build directory(default: OFF) +-c: code coverage(default: OFF) +-z: profiling(default: OFF) +-g: build GPU version(default: OFF) +-e: build without prometheus(default: OFF) +-s: build with CUDA arch(default:DEFAULT), for example '-gencode=compute_61,code=sm_61;-gencode=compute_75,code=sm_75' +-h: help +usage: +./build.sh -p \${INSTALL_PREFIX} -t \${BUILD_TYPE} -s \${CUDA_ARCH} -f\${CUSTOM_THIRDPARTY_PATH} [-u] [-l] [-r] [-c] [-z] [-g] [-m] [-e] [-h] + " + exit 0 + ;; + ?) + echo "ERROR! unknown argument" + exit 1 + ;; + esac +done + +if [[ ! -d ${BUILD_OUTPUT_DIR} ]]; then + mkdir ${BUILD_OUTPUT_DIR} +fi + +cd ${BUILD_OUTPUT_DIR} + +# remove make cache since build.sh -l use default variables +# force update the variables each time +make rebuild_cache >/dev/null 2>&1 + + +if [[ ${MAKE_CLEAN} == "ON" ]]; then + echo "Runing make clean in ${BUILD_OUTPUT_DIR} ..." + make clean + exit 0 +fi + +unameOut="$(uname -s)" +case "${unameOut}" in + Darwin*) + llvm_prefix="$(brew --prefix llvm)" + export CLANG_TOOLS_PATH="${llvm_prefix}/bin" + export CC="${llvm_prefix}/bin/clang" + export CXX="${llvm_prefix}/bin/clang++" + export LDFLAGS="-L${llvm_prefix}/lib -L/usr/local/opt/libomp/lib" + export CXXFLAGS="-I${llvm_prefix}/include -I/usr/local/include -I/usr/local/opt/libomp/include" + ;; + *) echo "==System:${unameOut}"; +esac + +CMAKE_CMD="cmake \ +-DBUILD_UNIT_TEST=${BUILD_UNITTEST} \ +-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} +-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ +-DOpenBLAS_SOURCE=AUTO \ +-DCMAKE_CUDA_COMPILER=${CUDA_COMPILER} \ +-DBUILD_COVERAGE=${BUILD_COVERAGE} \ +-DENABLE_CPU_PROFILING=${PROFILING} \ +-DMILVUS_GPU_VERSION=${GPU_VERSION} \ +-DMILVUS_WITH_PROMETHEUS=${WITH_PROMETHEUS} \ +-DMILVUS_CUDA_ARCH=${CUDA_ARCH} \ +-DCUSTOM_THIRDPARTY_DOWNLOAD_PATH=${CUSTOM_THIRDPARTY_PATH} \ +-DKNOWHERE_GPU_VERSION=${SUPPORT_GPU} \ +-DBUILD_DISK_ANN=${BUILD_DISK_ANN} \ +${SCRIPTS_DIR}" +echo ${CMAKE_CMD} +${CMAKE_CMD} + + +if [[ ${RUN_CPPLINT} == "ON" ]]; then + # cpplint check + make lint + if [ $? -ne 0 ]; then + echo "ERROR! cpplint check failed" + exit 1 + fi + echo "cpplint check passed!" + + # clang-format check + make check-clang-format + if [ $? -ne 0 ]; then + echo "ERROR! clang-format check failed" + exit 1 + fi + echo "clang-format check passed!" + + # clang-tidy check + make check-clang-tidy + if [ $? -ne 0 ]; then + echo "ERROR! clang-tidy check failed" + exit 1 + fi + echo "clang-tidy check passed!" +else + # compile and build + make -j ${jobs} install || exit 1 +fi diff --git a/internal/core/src/common/CDataType.h b/internal/core/src/common/CDataType.h index a16f20447f47c..5d2c74ed1f9ad 100644 --- a/internal/core/src/common/CDataType.h +++ b/internal/core/src/common/CDataType.h @@ -15,10 +15,6 @@ #include namespace milvus { -inline bool -IsVectorType(CDataType dtype) { - return dtype == CDataType::FloatVector || dtype == CDataType::BinaryVector; -} template || std::is_same_v>> inline CDataType diff --git a/internal/core/src/common/CMakeLists.txt b/internal/core/src/common/CMakeLists.txt index 4d4b83ad2356d..af106c30e06ec 100644 --- a/internal/core/src/common/CMakeLists.txt +++ b/internal/core/src/common/CMakeLists.txt @@ -14,18 +14,16 @@ milvus_add_pkg_config("milvus_common") set(COMMON_SRC Schema.cpp SystemProperty.cpp - vector_index_c.cpp + binary_set_c.cpp + init_c.cpp ) add_library(milvus_common SHARED ${COMMON_SRC}) if ( MSYS ) target_link_libraries(milvus_common - milvus_utils milvus_config milvus_log - knowhere - milvus_proto yaml-cpp boost_bitset_ext arrow @@ -33,11 +31,8 @@ if ( MSYS ) ) else() target_link_libraries(milvus_common - milvus_utils milvus_config milvus_log - knowhere - milvus_proto yaml-cpp boost_bitset_ext arrow diff --git a/internal/core/src/common/Consts.h b/internal/core/src/common/Consts.h index effe5e59e6418..dd6033cffef66 100644 --- a/internal/core/src/common/Consts.h +++ b/internal/core/src/common/Consts.h @@ -26,6 +26,10 @@ const milvus::PkType INVALID_PK; // of std::monostate if not set. const int64_t START_USER_FIELDID = 100; const char MAX_LENGTH[] = "max_length"; +// const fieldID (rowID and timestamp) +const milvus::FieldId RowFieldID = milvus::FieldId(0); +const milvus::FieldId TimestampFieldID = milvus::FieldId(1); + // fill followed extra info to binlog file const char ORIGIN_SIZE_KEY[] = "original_size"; const char INDEX_BUILD_ID_KEY[] = "indexBuildID"; diff --git a/internal/core/src/common/LoadInfo.h b/internal/core/src/common/LoadInfo.h index 207ecc7936e61..3168ffa1f6e28 100644 --- a/internal/core/src/common/LoadInfo.h +++ b/internal/core/src/common/LoadInfo.h @@ -23,13 +23,6 @@ #include "common/CDataType.h" #include "knowhere/index/Index.h" -struct LoadIndexInfo { - int64_t field_id; - CDataType field_type; - std::map index_params; - knowhere::IndexPtr index; -}; - // NOTE: field_id can be system field // NOTE: Refer to common/SystemProperty.cpp for details // TODO: use arrow to pass field data instead of proto diff --git a/internal/core/src/common/QueryInfo.h b/internal/core/src/common/QueryInfo.h new file mode 100644 index 0000000000000..6723eaa21e577 --- /dev/null +++ b/internal/core/src/common/QueryInfo.h @@ -0,0 +1,34 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "common/Types.h" + +namespace milvus { +struct SearchInfo { + int64_t topk_; + int64_t round_decimal_; + FieldId field_id_; + MetricType metric_type_; + Config search_params_; +}; + +using SearchInfoPtr = std::shared_ptr; + +} // namespace milvus diff --git a/internal/core/src/common/Types.h b/internal/core/src/common/Types.h index d5cdb7e68607d..6857e0adc0740 100644 --- a/internal/core/src/common/Types.h +++ b/internal/core/src/common/Types.h @@ -31,6 +31,9 @@ #include #include "knowhere/index/vector_index/helpers/IndexParameter.h" +#include +#include "knowhere/common/BinarySet.h" +#include "knowhere/common/Dataset.h" #include "pb/schema.pb.h" #include "pb/segcore.pb.h" #include "pb/plan.pb.h" @@ -109,6 +112,16 @@ using BitsetTypeOpt = std::optional; template using FixedVector = boost::container::vector; -const FieldId RowFieldID = FieldId(0); -const FieldId TimestampFieldID = FieldId(1); +using Config = nlohmann::json; +using TargetBitmap = boost::dynamic_bitset<>; +using TargetBitmapPtr = std::unique_ptr; + +using BinarySet = knowhere::BinarySet; +using DatasetPtr = knowhere::DatasetPtr; +using MetricType = knowhere::MetricType; +// TODO :: type define milvus index type(vector index type and scalar index type) +using IndexType = knowhere::IndexType; +// TODO :: type define milvus index mode, add transfer func from milvus index mode to knowhere index mode +using IndexMode = knowhere::IndexMode; + } // namespace milvus diff --git a/internal/core/src/common/Utils.h b/internal/core/src/common/Utils.h index bb7b548c4bac2..d2954cb8af417 100644 --- a/internal/core/src/common/Utils.h +++ b/internal/core/src/common/Utils.h @@ -13,8 +13,43 @@ #include #include "exceptions/EasyAssert.h" +#include "config/ConfigChunkManager.h" +#include "common/Consts.h" +#include +#include "knowhere/index/vector_index/adapter/VectorAdapter.h" namespace milvus { + +inline DatasetPtr +GenDataset(const int64_t nb, const int64_t dim, const void* xb) { + return knowhere::GenDataset(nb, dim, xb); +} + +inline const float* +GetDatasetDistance(const DatasetPtr& dataset) { + return knowhere::GetDatasetDistance(dataset); +} + +inline const int64_t* +GetDatasetIDs(const DatasetPtr& dataset) { + return knowhere::GetDatasetIDs(dataset); +} + +inline int64_t +GetDatasetRows(const DatasetPtr& dataset) { + return knowhere::GetDatasetRows(dataset); +} + +inline const void* +GetDatasetTensor(const DatasetPtr& dataset) { + return knowhere::GetDatasetTensor(dataset); +} + +inline int64_t +GetDatasetDim(const DatasetPtr& dataset) { + return knowhere::GetDatasetDim(dataset); +} + inline bool PrefixMatch(const std::string& str, const std::string& prefix) { auto ret = strncmp(str.c_str(), prefix.c_str(), prefix.length()); diff --git a/internal/core/src/common/vector_index_c.cpp b/internal/core/src/common/binary_set_c.cpp similarity index 99% rename from internal/core/src/common/vector_index_c.cpp rename to internal/core/src/common/binary_set_c.cpp index d632706c0f3d8..84fcca32bc08f 100644 --- a/internal/core/src/common/vector_index_c.cpp +++ b/internal/core/src/common/binary_set_c.cpp @@ -15,7 +15,7 @@ // limitations under the License. #include "knowhere/common/BinarySet.h" -#include "common/vector_index_c.h" +#include "common/binary_set_c.h" CStatus NewBinarySet(CBinarySet* c_binary_set) { diff --git a/internal/core/src/common/vector_index_c.h b/internal/core/src/common/binary_set_c.h similarity index 100% rename from internal/core/src/common/vector_index_c.h rename to internal/core/src/common/binary_set_c.h diff --git a/internal/core/src/common/init_c.cpp b/internal/core/src/common/init_c.cpp new file mode 100644 index 0000000000000..ce1abf1654ab0 --- /dev/null +++ b/internal/core/src/common/init_c.cpp @@ -0,0 +1,66 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "common/init_c.h" + +#include +#include "config/ConfigChunkManager.h" + +void +MinioAddressInit(const char* address) { + std::string minio_address(address); + milvus::ChunkMangerConfig::SetAddress(address); +} + +void +MinioAccessKeyInit(const char* key) { + std::string minio_access_key(key); + milvus::ChunkMangerConfig::SetAccessKey(minio_access_key); +} + +void +MinioAccessValueInit(const char* value) { + std::string minio_access_value(value); + milvus::ChunkMangerConfig::SetAccessValue(value); +} + +void +MinioSSLInit(bool use_ssl) { + milvus::ChunkMangerConfig::SetUseSSL(use_ssl); +} + +void +MinioUseIamInit(bool use_iam) { + milvus::ChunkMangerConfig::SetUseIAM(use_iam); +} + +void +MinioBucketNameInit(const char* name) { + std::string bucket_name(name); + milvus::ChunkMangerConfig::SetBucketName(name); +} + +void +MinioRootPathInit(const char* name) { + std::string root_path(name); + milvus::ChunkMangerConfig::SetRemoteRootPath(name); +} + +void +LocalRootPathInit(const char* root_path) { + std::string local_path_root(root_path); + milvus::ChunkMangerConfig::SetLocalRootPath(local_path_root); +} diff --git a/internal/core/src/common/init_c.h b/internal/core/src/common/init_c.h new file mode 100644 index 0000000000000..66411fc8c922b --- /dev/null +++ b/internal/core/src/common/init_c.h @@ -0,0 +1,51 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void +MinioAddressInit(const char*); + +void +MinioAccessKeyInit(const char*); + +void +MinioAccessValueInit(const char*); + +void +MinioSSLInit(bool use_ssl); + +void +MinioUseIamInit(bool use_iam); + +void +MinioBucketNameInit(const char*); + +void +MinioRootPathInit(const char*); + +void +LocalRootPathInit(const char*); + +#ifdef __cplusplus +}; +#endif diff --git a/internal/core/src/config/ConfigChunkManager.cpp b/internal/core/src/config/ConfigChunkManager.cpp index 8f66dfd2e2e7c..561d99a4d1359 100644 --- a/internal/core/src/config/ConfigChunkManager.cpp +++ b/internal/core/src/config/ConfigChunkManager.cpp @@ -18,51 +18,53 @@ namespace milvus::ChunkMangerConfig { -std::string MINIO_ADDRESS = "localhost:9000"; // NOLINT -std::string MINIO_ACCESS_KEY = "minioadmin"; // NOLINT -std::string MINIO_ACCESS_VALUE = "minioadmin"; // NOLINT -std::string MINIO_BUCKET_NAME = "a-bucket"; // NOLINT -std::string LOCAL_BUCKET_NAME = "/tmp/milvus"; // NOLINT +std::string REMOTE_ADDRESS = "localhost:9000"; // NOLINT +std::string REMOTE_ACCESS_KEY = "minioadmin"; // NOLINT +std::string REMOTE_ACCESS_VALUE = "minioadmin"; // NOLINT +std::string REMOTE_BUCKET_NAME = "a-bucket"; // NOLINT +std::string REMOTE_ROOT_PATH = "files"; // NOLINT +std::string LOCAL_ROOT_PATH = "/tmp/milvus"; // NOLINT bool MINIO_USE_SSL = false; +bool MINIO_USE_IAM = false; void SetAddress(const std::string& address) { - MINIO_ADDRESS = address.c_str(); + REMOTE_ADDRESS = address; } std::string GetAddress() { - return MINIO_ADDRESS; + return REMOTE_ADDRESS; } void SetAccessKey(const std::string& access_key) { - MINIO_ACCESS_KEY = access_key.c_str(); + REMOTE_ACCESS_KEY = access_key; } std::string GetAccessKey() { - return MINIO_ACCESS_KEY; + return REMOTE_ACCESS_KEY; } void SetAccessValue(const std::string& access_value) { - MINIO_ACCESS_VALUE = access_value.c_str(); + REMOTE_ACCESS_VALUE = access_value; } std::string GetAccessValue() { - return MINIO_ACCESS_VALUE; + return REMOTE_ACCESS_VALUE; } void SetBucketName(const std::string& bucket_name) { - MINIO_BUCKET_NAME = bucket_name.c_str(); + REMOTE_BUCKET_NAME = bucket_name; } std::string GetBucketName() { - return MINIO_BUCKET_NAME; + return REMOTE_BUCKET_NAME; } void @@ -76,13 +78,33 @@ GetUseSSL() { } void -SetLocalBucketName(const std::string& path_prefix) { - LOCAL_BUCKET_NAME = path_prefix.c_str(); +SetUseIAM(bool use_iam) { + MINIO_USE_IAM = use_iam; +} + +bool +GetUseIAM() { + return MINIO_USE_IAM; +} + +void +SetRemoteRootPath(const std::string& root_path) { + REMOTE_ROOT_PATH = root_path; +} + +std::string +GetRemoteRootPath() { + return REMOTE_ROOT_PATH; +} + +void +SetLocalRootPath(const std::string& path_prefix) { + LOCAL_ROOT_PATH = path_prefix; } std::string -GetLocalBucketName() { - return LOCAL_BUCKET_NAME; +GetLocalRootPath() { + return LOCAL_ROOT_PATH; } } // namespace milvus::ChunkMangerConfig diff --git a/internal/core/src/config/ConfigChunkManager.h b/internal/core/src/config/ConfigChunkManager.h index b39c40b1c5d3f..ebdaed586de8b 100644 --- a/internal/core/src/config/ConfigChunkManager.h +++ b/internal/core/src/config/ConfigChunkManager.h @@ -44,6 +44,12 @@ SetUseSSL(bool use_ssl); bool GetUseSSL(); +void +SetUseIAM(bool use_iam); + +bool +GetUseIAM(); + void SetBucketName(const std::string& bucket_name); @@ -51,9 +57,15 @@ std::string GetBucketName(); void -SetLocalBucketName(const std::string& path_prefix); +SetRemoteRootPath(const std::string& path_prefix); + +std::string +GetRemoteRootPath(); + +void +SetLocalRootPath(const std::string& path_prefix); std::string -GetLocalBucketName(); +GetLocalRootPath(); } // namespace milvus::ChunkMangerConfig diff --git a/internal/core/src/index/BoolIndex.h b/internal/core/src/index/BoolIndex.h index 20cfb90e4c93b..10894e5c7d76a 100644 --- a/internal/core/src/index/BoolIndex.h +++ b/internal/core/src/index/BoolIndex.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once @@ -15,24 +20,14 @@ #include #include "index/ScalarIndexSort.h" -namespace milvus::scalar { +namespace milvus::index { -// TODO: optimize here. -class BoolIndex : public ScalarIndexSort { - public: - void - BuildWithDataset(const DatasetPtr& dataset) override { - auto size = knowhere::GetDatasetRows(dataset); - auto data = knowhere::GetDatasetTensor(dataset); - proto::schema::BoolArray arr; - arr.ParseFromArray(data, size); - Build(arr.data().size(), arr.data().data()); - } -}; -using BoolIndexPtr = std::unique_ptr; +//// TODO: optimize here. +class BoolIndex : public ScalarIndexSort {}; +using BoolIndexPtr = std::shared_ptr; inline BoolIndexPtr CreateBoolIndex() { return std::make_unique(); } -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/CMakeLists.txt b/internal/core/src/index/CMakeLists.txt index 2fb21b40a9843..d9c131f3abda2 100644 --- a/internal/core/src/index/CMakeLists.txt +++ b/internal/core/src/index/CMakeLists.txt @@ -9,11 +9,23 @@ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express # or implied. See the License for the specific language governing permissions and limitations under the License -aux_source_directory( ${MILVUS_ENGINE_SRC}/index INDEX_FILES ) +set(INDEX_FILES + StringIndexMarisa.cpp + Utils.cpp + VectorMemIndex.cpp + IndexFactory.cpp + ) + +if ( BUILD_DISK_ANN STREQUAL "ON" ) + set(INDEX_FILES + ${INDEX_FILES} + VectorDiskIndex.cpp + ) +endif () -add_library( milvus_index SHARED ${INDEX_FILES} ) +milvus_add_pkg_config("milvus_index") +add_library(milvus_index SHARED ${INDEX_FILES}) -# TODO: support compile marisa on windows. set(PLATFORM_LIBS ) if ( LINUX OR APPLE ) set(PLATFORM_LIBS marisa) @@ -23,9 +35,7 @@ if (MSYS) endif () target_link_libraries(milvus_index - milvus_proto - milvus_exceptions - knowhere + milvus_storage ${PLATFORM_LIBS} ) diff --git a/internal/core/src/index/Index.h b/internal/core/src/index/Index.h index 66ff943df5534..cddec592b8380 100644 --- a/internal/core/src/index/Index.h +++ b/internal/core/src/index/Index.h @@ -1,41 +1,51 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once #include -#include -#include #include -namespace milvus::scalar { -using Index = knowhere::Index; -using IndexPtr = std::unique_ptr; -using BinarySet = knowhere::BinarySet; -using Config = knowhere::Config; -using DatasetPtr = knowhere::DatasetPtr; -using TargetBitmap = boost::dynamic_bitset<>; -using TargetBitmapPtr = std::unique_ptr; +#include "common/Types.h" + +namespace milvus::index { -class IndexBase : public Index { +class IndexBase { public: + virtual ~IndexBase() = default; + + virtual BinarySet + Serialize(const Config& config) = 0; + + virtual void + Load(const BinarySet& binary_set, const Config& config = {}) = 0; + virtual void - BuildWithDataset(const DatasetPtr& dataset) = 0; + BuildWithRawData(size_t n, const void* values, const Config& config = {}) = 0; - virtual const TargetBitmapPtr - Query(const DatasetPtr& dataset) = 0; + virtual void + BuildWithDataset(const DatasetPtr& dataset, const Config& config = {}) = 0; - virtual size_t + virtual int64_t Count() = 0; + + protected: + IndexType index_type_ = ""; + IndexMode index_mode_ = IndexMode::MODE_CPU; }; -using IndexBasePtr = std::unique_ptr; -} // namespace milvus::scalar +using IndexBasePtr = std::unique_ptr; +} // namespace milvus::index diff --git a/internal/core/src/index/IndexFactory-inl.h b/internal/core/src/index/IndexFactory-inl.h index 14abc898ea0fa..c4e5e7254ee62 100644 --- a/internal/core/src/index/IndexFactory-inl.h +++ b/internal/core/src/index/IndexFactory-inl.h @@ -1,37 +1,41 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include #include "index/ScalarIndexSort.h" #include "index/StringIndexMarisa.h" -#include "index/IndexType.h" #include "index/BoolIndex.h" -namespace milvus::scalar { +namespace milvus::index { template inline ScalarIndexPtr -IndexFactory::CreateIndex(const std::string& index_type) { +IndexFactory::CreateScalarIndex(const IndexType& index_type) { return CreateScalarIndexSort(); } -template <> -inline ScalarIndexPtr -IndexFactory::CreateIndex(const std::string& index_type) { - return CreateBoolIndex(); -} +// template <> +// inline ScalarIndexPtr +// IndexFactory::CreateScalarIndex(const IndexType& index_type) { +// return CreateBoolIndex(); +//} template <> inline ScalarIndexPtr -IndexFactory::CreateIndex(const std::string& index_type) { +IndexFactory::CreateScalarIndex(const IndexType& index_type) { #if defined(__linux__) || defined(__APPLE__) return CreateStringIndexMarisa(); #else @@ -39,4 +43,4 @@ IndexFactory::CreateIndex(const std::string& index_type) { #endif } -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/IndexFactory.cpp b/internal/core/src/index/IndexFactory.cpp index ebda84010237e..1f7bbff2118fb 100644 --- a/internal/core/src/index/IndexFactory.cpp +++ b/internal/core/src/index/IndexFactory.cpp @@ -1,48 +1,94 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "index/IndexFactory.h" -#include "index/ScalarIndexSort.h" -#include "index/StringIndexMarisa.h" +#include "index/VectorMemIndex.h" +#include "index/Utils.h" +#include "index/Meta.h" + +#ifdef BUILD_DISK_ANN +#include "index/VectorDiskIndex.h" +#endif + +namespace milvus::index { + +IndexBasePtr +IndexFactory::CreateIndex(const CreateIndexInfo& create_index_info, storage::FileManagerImplPtr file_manager) { + if (datatype_is_vector(create_index_info.field_type)) { + return CreateVectorIndex(create_index_info, file_manager); + } -namespace milvus::scalar { + return CreateScalarIndex(create_index_info); +} IndexBasePtr -IndexFactory::CreateIndex(CDataType dtype, const std::string& index_type) { - switch (dtype) { - case Bool: - return CreateIndex(index_type); - case Int8: - return CreateIndex(index_type); - case Int16: - return CreateIndex(index_type); - case Int32: - return CreateIndex(index_type); - case Int64: - return CreateIndex(index_type); - case Float: - return CreateIndex(index_type); - case Double: - return CreateIndex(index_type); - - case String: - case VarChar: - return CreateIndex(index_type); - - case None: - case BinaryVector: - case FloatVector: +IndexFactory::CreateScalarIndex(const CreateIndexInfo& create_index_info) { + auto data_type = create_index_info.field_type; + auto index_type = create_index_info.index_type; + + switch (data_type) { + // create scalar index + case DataType::BOOL: + return CreateScalarIndex(index_type); + case DataType::INT8: + return CreateScalarIndex(index_type); + case DataType::INT16: + return CreateScalarIndex(index_type); + case DataType::INT32: + return CreateScalarIndex(index_type); + case DataType::INT64: + return CreateScalarIndex(index_type); + case DataType::FLOAT: + return CreateScalarIndex(index_type); + case DataType::DOUBLE: + return CreateScalarIndex(index_type); + + // create string index + case DataType::STRING: + case DataType::VARCHAR: + return CreateScalarIndex(index_type); default: - throw std::invalid_argument(std::string("invalid data type: ") + std::to_string(dtype)); + throw std::invalid_argument(std::string("invalid data type to build index: ") + + std::to_string(int(data_type))); } } -} // namespace milvus::scalar +IndexBasePtr +IndexFactory::CreateVectorIndex(const CreateIndexInfo& create_index_info, storage::FileManagerImplPtr file_manager) { + auto data_type = create_index_info.field_type; + auto index_type = create_index_info.index_type; + auto metric_type = create_index_info.metric_type; + auto index_mode = create_index_info.index_mode; + +#ifdef BUILD_DISK_ANN + // create disk index + if (is_in_disk_list(index_type)) { + switch (data_type) { + case DataType::VECTOR_FLOAT: { + return std::make_unique>(index_type, metric_type, index_mode, file_manager); + } + default: + throw std::invalid_argument(std::string("invalid data type to build disk index: ") + + std::to_string(int(data_type))); + } + } +#endif + + // create mem index + return std::make_unique(index_type, metric_type, index_mode); +} + +} // namespace milvus::index diff --git a/internal/core/src/index/IndexFactory.h b/internal/core/src/index/IndexFactory.h index 9487498176131..716f2e7f91d20 100644 --- a/internal/core/src/index/IndexFactory.h +++ b/internal/core/src/index/IndexFactory.h @@ -1,24 +1,40 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once #include +#include +#include #include "common/type_c.h" +#include "config/ConfigChunkManager.h" #include "index/Index.h" #include "index/ScalarIndex.h" -#include "index/StringIndex.h" +#include "index/VectorIndex.h" +#include "index/IndexInfo.h" +#include "storage/Types.h" +#include "storage/FileManager.h" + +#ifdef BUILD_DISK_ANN +#include "storage/LocalChunkManager.h" +#include "storage/MinioChunkManager.h" +#endif -namespace milvus::scalar { +namespace milvus::index { class IndexFactory { public: @@ -32,17 +48,27 @@ class IndexFactory { GetInstance() { // thread-safe enough after c++ 11 static IndexFactory instance; + return instance; } IndexBasePtr - CreateIndex(CDataType dtype, const std::string& index_type); + CreateIndex(const CreateIndexInfo& create_index_info, storage::FileManagerImplPtr file_manager); + + IndexBasePtr + CreateVectorIndex(const CreateIndexInfo& create_index_info, storage::FileManagerImplPtr file_manager); + + IndexBasePtr + CreateScalarIndex(const CreateIndexInfo& create_index_info); + // IndexBasePtr + // CreateIndex(DataType dtype, const IndexType& index_type, const IndexMode& index_mode = IndexMode::MODE_CPU); + private: template ScalarIndexPtr - CreateIndex(const std::string& index_type); + CreateScalarIndex(const IndexType& index_type); }; -} // namespace milvus::scalar +} // namespace milvus::index #include "index/IndexFactory-inl.h" diff --git a/internal/core/src/index/IndexInfo.h b/internal/core/src/index/IndexInfo.h new file mode 100644 index 0000000000000..66001a0c424f2 --- /dev/null +++ b/internal/core/src/index/IndexInfo.h @@ -0,0 +1,51 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include + +#include "common/Types.h" +#include "common/type_c.h" +#include "index/Index.h" + +namespace milvus::index { + +struct LoadIndexInfo { + int64_t collection_id; + int64_t partition_id; + int64_t segment_id; + int64_t field_id; + DataType field_type; + int64_t index_id; + int64_t index_build_id; + int64_t index_version; + std::map index_params; + std::vector index_files; + index::IndexBasePtr index; +}; + +struct CreateIndexInfo { + DataType field_type; + IndexType index_type; + MetricType metric_type; + IndexMode index_mode = IndexMode::MODE_CPU; +}; + +} // namespace milvus::index diff --git a/internal/core/src/index/IndexStructure.h b/internal/core/src/index/IndexStructure.h index d8e43df5ca33a..d64e7182df228 100644 --- a/internal/core/src/index/IndexStructure.h +++ b/internal/core/src/index/IndexStructure.h @@ -1,15 +1,20 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -namespace milvus::scalar { +namespace milvus::index { template struct IndexStructure { IndexStructure() : a_(0), idx_(0) { @@ -41,4 +46,4 @@ struct IndexStructure { T a_; size_t idx_; }; -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/IndexType.h b/internal/core/src/index/IndexType.h deleted file mode 100644 index 1184f5da81622..0000000000000 --- a/internal/core/src/index/IndexType.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License - -#pragma once - -namespace milvus::scalar { -constexpr const char* INDEX_TYPE_MARISA = "marisa"; -} diff --git a/internal/core/src/index/Meta.h b/internal/core/src/index/Meta.h index b6aa8554bb554..0873554bd89f5 100644 --- a/internal/core/src/index/Meta.h +++ b/internal/core/src/index/Meta.h @@ -1,17 +1,25 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once -namespace milvus::scalar { +#include "knowhere/index/IndexType.h" +#include "knowhere/index/vector_index/helpers/IndexParameter.h" + +namespace milvus::index { constexpr const char* OPERATOR_TYPE = "operator_type"; constexpr const char* RANGE_VALUE = "range_value"; constexpr const char* LOWER_BOUND_VALUE = "lower_bound_value"; @@ -19,9 +27,49 @@ constexpr const char* LOWER_BOUND_INCLUSIVE = "lower_bound_inclusive"; constexpr const char* UPPER_BOUND_VALUE = "upper_bound_value"; constexpr const char* UPPER_BOUND_INCLUSIVE = "upper_bound_inclusive"; constexpr const char* PREFIX_VALUE = "prefix_value"; -constexpr const char* MARISA_TRIE = "marisa_trie"; // below configurations will be persistent, do not edit them. constexpr const char* MARISA_TRIE_INDEX = "marisa_trie_index"; constexpr const char* MARISA_STR_IDS = "marisa_trie_str_ids"; -constexpr const char* FLAT_STR_INDEX = "flat_str_index"; -} // namespace milvus::scalar + +constexpr const char* INDEX_TYPE = "index_type"; +constexpr const char* INDEX_MODE = "index_mode"; +constexpr const char* METRIC_TYPE = "metric_type"; + +// scalar index type +constexpr const char* ASCENDING_SORT = "STL_SORT"; +constexpr const char* MARISA_TRIE = "Trie"; + +// index meta +constexpr const char* COLLECTION_ID = "collection_id"; +constexpr const char* PARTITION_ID = "partition_id"; +constexpr const char* SEGMENT_ID = "segment_id"; +constexpr const char* FIELD_ID = "field_id"; +constexpr const char* INDEX_BUILD_ID = "index_build_id"; +constexpr const char* INDEX_ID = "index_id"; +constexpr const char* INDEX_VERSION = "index_version"; + +// DiskAnn build params +constexpr const char* DISK_ANN_RAW_DATA_PATH = "data_path"; +constexpr const char* DISK_ANN_MAX_DEGREE = "max_degree"; +constexpr const char* DISK_ANN_BUILD_LIST = "build_list"; +constexpr const char* DISK_ANN_SEARCH_DRAM_BUDGET = "search_dram_budget"; +constexpr const char* DISK_ANN_BUILD_DRAM_BUDGET = "build_dram_budget"; +constexpr const char* DISK_ANN_BUILD_THREAD_NUM = "num_build_thread"; +constexpr const char* DISK_ANN_PQ_BYTES = "ps_disk_bytes"; + +// DiskAnn prepare params +constexpr const char* DISK_ANN_PREPARE_THREAD_NUM = "num_prepare_thread"; +constexpr const char* NUM_ROW_OF_RAW_DATA = "count"; +constexpr const char* DISK_ANN_PREPARE_WARM_UP = "warm_up"; +constexpr const char* DISK_ANN_PREPARE_USE_BFS_CACHE = "use_bfs_cache"; + +// DiskAnn query params +constexpr const char* DISK_ANN_QUERY_LIST = "search_list"; +constexpr const char* DISK_ANN_QUERY_BEAMWIDTH = "beamwidth"; + +// DiskAnn config name +constexpr const char* Disk_ANN_Build_Config = "diskANN_build_config"; +constexpr const char* Disk_ANN_Prepare_Config = "diskANN_prepare_config"; +constexpr const char* Disk_ANN_Query_Config = "diskANN_query_config"; + +} // namespace milvus::index diff --git a/internal/core/src/index/ScalarIndex-inl.h b/internal/core/src/index/ScalarIndex-inl.h index f949da1faafa2..0ca7f6f62f345 100644 --- a/internal/core/src/index/ScalarIndex-inl.h +++ b/internal/core/src/index/ScalarIndex-inl.h @@ -1,21 +1,27 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include #include +#include #include "index/Meta.h" #include "knowhere/index/vector_index/adapter/VectorAdapter.h" -namespace milvus::scalar { +namespace milvus::index { template const TargetBitmapPtr ScalarIndex::Query(const DatasetPtr& dataset) { @@ -55,4 +61,67 @@ ScalarIndex::Query(const DatasetPtr& dataset) { throw std::invalid_argument(std::string("unsupported operator type: " + std::to_string(op))); } } -} // namespace milvus::scalar + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + // TODO :: use arrow + proto::schema::StringArray arr; + arr.ParseFromArray(values, n); + + // TODO :: optimize here. avoid memory copy. + std::vector vecs{arr.data().begin(), arr.data().end()}; + Build(arr.data_size(), vecs.data()); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + proto::schema::BoolArray arr; + arr.ParseFromArray(values, n); + Build(arr.data_size(), arr.data().data()); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +template <> +inline void +ScalarIndex::BuildWithRawData(size_t n, const void* values, const Config& config) { + auto data = reinterpret_cast(const_cast(values)); + Build(n, data); +} + +} // namespace milvus::index diff --git a/internal/core/src/index/ScalarIndex.h b/internal/core/src/index/ScalarIndex.h index 6aa67b7a7af33..877151df88220 100644 --- a/internal/core/src/index/ScalarIndex.h +++ b/internal/core/src/index/ScalarIndex.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once @@ -17,11 +22,21 @@ #include #include "index/Index.h" #include "common/Types.h" +#include "exceptions/EasyAssert.h" -namespace milvus::scalar { +namespace milvus::index { template class ScalarIndex : public IndexBase { + public: + void + BuildWithRawData(size_t n, const void* values, const Config& config = {}) override; + + void + BuildWithDataset(const DatasetPtr& dataset, const Config& config = {}) override { + PanicInfo("scalar index don't support build index with dataset"); + }; + public: virtual void Build(size_t n, const T* values) = 0; @@ -41,13 +56,16 @@ class ScalarIndex : public IndexBase { virtual T Reverse_Lookup(size_t offset) const = 0; - const TargetBitmapPtr - Query(const DatasetPtr& dataset) override; + virtual const TargetBitmapPtr + Query(const DatasetPtr& dataset); + + virtual int64_t + Size() = 0; }; template using ScalarIndexPtr = std::unique_ptr>; -} // namespace milvus::scalar +} // namespace milvus::index #include "index/ScalarIndex-inl.h" diff --git a/internal/core/src/index/ScalarIndexSort-inl.h b/internal/core/src/index/ScalarIndexSort-inl.h index b27ef7bc138f6..cf71646087305 100644 --- a/internal/core/src/index/ScalarIndexSort-inl.h +++ b/internal/core/src/index/ScalarIndexSort-inl.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include #include @@ -19,7 +24,7 @@ #include "Meta.h" #include "common/Utils.h" -namespace milvus::scalar { +namespace milvus::index { template inline ScalarIndexSort::ScalarIndexSort() : is_built_(false), data_() { @@ -27,38 +32,24 @@ inline ScalarIndexSort::ScalarIndexSort() : is_built_(false), data_() { template inline ScalarIndexSort::ScalarIndexSort(const size_t n, const T* values) : is_built_(false) { - ScalarIndexSort::Build(n, values); -} - -template -inline void -ScalarIndexSort::BuildWithDataset(const DatasetPtr& dataset) { - auto size = knowhere::GetDatasetRows(dataset); - auto data = knowhere::GetDatasetTensor(dataset); - Build(size, reinterpret_cast(data)); + ScalarIndexSort::BuildWithDataset(n, values); } template inline void ScalarIndexSort::Build(const size_t n, const T* values) { + if (is_built_) + return; + if (n == 0) { + // todo: throw an exception + throw std::invalid_argument("ScalarIndexSort cannot build null values!"); + } data_.reserve(n); idx_to_offsets_.resize(n); T* p = const_cast(values); for (size_t i = 0; i < n; ++i) { data_.emplace_back(IndexStructure(*p++, i)); } - build(); -} - -template -inline void -ScalarIndexSort::build() { - if (is_built_) - return; - if (data_.size() == 0) { - // todo: throw an exception - throw std::invalid_argument("ScalarIndexSort cannot build null values!"); - } std::sort(data_.begin(), data_.end()); for (size_t i = 0; i < data_.size(); ++i) { idx_to_offsets_[data_[i].idx_] = i; @@ -87,7 +78,7 @@ ScalarIndexSort::Serialize(const Config& config) { template inline void -ScalarIndexSort::Load(const BinarySet& index_binary) { +ScalarIndexSort::Load(const BinarySet& index_binary, const Config& config) { size_t index_size; auto index_length = index_binary.GetByName("index_length"); memcpy(&index_size, index_length->data.get(), (size_t)index_length->size); @@ -206,5 +197,4 @@ ScalarIndexSort::Reverse_Lookup(size_t idx) const { auto offset = idx_to_offsets_[idx]; return data_[offset].a_; } - -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/ScalarIndexSort.h b/internal/core/src/index/ScalarIndexSort.h index 0d1f5355e1a9f..8112630fca90b 100644 --- a/internal/core/src/index/ScalarIndexSort.h +++ b/internal/core/src/index/ScalarIndexSort.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once @@ -20,7 +25,7 @@ #include "index/IndexStructure.h" #include "index/ScalarIndex.h" -namespace milvus::scalar { +namespace milvus::index { template class ScalarIndexSort : public ScalarIndex { @@ -32,12 +37,9 @@ class ScalarIndexSort : public ScalarIndex { Serialize(const Config& config) override; void - Load(const BinarySet& index_binary) override; - - void - BuildWithDataset(const DatasetPtr& dataset) override; + Load(const BinarySet& index_binary, const Config& config = {}) override; - size_t + int64_t Count() override { return data_.size(); } @@ -45,9 +47,6 @@ class ScalarIndexSort : public ScalarIndex { void Build(size_t n, const T* values) override; - void - build(); - const TargetBitmapPtr In(size_t n, const T* values) override; @@ -63,17 +62,17 @@ class ScalarIndexSort : public ScalarIndex { T Reverse_Lookup(size_t offset) const override; + int64_t + Size() override { + return (int64_t)data_.size(); + } + public: const std::vector>& GetData() { return data_; } - int64_t - Size() override { - return (int64_t)data_.size(); - } - bool IsBuilt() const { return is_built_; @@ -81,6 +80,7 @@ class ScalarIndexSort : public ScalarIndex { private: bool is_built_; + Config config_; std::vector idx_to_offsets_; // used to retrieve. std::vector> data_; }; @@ -88,14 +88,14 @@ class ScalarIndexSort : public ScalarIndex { template using ScalarIndexSortPtr = std::unique_ptr>; -} // namespace milvus::scalar +} // namespace milvus::index #include "index/ScalarIndexSort-inl.h" -namespace milvus::scalar { +namespace milvus::index { template inline ScalarIndexSortPtr CreateScalarIndexSort() { return std::make_unique>(); } -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/StringIndex.h b/internal/core/src/index/StringIndex.h index b8af2597c2e3b..f92b9c9fca42d 100644 --- a/internal/core/src/index/StringIndex.h +++ b/internal/core/src/index/StringIndex.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once @@ -18,30 +23,10 @@ #include "index/Meta.h" #include -namespace milvus::scalar { +namespace milvus::index { class StringIndex : public ScalarIndex { public: - void - BuildWithDataset(const DatasetPtr& dataset) override { - auto size = knowhere::GetDatasetRows(dataset); - auto data = knowhere::GetDatasetTensor(dataset); - proto::schema::StringArray arr; - arr.ParseFromArray(data, size); - - { - // TODO: optimize here. avoid memory copy. - std::vector vecs{arr.data().begin(), arr.data().end()}; - Build(arr.data().size(), vecs.data()); - } - - { - // TODO: test this way. - // auto strs = (const std::string*)arr.data().data(); - // Build(arr.data().size(), strs); - } - } - const TargetBitmapPtr Query(const DatasetPtr& dataset) override { auto op = dataset->Get(OPERATOR_TYPE); @@ -56,4 +41,4 @@ class StringIndex : public ScalarIndex { PrefixMatch(std::string prefix) = 0; }; using StringIndexPtr = std::unique_ptr; -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/StringIndexMarisa.cpp b/internal/core/src/index/StringIndexMarisa.cpp index f2934eae849c3..274593993dc17 100644 --- a/internal/core/src/index/StringIndexMarisa.cpp +++ b/internal/core/src/index/StringIndexMarisa.cpp @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include #include @@ -22,7 +27,7 @@ #include "index/Index.h" #include "common/Utils.h" -namespace milvus::scalar { +namespace milvus::index { #if defined(__linux__) || defined(__APPLE__) @@ -86,7 +91,7 @@ StringIndexMarisa::Serialize(const Config& config) { } void -StringIndexMarisa::Load(const BinarySet& set) { +StringIndexMarisa::Load(const BinarySet& set, const Config& config) { knowhere::Assemble(const_cast(set)); auto uuid = boost::uuids::random_generator()(); @@ -289,4 +294,4 @@ StringIndexMarisa::Reverse_Lookup(size_t offset) const { #endif -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/StringIndexMarisa.h b/internal/core/src/index/StringIndexMarisa.h index 9aa275208d785..45adae7db5543 100644 --- a/internal/core/src/index/StringIndexMarisa.h +++ b/internal/core/src/index/StringIndexMarisa.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once @@ -20,7 +25,7 @@ #include #include -namespace milvus::scalar { +namespace milvus::index { class StringIndexMarisa : public StringIndex { public: @@ -33,9 +38,9 @@ class StringIndexMarisa : public StringIndex { Serialize(const Config& config) override; void - Load(const BinarySet& set) override; + Load(const BinarySet& set, const Config& config = {}) override; - size_t + int64_t Count() override { return str_ids_.size(); } @@ -76,6 +81,7 @@ class StringIndexMarisa : public StringIndex { prefix_match(const std::string& prefix); private: + Config config_; marisa::Trie trie_; std::vector str_ids_; // used to retrieve. std::map> str_ids_to_offsets_; @@ -89,6 +95,6 @@ CreateStringIndexMarisa() { return std::make_unique(); } -} // namespace milvus::scalar +} // namespace milvus::index #endif diff --git a/internal/core/src/index/StringIndexSort.h b/internal/core/src/index/StringIndexSort.h index ac9592cc62219..aebeabd4a6412 100644 --- a/internal/core/src/index/StringIndexSort.h +++ b/internal/core/src/index/StringIndexSort.h @@ -1,13 +1,18 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include #include @@ -18,30 +23,10 @@ #include "index/StringIndex.h" #include "knowhere/index/vector_index/adapter/VectorAdapter.h" -namespace milvus::scalar { +namespace milvus::index { // TODO: should inherit from StringIndex? class StringIndexSort : public ScalarIndexSort { public: - void - BuildWithDataset(const DatasetPtr& dataset) override { - auto size = knowhere::GetDatasetRows(dataset); - auto data = knowhere::GetDatasetTensor(dataset); - proto::schema::StringArray arr; - arr.ParseFromArray(data, size); - - { - // TODO: optimize here. avoid memory copy. - std::vector vecs{arr.data().begin(), arr.data().end()}; - Build(arr.data().size(), vecs.data()); - } - - { - // TODO: test this way. - // auto strs = (const std::string*)arr.data().data(); - // Build(arr.data().size(), strs); - } - } - const TargetBitmapPtr Query(const DatasetPtr& dataset) override { auto op = dataset->Get(OPERATOR_TYPE); @@ -70,4 +55,4 @@ inline StringIndexSortPtr CreateStringIndexSort() { return std::make_unique(); } -} // namespace milvus::scalar +} // namespace milvus::index diff --git a/internal/core/src/index/Utils.cpp b/internal/core/src/index/Utils.cpp new file mode 100644 index 0000000000000..36b3b11f5580e --- /dev/null +++ b/internal/core/src/index/Utils.cpp @@ -0,0 +1,205 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "index/Utils.h" +#include "index/Meta.h" +#include "pb/index_cgo_msg.pb.h" +#include +#include "exceptions/EasyAssert.h" + +namespace milvus::index { + +size_t +get_file_size(int fd) { + struct stat s; + fstat(fd, &s); + return s.st_size; +} + +std::vector +NM_List() { + static std::vector ret{ + knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, + }; + return ret; +} + +std::vector +BIN_List() { + static std::vector ret{ + knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP, + knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, + }; + return ret; +} + +std::vector +DISK_LIST() { + static std::vector ret{ + knowhere::IndexEnum::INDEX_DISKANN, + }; + return ret; +} + +std::vector> +unsupported_index_combinations() { + static std::vector> ret{ + std::make_tuple(knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, knowhere::metric::L2), + }; + return ret; +} + +bool +is_in_bin_list(const IndexType& index_type) { + return is_in_list(index_type, BIN_List); +} + +bool +is_in_nm_list(const IndexType& index_type) { + return is_in_list(index_type, NM_List); +} + +bool +is_in_disk_list(const IndexType& index_type) { + return is_in_list(index_type, DISK_LIST); +} + +bool +is_unsupported(const IndexType& index_type, const MetricType& metric_type) { + return is_in_list>(std::make_tuple(index_type, metric_type), + unsupported_index_combinations); +} + +bool +CheckKeyInConfig(const Config& cfg, const std::string& key) { + return cfg.contains(key); +} + +void +ParseFromString(google::protobuf::Message& params, const std::string& str) { + auto ok = google::protobuf::TextFormat::ParseFromString(str, ¶ms); + AssertInfo(ok, "failed to parse params from string"); +} + +int64_t +GetDimFromConfig(const Config& config) { + auto dimension = GetValueFromConfig(config, "dim"); + AssertInfo(dimension.has_value(), "dimension not exist in config"); + return (std::stoi(dimension.value())); +} + +std::string +GetMetricTypeFromConfig(const Config& config) { + auto metric_type = GetValueFromConfig(config, "metric_type"); + AssertInfo(metric_type.has_value(), "metric_type not exist in config"); + return metric_type.value(); +} + +std::string +GetIndexTypeFromConfig(const Config& config) { + auto index_type = GetValueFromConfig(config, "index_type"); + AssertInfo(index_type.has_value(), "index_type not exist in config"); + return index_type.value(); +} + +IndexMode +GetIndexModeFromConfig(const Config& config) { + auto mode = GetValueFromConfig(config, INDEX_MODE); + return mode.has_value() ? GetIndexMode(mode.value()) : knowhere::IndexMode::MODE_CPU; +} + +IndexMode +GetIndexMode(const std::string index_mode) { + if (index_mode.compare("CPU") != 0) { + return IndexMode::MODE_CPU; + } + + if (index_mode.compare("GPU") != 0) { + return IndexMode::MODE_GPU; + } + + PanicInfo("unsupported index mode"); +} + +// TODO :: too ugly +storage::FieldDataMeta +GetFieldDataMetaFromConfig(const Config& config) { + storage::FieldDataMeta field_data_meta; + // set collection id + auto collection_id = index::GetValueFromConfig(config, index::COLLECTION_ID); + AssertInfo(collection_id.has_value(), "collection id not exist in index config"); + field_data_meta.collection_id = std::stol(collection_id.value()); + + // set partition id + auto partition_id = index::GetValueFromConfig(config, index::PARTITION_ID); + AssertInfo(partition_id.has_value(), "partition id not exist in index config"); + field_data_meta.partition_id = std::stol(partition_id.value()); + + // set segment id + auto segment_id = index::GetValueFromConfig(config, index::SEGMENT_ID); + AssertInfo(segment_id.has_value(), "segment id not exist in index config"); + field_data_meta.segment_id = std::stol(segment_id.value()); + + // set field id + auto field_id = index::GetValueFromConfig(config, index::FIELD_ID); + AssertInfo(field_id.has_value(), "field id not exist in index config"); + field_data_meta.field_id = std::stol(field_id.value()); + + return field_data_meta; +} + +storage::IndexMeta +GetIndexMetaFromConfig(const Config& config) { + storage::IndexMeta index_meta; + // set segment id + auto segment_id = index::GetValueFromConfig(config, index::SEGMENT_ID); + AssertInfo(segment_id.has_value(), "segment id not exist in index config"); + index_meta.segment_id = std::stol(segment_id.value()); + + // set field id + auto field_id = index::GetValueFromConfig(config, index::FIELD_ID); + AssertInfo(field_id.has_value(), "field id not exist in index config"); + index_meta.field_id = std::stol(field_id.value()); + + // set index version + auto index_version = index::GetValueFromConfig(config, index::INDEX_VERSION); + AssertInfo(index_version.has_value(), "index_version id not exist in index config"); + index_meta.index_version = std::stol(index_version.value()); + + // set index id + auto build_id = index::GetValueFromConfig(config, index::INDEX_BUILD_ID); + AssertInfo(build_id.has_value(), "build id not exist in index config"); + index_meta.build_id = std::stol(build_id.value()); + + return index_meta; +} + +Config +ParseConfigFromIndexParams(const std::map& index_params) { + Config config; + for (auto& p : index_params) { + config[p.first] = p.second; + } + + return config; +} + +} // namespace milvus::index diff --git a/internal/core/src/index/Utils.h b/internal/core/src/index/Utils.h index e1b222e809905..d561039e3c077 100644 --- a/internal/core/src/index/Utils.h +++ b/internal/core/src/index/Utils.h @@ -1,13 +1,20 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once #include #include @@ -15,14 +22,105 @@ #include #include #include +#include +#include +#include -namespace milvus::scalar { +#include "common/Types.h" +#include "index/IndexInfo.h" +#include "storage/Types.h" + +namespace milvus::index { size_t -get_file_size(int fd) { - struct stat s; - fstat(fd, &s); - return s.st_size; +get_file_size(int fd); + +std::vector +NM_List(); + +std::vector +BIN_List(); + +std::vector> +unsupported_index_combinations(); + +template +inline bool +is_in_list(const T& t, std::function()> list_func) { + auto l = list_func(); + return std::find(l.begin(), l.end(), t) != l.end(); } -} // namespace milvus::scalar +bool +is_in_bin_list(const IndexType& index_type); + +bool +is_in_nm_list(const IndexType& index_type); + +bool +is_in_disk_list(const IndexType& index_type); + +bool +is_unsupported(const IndexType& index_type, const MetricType& metric_type); + +bool +CheckKeyInConfig(const Config& cfg, const std::string& key); + +void +ParseFromString(google::protobuf::Message& params, const std::string& str); + +template +void inline CheckParameter(Config& conf, + const std::string& key, + std::function fn, + std::optional default_v) { + if (!conf.contains(key)) { + if (default_v.has_value()) { + conf[key] = default_v.value(); + } + } else { + auto value = conf[key]; + conf[key] = fn(value); + } +} + +template +inline std::optional +GetValueFromConfig(const Config& cfg, const std::string& key) { + if (cfg.contains(key)) { + return cfg.at(key).get(); + } + return std::nullopt; +} + +template +inline void +SetValueToConfig(Config& cfg, const std::string& key, const T value) { + cfg[key] = value; +} + +int64_t +GetDimFromConfig(const Config& config); + +std::string +GetMetricTypeFromConfig(const Config& config); + +std::string +GetIndexTypeFromConfig(const Config& config); + +IndexMode +GetIndexModeFromConfig(const Config& config); + +IndexMode +GetIndexMode(const std::string index_mode); + +storage::FieldDataMeta +GetFieldDataMetaFromConfig(const Config& config); + +storage::IndexMeta +GetIndexMetaFromConfig(const Config& config); + +Config +ParseConfigFromIndexParams(const std::map& index_params); + +} // namespace milvus::index diff --git a/internal/core/src/index/VectorDiskIndex.cpp b/internal/core/src/index/VectorDiskIndex.cpp new file mode 100644 index 0000000000000..f55b62b498694 --- /dev/null +++ b/internal/core/src/index/VectorDiskIndex.cpp @@ -0,0 +1,263 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "index/VectorDiskIndex.h" +#include "index/Meta.h" +#include "index/Utils.h" + +#include "storage/LocalChunkManager.h" +#include "config/ConfigKnowhere.h" +#include "storage/Util.h" +#include "common/Utils.h" + +namespace milvus::index { + +#ifdef BUILD_DISK_ANN + +template +VectorDiskAnnIndex::VectorDiskAnnIndex(const IndexType& index_type, + const MetricType& metric_type, + const IndexMode& index_mode, + storage::FileManagerImplPtr file_manager) + : VectorIndex(index_type, index_mode, metric_type) { + file_manager_ = std::dynamic_pointer_cast(file_manager); + auto& local_chunk_manager = storage::LocalChunkManager::GetInstance(); + auto local_index_path_prefix = file_manager_->GetLocalIndexObjectPrefix(); + AssertInfo(!local_chunk_manager.Exist(local_index_path_prefix), + "local index path " + local_index_path_prefix + " has been exist"); + local_chunk_manager.CreateDir(local_index_path_prefix); + index_ = std::make_unique>(local_index_path_prefix, metric_type, file_manager); +} + +template +void +VectorDiskAnnIndex::Load(const BinarySet& binary_set /* not used */, const Config& config) { + auto prepare_config = parse_prepare_config(config); + knowhere::Config cfg; + knowhere::DiskANNPrepareConfig::Set(cfg, prepare_config); + + auto index_files = GetValueFromConfig>(config, "index_files"); + AssertInfo(index_files.has_value(), "index file paths is empty when load disk ann index data"); + file_manager_->CacheIndexToDisk(index_files.value()); + index_->Prepare(cfg); + SetDim(index_->Dim()); +} + +template +void +VectorDiskAnnIndex::BuildWithDataset(const DatasetPtr& dataset, const Config& config) { + auto& local_chunk_manager = storage::LocalChunkManager::GetInstance(); + auto build_config = parse_build_config(config); + auto segment_id = file_manager_->GetFileDataMeta().segment_id; + auto field_id = file_manager_->GetFileDataMeta().field_id; + auto local_data_path = storage::GenFieldRawDataPathPrefix(segment_id, field_id) + "raw_data"; + build_config.data_path = local_data_path; + if (!local_chunk_manager.Exist(local_data_path)) { + local_chunk_manager.CreateFile(local_data_path); + } + + int64_t offset = 0; + auto num = uint32_t(milvus::GetDatasetRows(dataset)); + local_chunk_manager.Write(local_data_path, offset, &num, sizeof(num)); + offset += sizeof(num); + + auto dim = uint32_t(milvus::GetDatasetDim(dataset)); + local_chunk_manager.Write(local_data_path, offset, &dim, sizeof(dim)); + offset += sizeof(dim); + + auto data_size = num * dim * sizeof(float); + auto raw_data = const_cast(milvus::GetDatasetTensor(dataset)); + local_chunk_manager.Write(local_data_path, offset, raw_data, data_size); + + knowhere::Config cfg; + knowhere::DiskANNBuildConfig::Set(cfg, build_config); + + index_->BuildAll(nullptr, cfg); + + local_chunk_manager.RemoveDir(storage::GetSegmentRawDataPathPrefix(segment_id)); + // TODO :: + // SetDim(index_->Dim()); +} + +template +std::unique_ptr +VectorDiskAnnIndex::Query(const DatasetPtr dataset, const SearchInfo& search_info, const BitsetView& bitset) { + AssertInfo(GetMetricType() == search_info.metric_type_, + "Metric type of field index isn't the same with search info"); + auto num_queries = milvus::GetDatasetRows(dataset); + auto topk = search_info.topk_; + + knowhere::DiskANNQueryConfig query_config; + query_config.k = topk; + + // set search list + auto search_list_size = GetValueFromConfig(search_info.search_params_, DISK_ANN_QUERY_LIST); + AssertInfo(search_list_size.has_value(), "param " + std::string(DISK_ANN_QUERY_LIST) + "is empty"); + query_config.search_list_size = search_list_size.value(); + + AssertInfo(query_config.search_list_size > topk, "search_list should be greater than topk"); + AssertInfo(query_config.search_list_size < std::min(uint32_t(topk * 10), uint32_t(65535)), + "search_list should less than min(topk*10, 65535)"); + + // set beamwidth + query_config.beamwidth = 16; + auto beam_width = GetValueFromConfig(search_info.search_params_, DISK_ANN_QUERY_BEAMWIDTH); + if (beam_width.has_value()) { + query_config.beamwidth = beam_width.value(); + } + + knowhere::Config cfg; + knowhere::DiskANNQueryConfig::Set(cfg, query_config); + + auto final_result = index_->Query(dataset, cfg, bitset); + auto ids = milvus::GetDatasetIDs(final_result); + float* distances = (float*)milvus::GetDatasetDistance(final_result); + + auto round_decimal = search_info.round_decimal_; + auto total_num = num_queries * topk; + + if (round_decimal != -1) { + const float multiplier = pow(10.0, round_decimal); + for (int i = 0; i < total_num; i++) { + distances[i] = round(distances[i] * multiplier) / multiplier; + } + } + auto result = std::make_unique(); + result->seg_offsets_.resize(total_num); + result->distances_.resize(total_num); + result->total_nq_ = num_queries; + result->unity_topK_ = topk; + + std::copy_n(ids, total_num, result->seg_offsets_.data()); + std::copy_n(distances, total_num, result->distances_.data()); + + return result; +} + +template +void +VectorDiskAnnIndex::CleanLocalData() { + auto& local_chunk_manager = storage::LocalChunkManager::GetInstance(); + local_chunk_manager.RemoveDir(file_manager_->GetLocalIndexObjectPrefix()); + local_chunk_manager.RemoveDir(file_manager_->GetLocalRawDataObjectPrefix()); +} + +template +knowhere::DiskANNBuildConfig +VectorDiskAnnIndex::parse_build_config(const Config& config) { + Config build_config = config; + parse_config(build_config); + + // set disk ann build config + knowhere::DiskANNBuildConfig build_disk_ann_config; + + // set max degree + auto max_degree = GetValueFromConfig(build_config, DISK_ANN_MAX_DEGREE); + AssertInfo(max_degree.has_value(), "param " + std::string(DISK_ANN_MAX_DEGREE) + "is empty"); + build_disk_ann_config.max_degree = max_degree.value(); + + // set build list + auto search_list_size = GetValueFromConfig(build_config, DISK_ANN_BUILD_LIST); + AssertInfo(search_list_size.has_value(), "param " + std::string(DISK_ANN_BUILD_LIST) + "is empty"); + build_disk_ann_config.search_list_size = search_list_size.value(); + + // set search dram budget + auto search_dram_budget_gb = GetValueFromConfig(build_config, DISK_ANN_SEARCH_DRAM_BUDGET); + AssertInfo(search_dram_budget_gb.has_value(), "param " + std::string(DISK_ANN_SEARCH_DRAM_BUDGET) + "is empty"); + build_disk_ann_config.pq_code_budget_gb = search_dram_budget_gb.value(); + + // set build dram budget + auto build_dram_budget_gb = GetValueFromConfig(build_config, DISK_ANN_BUILD_DRAM_BUDGET); + AssertInfo(build_dram_budget_gb.has_value(), "param " + std::string(DISK_ANN_BUILD_DRAM_BUDGET) + "is empty"); + build_disk_ann_config.build_dram_budget_gb = build_dram_budget_gb.value(); + + // set num build thread + auto num_threads = GetValueFromConfig(build_config, DISK_ANN_BUILD_THREAD_NUM); + AssertInfo(num_threads.has_value(), "param " + std::string(DISK_ANN_BUILD_THREAD_NUM) + "is empty"); + build_disk_ann_config.num_threads = num_threads.value(); + + // set pq bytes + auto pq_disk_bytes = GetValueFromConfig(build_config, DISK_ANN_PQ_BYTES); + AssertInfo(pq_disk_bytes.has_value(), "param " + std::string(DISK_ANN_PQ_BYTES) + "is empty"); + build_disk_ann_config.disk_pq_dims = pq_disk_bytes.value(); + + return build_disk_ann_config; +} + +template +knowhere::DiskANNPrepareConfig +VectorDiskAnnIndex::parse_prepare_config(const Config& config) { + Config prepare_config = config; + auto dim = GetDimFromConfig(prepare_config); + parse_config(prepare_config); + + knowhere::DiskANNPrepareConfig prepare_disk_ann_config; + prepare_disk_ann_config.warm_up = false; + prepare_disk_ann_config.use_bfs_cache = false; + + // set prepare thread num + auto num_threads = GetValueFromConfig(prepare_config, DISK_ANN_PREPARE_THREAD_NUM); + AssertInfo(num_threads.has_value(), "param " + std::string(DISK_ANN_PREPARE_THREAD_NUM) + "is empty"); + prepare_disk_ann_config.num_threads = num_threads.value(); + + // get max degree + auto max_degree = GetValueFromConfig(prepare_config, DISK_ANN_MAX_DEGREE); + AssertInfo(max_degree.has_value(), "param " + std::string(DISK_ANN_MAX_DEGREE) + "is empty"); + + // set prepare cached node + auto num_rows = GetValueFromConfig(prepare_config, NUM_ROW_OF_RAW_DATA); + AssertInfo(num_rows.has_value(), "param " + std::string(NUM_ROW_OF_RAW_DATA) + "is empty"); + + prepare_disk_ann_config.search_cache_budget_gb = + (dim + max_degree.value() + 1) * sizeof(float) * 1.2 * num_rows.value() * 0.1 / 1024 / 1024 / 1024; + + return prepare_disk_ann_config; +} + +template +void +VectorDiskAnnIndex::parse_config(Config& config) { + auto stoi_closure = [](const std::string& s) -> uint32_t { return std::stoi(s); }; + auto stof_closure = [](const std::string& s) -> float { return std::stof(s); }; + + /***************************** meta *******************************/ + CheckParameter(config, knowhere::meta::SLICE_SIZE, stoi_closure, + std::optional{config::KnowhereGetIndexSliceSize()}); + CheckParameter(config, knowhere::meta::DIM, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::meta::TOPK, stoi_closure, std::nullopt); + + /************************** DiskAnn build Params ************************/ + CheckParameter(config, DISK_ANN_MAX_DEGREE, stoi_closure, std::optional{48}); + CheckParameter(config, DISK_ANN_BUILD_LIST, stoi_closure, std::optional{128}); + CheckParameter(config, DISK_ANN_SEARCH_DRAM_BUDGET, stof_closure, std::optional{0.03}); + CheckParameter(config, DISK_ANN_BUILD_DRAM_BUDGET, stof_closure, std::optional{32}); + CheckParameter(config, DISK_ANN_BUILD_THREAD_NUM, stoi_closure, std::optional{8}); + CheckParameter(config, DISK_ANN_PQ_BYTES, stoi_closure, std::optional{0}); + + /************************** DiskAnn prepare Params ************************/ + CheckParameter(config, DISK_ANN_PREPARE_THREAD_NUM, stoi_closure, std::optional{8}); + CheckParameter(config, NUM_ROW_OF_RAW_DATA, stoi_closure, std::nullopt); + + /************************** DiskAnn query Params ************************/ + // CheckParameter(config, DISK_ANN_QUERY_LIST, stoi_closure, std::nullopt); + // CheckParameter(config, DISK_ANN_QUERY_BEAMWIDTH, stoi_closure, std::optional{16}); +} + +template class VectorDiskAnnIndex; + +#endif + +} // namespace milvus::index diff --git a/internal/core/src/index/VectorDiskIndex.h b/internal/core/src/index/VectorDiskIndex.h new file mode 100644 index 0000000000000..bae3615802233 --- /dev/null +++ b/internal/core/src/index/VectorDiskIndex.h @@ -0,0 +1,84 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "index/VectorIndex.h" +#include "storage/DiskFileManagerImpl.h" +#include "knowhere/index/vector_index/IndexDiskANN.h" +#include "knowhere/index/vector_index/IndexDiskANNConfig.h" + +namespace milvus::index { + +#ifdef BUILD_DISK_ANN + +template +class VectorDiskAnnIndex : public VectorIndex { + public: + explicit VectorDiskAnnIndex(const IndexType& index_type, + const MetricType& metric_type, + const IndexMode& index_mode, + storage::FileManagerImplPtr file_manager); + BinarySet + Serialize(const Config& config) override { + auto remote_paths_to_size = file_manager_->GetRemotePathsToFileSize(); + BinarySet binary_set; + for (auto& file : remote_paths_to_size) { + binary_set.Append(file.first, nullptr, file.second); + } + + return binary_set; + } + + int64_t + Count() override { + return index_->Count(); + } + + void + Load(const BinarySet& binary_set /* not used */, const Config& config = {}) override; + + void + BuildWithDataset(const DatasetPtr& dataset, const Config& config = {}) override; + + std::unique_ptr + Query(const DatasetPtr dataset, const SearchInfo& search_info, const BitsetView& bitset) override; + + void + CleanLocalData() override; + + private: + knowhere::DiskANNBuildConfig + parse_build_config(const Config& config); + + knowhere::DiskANNPrepareConfig + parse_prepare_config(const Config& config); + + void + parse_config(Config& config); + + private: + std::unique_ptr> index_; + std::shared_ptr file_manager_; +}; + +template +using VectorDiskAnnIndexPtr = std::unique_ptr>; +#endif + +} // namespace milvus::index diff --git a/internal/core/src/index/VectorIndex.h b/internal/core/src/index/VectorIndex.h new file mode 100644 index 0000000000000..dc09a66eabfb2 --- /dev/null +++ b/internal/core/src/index/VectorIndex.h @@ -0,0 +1,85 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include + +#include "knowhere/index/VecIndex.h" +#include "index/Index.h" +#include "common/Types.h" +#include "common/BitsetView.h" +#include "common/QueryResult.h" +#include "common/QueryInfo.h" + +namespace milvus::index { + +class VectorIndex : public IndexBase { + public: + explicit VectorIndex(const IndexType& index_type, const IndexMode& index_mode, const MetricType& metric_type) + : index_type_(index_type), index_mode_(index_mode), metric_type_(metric_type) { + } + + public: + void + BuildWithRawData(size_t n, const void* values, const Config& config = {}) override { + PanicInfo("vector index don't support build index with raw data"); + }; + + virtual std::unique_ptr + Query(const DatasetPtr dataset, const SearchInfo& search_info, const BitsetView& bitset) = 0; + + IndexType + GetIndexType() const { + return index_type_; + } + + MetricType + GetMetricType() const { + return metric_type_; + } + + IndexMode + GetIndexMode() const { + return index_mode_; + } + + int64_t + GetDim() const { + return dim_; + } + + void + SetDim(int64_t dim) { + dim_ = dim; + } + + virtual void + CleanLocalData() { + } + + private: + IndexType index_type_; + IndexMode index_mode_; + MetricType metric_type_; + int64_t dim_; +}; + +using VectorIndexPtr = std::unique_ptr; +} // namespace milvus::index diff --git a/internal/core/src/index/VectorMemIndex.cpp b/internal/core/src/index/VectorMemIndex.cpp new file mode 100644 index 0000000000000..c0ce073c0f753 --- /dev/null +++ b/internal/core/src/index/VectorMemIndex.cpp @@ -0,0 +1,218 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "index/VectorMemIndex.h" +#include "index/Meta.h" +#include "index/Utils.h" +#include "exceptions/EasyAssert.h" +#include "config/ConfigKnowhere.h" + +#include "knowhere/index/VecIndexFactory.h" +#include "knowhere/common/Timer.h" +#include "common/BitsetView.h" +#include "knowhere/index/vector_index/ConfAdapterMgr.h" +#include "knowhere/index/vector_index/adapter/VectorAdapter.h" +#include "pb/index_cgo_msg.pb.h" + +namespace milvus::index { + +VectorMemIndex::VectorMemIndex(const IndexType& index_type, const MetricType& metric_type, const IndexMode& index_mode) + : VectorIndex(index_type, index_mode, metric_type) { + AssertInfo(!is_unsupported(index_type, metric_type), index_type + " doesn't support metric: " + metric_type); + + index_ = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(GetIndexType(), index_mode); + AssertInfo(index_ != nullptr, "[VecIndexCreator]Index is null after create index"); +} + +BinarySet +VectorMemIndex::Serialize(const Config& config) { + knowhere::Config serialize_config = config; + parse_config(serialize_config); + + auto ret = index_->Serialize(serialize_config); + auto index_type = GetIndexType(); + + if (is_in_nm_list(index_type)) { + auto deleter = [&](uint8_t*) {}; // avoid repeated deconstruction + auto raw_data = std::shared_ptr(static_cast(raw_data_.data()), deleter); + + // std::shared_ptr raw_data(new uint8_t[raw_data_.size()], std::default_delete()); + // memcpy(raw_data.get(), raw_data_.data(), raw_data_.size()); + ret.Append(RAW_DATA, raw_data, raw_data_.size()); + // Disassemble will only divide the raw vectors, other keys were already divided + knowhere::Disassemble(ret, serialize_config); + } + return ret; +} + +void +VectorMemIndex::Load(const BinarySet& binary_set, const Config& config) { + auto& map_ = binary_set.binary_map_; + for (auto it = map_.begin(); it != map_.end(); ++it) { + if (it->first == RAW_DATA) { + raw_data_.clear(); + auto data_size = it->second->size; + raw_data_.resize(data_size); + memcpy(raw_data_.data(), it->second->data.get(), data_size); + break; + } + } + index_->Load(binary_set); + SetDim(index_->Dim()); +} + +void +VectorMemIndex::BuildWithDataset(const DatasetPtr& dataset, const Config& config) { + knowhere::Config index_config; + index_config.update(config); + parse_config(index_config); + + SetDim(knowhere::GetDatasetDim(dataset)); + knowhere::SetMetaRows(index_config, knowhere::GetDatasetRows(dataset)); + if (GetIndexType() == knowhere::IndexEnum::INDEX_FAISS_IVFPQ) { + if (!config.contains(knowhere::indexparam::NBITS)) { + knowhere::SetIndexParamNbits(index_config, 8); + } + } + auto conf_adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(GetIndexType()); + AssertInfo(conf_adapter->CheckTrain(index_config, GetIndexMode()), "something wrong in index parameters!"); + + knowhere::TimeRecorder rc("BuildWithoutIds", 1); + index_->BuildAll(dataset, index_config); + rc.RecordSection("TrainAndAdd"); + + if (is_in_nm_list(GetIndexType())) { + store_raw_data(dataset); + rc.RecordSection("store_raw_data"); + } + rc.ElapseFromBegin("Done"); + SetDim(index_->Dim()); +} + +std::unique_ptr +VectorMemIndex::Query(const DatasetPtr dataset, const SearchInfo& search_info, const BitsetView& bitset) { + // AssertInfo(GetMetricType() == search_info.metric_type_, + // "Metric type of field index isn't the same with search info"); + + auto load_raw_data_closure = [&]() { LoadRawData(); }; // hide this pointer + auto index_type = GetIndexType(); + if (is_in_nm_list(index_type)) { + std::call_once(raw_data_loaded_, load_raw_data_closure); + } + + auto num_queries = knowhere::GetDatasetRows(dataset); + Config search_conf = search_info.search_params_; + auto topk = search_info.topk_; + // TODO :: check dim of search data + auto final = [&] { + knowhere::SetMetaTopk(search_conf, topk); + knowhere::SetMetaMetricType(search_conf, GetMetricType()); + auto index_type = GetIndexType(); + auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_type); + try { + adapter->CheckSearch(search_conf, index_type, GetIndexMode()); + } catch (std::exception& e) { + AssertInfo(false, e.what()); + } + return index_->Query(dataset, search_conf, bitset); + }(); + + auto ids = knowhere::GetDatasetIDs(final); + float* distances = (float*)knowhere::GetDatasetDistance(final); + + auto round_decimal = search_info.round_decimal_; + auto total_num = num_queries * topk; + + if (round_decimal != -1) { + const float multiplier = pow(10.0, round_decimal); + for (int i = 0; i < total_num; i++) { + distances[i] = round(distances[i] * multiplier) / multiplier; + } + } + auto result = std::make_unique(); + result->seg_offsets_.resize(total_num); + result->distances_.resize(total_num); + result->total_nq_ = num_queries; + result->unity_topK_ = topk; + + std::copy_n(ids, total_num, result->seg_offsets_.data()); + std::copy_n(distances, total_num, result->distances_.data()); + + return result; +} + +void +VectorMemIndex::store_raw_data(const knowhere::DatasetPtr& dataset) { + auto index_type = GetIndexType(); + if (is_in_nm_list(index_type)) { + auto tensor = knowhere::GetDatasetTensor(dataset); + auto row_num = knowhere::GetDatasetRows(dataset); + auto dim = knowhere::GetDatasetDim(dataset); + int64_t data_size; + if (is_in_bin_list(index_type)) { + data_size = dim / 8 * row_num; + } else { + data_size = dim * row_num * sizeof(float); + } + raw_data_.resize(data_size); + memcpy(raw_data_.data(), tensor, data_size); + } +} + +void +VectorMemIndex::LoadRawData() { + auto index_type = GetIndexType(); + if (is_in_nm_list(index_type)) { + auto bs = index_->Serialize(Config{knowhere::meta::SLICE_SIZE, config::KnowhereGetIndexSliceSize()}); + auto bptr = std::make_shared(); + auto deleter = [&](uint8_t*) {}; // avoid repeated deconstruction + bptr->data = std::shared_ptr(static_cast(raw_data_.data()), deleter); + bptr->size = raw_data_.size(); + bs.Append(RAW_DATA, bptr); + index_->Load(bs); + } +} + +void +VectorMemIndex::parse_config(Config& config) { + auto stoi_closure = [](const std::string& s) -> int { return std::stoi(s); }; + + /***************************** meta *******************************/ + CheckParameter(config, knowhere::meta::SLICE_SIZE, stoi_closure, + std::optional{config::KnowhereGetIndexSliceSize()}); + CheckParameter(config, knowhere::meta::DIM, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::meta::TOPK, stoi_closure, std::nullopt); + + /***************************** IVF Params *******************************/ + CheckParameter(config, knowhere::indexparam::NPROBE, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::NLIST, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::M, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::NBITS, stoi_closure, std::nullopt); + + /************************** PQ Params *****************************/ + CheckParameter(config, knowhere::indexparam::PQ_M, stoi_closure, std::nullopt); + + /************************** HNSW Params *****************************/ + CheckParameter(config, knowhere::indexparam::EFCONSTRUCTION, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::HNSW_M, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::EF, stoi_closure, std::nullopt); + + /************************** Annoy Params *****************************/ + CheckParameter(config, knowhere::indexparam::N_TREES, stoi_closure, std::nullopt); + CheckParameter(config, knowhere::indexparam::SEARCH_K, stoi_closure, std::nullopt); +} + +} // namespace milvus::index diff --git a/internal/core/src/index/VectorMemIndex.h b/internal/core/src/index/VectorMemIndex.h new file mode 100644 index 0000000000000..9cfb9c1c1b2db --- /dev/null +++ b/internal/core/src/index/VectorMemIndex.h @@ -0,0 +1,68 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include + +#include "index/VectorIndex.h" + +namespace milvus::index { + +class VectorMemIndex : public VectorIndex { + public: + explicit VectorMemIndex(const IndexType& index_type, const MetricType& metric_type, const IndexMode& index_mode); + + BinarySet + Serialize(const Config& config) override; + + void + Load(const BinarySet& binary_set, const Config& config = {}) override; + + void + BuildWithDataset(const DatasetPtr& dataset, const Config& config = {}) override; + + int64_t + Count() override { + return index_->Count(); + } + + std::unique_ptr + Query(const DatasetPtr dataset, const SearchInfo& search_info, const BitsetView& bitset) override; + + private: + void + store_raw_data(const knowhere::DatasetPtr& dataset); + + void + parse_config(Config& config); + + void + LoadRawData(); + + private: + Config config_; + knowhere::VecIndexPtr index_ = nullptr; + std::vector raw_data_; + std::once_flag raw_data_loaded_; +}; + +using VectorMemIndexPtr = std::unique_ptr; +} // namespace milvus::index diff --git a/internal/core/src/index/milvus_index.pc.in b/internal/core/src/index/milvus_index.pc.in new file mode 100644 index 0000000000000..ffc4559bdf2c2 --- /dev/null +++ b/internal/core/src/index/milvus_index.pc.in @@ -0,0 +1,9 @@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: Milvus index +Description: index modules for Milvus +Version: @MILVUS_VERSION@ + +Libs: -L${libdir} -lmilvus_index +Cflags: -I${includedir} diff --git a/internal/core/src/indexbuilder/CMakeLists.txt b/internal/core/src/indexbuilder/CMakeLists.txt index d4b3f53d35aae..cae7415c9ca0a 100644 --- a/internal/core/src/indexbuilder/CMakeLists.txt +++ b/internal/core/src/indexbuilder/CMakeLists.txt @@ -14,7 +14,6 @@ set(INDEXBUILDER_FILES VecIndexCreator.cpp index_c.cpp init_c.cpp - utils.cpp ScalarIndexCreator.cpp ) @@ -30,11 +29,8 @@ endif () # link order matters target_link_libraries(milvus_indexbuilder milvus_index - milvus_common - knowhere ${TBB} ${PLATFORM_LIBS} - pthread ) install(TARGETS milvus_indexbuilder DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/internal/core/src/indexbuilder/IndexCreatorBase.h b/internal/core/src/indexbuilder/IndexCreatorBase.h index 7180023d90835..15ce6e8a5c842 100644 --- a/internal/core/src/indexbuilder/IndexCreatorBase.h +++ b/internal/core/src/indexbuilder/IndexCreatorBase.h @@ -11,10 +11,8 @@ #pragma once -#include "knowhere/common/Dataset.h" -#include "knowhere/common/BinarySet.h" #include -#include +#include "common/Types.h" namespace milvus::indexbuilder { class IndexCreatorBase { @@ -22,17 +20,14 @@ class IndexCreatorBase { virtual ~IndexCreatorBase() = default; virtual void - Build(const knowhere::DatasetPtr& dataset) = 0; + Build(const milvus::DatasetPtr& dataset) = 0; - virtual knowhere::BinarySet + virtual milvus::BinarySet Serialize() = 0; // used for test. virtual void - Load(const knowhere::BinarySet&) = 0; - - // virtual knowhere::IndexPtr - // GetIndex() = 0; + Load(const milvus::BinarySet&) = 0; }; using IndexCreatorBasePtr = std::unique_ptr; diff --git a/internal/core/src/indexbuilder/IndexFactory.h b/internal/core/src/indexbuilder/IndexFactory.h index cded061e79b79..5896ac3de8720 100644 --- a/internal/core/src/indexbuilder/IndexFactory.h +++ b/internal/core/src/indexbuilder/IndexFactory.h @@ -40,28 +40,24 @@ class IndexFactory { IndexCreatorBasePtr CreateIndex(CDataType dtype, const char* type_params, const char* index_params) { - auto real_dtype = proto::schema::DataType(dtype); - auto invalid_dtype_msg = std::string("invalid data type: ") + std::to_string(real_dtype); + auto real_dtype = DataType(dtype); + auto invalid_dtype_msg = std::string("invalid data type: ") + std::to_string(int(real_dtype)); switch (real_dtype) { - case proto::schema::Bool: - case proto::schema::Int8: - case proto::schema::Int16: - case proto::schema::Int32: - case proto::schema::Int64: - case proto::schema::Float: - case proto::schema::Double: - case proto::schema::VarChar: - case proto::schema::String: - return CreateScalarIndex(dtype, type_params, index_params); + case DataType::BOOL: + case DataType::INT8: + case DataType::INT16: + case DataType::INT32: + case DataType::INT64: + case DataType::FLOAT: + case DataType::DOUBLE: + case DataType::VARCHAR: + case DataType::STRING: + return CreateScalarIndex(real_dtype, type_params, index_params); - case proto::schema::BinaryVector: - case proto::schema::FloatVector: - return std::make_unique(type_params, index_params); - - case proto::schema::None: - case proto::schema::DataType_INT_MIN_SENTINEL_DO_NOT_USE_: - case proto::schema::DataType_INT_MAX_SENTINEL_DO_NOT_USE_: + case DataType::VECTOR_FLOAT: + case DataType::VECTOR_BINARY: + return std::make_unique(real_dtype, type_params, index_params); default: throw std::invalid_argument(invalid_dtype_msg); } diff --git a/internal/core/src/indexbuilder/ScalarIndexCreator.cpp b/internal/core/src/indexbuilder/ScalarIndexCreator.cpp index 8ac230fde7c62..d9bae8995e94b 100644 --- a/internal/core/src/indexbuilder/ScalarIndexCreator.cpp +++ b/internal/core/src/indexbuilder/ScalarIndexCreator.cpp @@ -9,35 +9,53 @@ // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express // or implied. See the License for the specific language governing permissions and limitations under the License -#include "indexbuilder/helper.h" #include "indexbuilder/ScalarIndexCreator.h" #include "index/IndexFactory.h" +#include "index/IndexInfo.h" +#include "index/Meta.h" +#include "index/Utils.h" #include namespace milvus::indexbuilder { -ScalarIndexCreator::ScalarIndexCreator(CDataType dtype, const char* type_params, const char* index_params) { - dtype_ = dtype; +ScalarIndexCreator::ScalarIndexCreator(DataType dtype, const char* type_params, const char* index_params) + : dtype_(dtype) { // TODO: move parse-related logic to a common interface. - Helper::ParseFromString(type_params_, std::string(type_params)); - Helper::ParseFromString(index_params_, std::string(index_params)); - // TODO: create index according to the params. - index_ = scalar::IndexFactory::GetInstance().CreateIndex(dtype_, index_type()); + milvus::index::ParseFromString(type_params_, std::string(type_params)); + milvus::index::ParseFromString(index_params_, std::string(index_params)); + + for (auto i = 0; i < type_params_.params_size(); ++i) { + const auto& param = type_params_.params(i); + config_[param.key()] = param.value(); + } + + for (auto i = 0; i < index_params_.params_size(); ++i) { + const auto& param = index_params_.params(i); + config_[param.key()] = param.value(); + } + + milvus::index::CreateIndexInfo index_info; + index_info.field_type = dtype_; + index_info.index_type = index_type(); + index_info.index_mode = IndexMode::MODE_CPU; + index_ = index::IndexFactory::GetInstance().CreateIndex(index_info, nullptr); } void -ScalarIndexCreator::Build(const knowhere::DatasetPtr& dataset) { - index_->BuildWithDataset(dataset); +ScalarIndexCreator::Build(const milvus::DatasetPtr& dataset) { + auto size = knowhere::GetDatasetRows(dataset); + auto data = knowhere::GetDatasetTensor(dataset); + index_->BuildWithRawData(size, data); } -knowhere::BinarySet +milvus::BinarySet ScalarIndexCreator::Serialize() { return index_->Serialize(config_); } void -ScalarIndexCreator::Load(const knowhere::BinarySet& binary_set) { +ScalarIndexCreator::Load(const milvus::BinarySet& binary_set) { index_->Load(binary_set); } diff --git a/internal/core/src/indexbuilder/ScalarIndexCreator.h b/internal/core/src/indexbuilder/ScalarIndexCreator.h index c0be9730fb5c8..d66038ae61e96 100644 --- a/internal/core/src/indexbuilder/ScalarIndexCreator.h +++ b/internal/core/src/indexbuilder/ScalarIndexCreator.h @@ -23,33 +23,33 @@ namespace milvus::indexbuilder { class ScalarIndexCreator : public IndexCreatorBase { public: - ScalarIndexCreator(CDataType dtype, const char* type_params, const char* index_params); + ScalarIndexCreator(DataType data_type, const char* type_params, const char* index_params); void - Build(const knowhere::DatasetPtr& dataset) override; + Build(const milvus::DatasetPtr& dataset) override; - knowhere::BinarySet + milvus::BinarySet Serialize() override; void - Load(const knowhere::BinarySet&) override; + Load(const milvus::BinarySet&) override; private: std::string index_type(); private: - scalar::IndexBasePtr index_ = nullptr; + index::IndexBasePtr index_ = nullptr; proto::indexcgo::TypeParams type_params_; proto::indexcgo::IndexParams index_params_; - knowhere::Config config_; - CDataType dtype_; + Config config_; + DataType dtype_; }; using ScalarIndexCreatorPtr = std::unique_ptr; inline ScalarIndexCreatorPtr -CreateScalarIndex(CDataType dtype, const char* type_params, const char* index_params) { +CreateScalarIndex(DataType dtype, const char* type_params, const char* index_params) { return std::make_unique(dtype, type_params, index_params); } diff --git a/internal/core/src/indexbuilder/VecIndexCreator.cpp b/internal/core/src/indexbuilder/VecIndexCreator.cpp index 14b79ad9d99bb..0cede95a3eda3 100644 --- a/internal/core/src/indexbuilder/VecIndexCreator.cpp +++ b/internal/core/src/indexbuilder/VecIndexCreator.cpp @@ -9,323 +9,85 @@ // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express // or implied. See the License for the specific language governing permissions and limitations under the License -#include #include -#include #include "exceptions/EasyAssert.h" #include "indexbuilder/VecIndexCreator.h" -#include "indexbuilder/utils.h" -#include "knowhere/common/Timer.h" -#include "knowhere/index/VecIndex.h" -#include "knowhere/index/VecIndexFactory.h" -#include "knowhere/index/vector_index/ConfAdapterMgr.h" -#include "knowhere/index/vector_index/adapter/VectorAdapter.h" -#include "knowhere/index/vector_index/helpers/IndexParameter.h" -#include "pb/index_cgo_msg.pb.h" +#include "index/Utils.h" +#include "index/IndexFactory.h" -namespace milvus::indexbuilder { - -VecIndexCreator::VecIndexCreator(const char* serialized_type_params, const char* serialized_index_params) { - type_params_ = std::string(serialized_type_params); - index_params_ = std::string(serialized_index_params); - - parse(); - - auto index_mode = get_index_mode(); - auto index_type = get_index_type(); - auto metric_type = get_metric_type(); - AssertInfo(!is_unsupported(index_type, metric_type), index_type + " doesn't support metric: " + metric_type); +#ifdef BUILD_DISK_ANN +#include "storage/DiskFileManagerImpl.h" +#endif - index_ = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(get_index_type(), index_mode); - AssertInfo(index_ != nullptr, "[VecIndexCreator]Index is null after create index"); -} - -template -// ugly here, ParamsT will just be MapParams later -void -VecIndexCreator::parse_impl(const std::string& serialized_params_str, knowhere::Config& conf) { - bool deserialized_success; +namespace milvus::indexbuilder { - ParamsT params; - deserialized_success = google::protobuf::TextFormat::ParseFromString(serialized_params_str, ¶ms); - AssertInfo(deserialized_success, "[VecIndexCreator]Deserialize params failed"); +VecIndexCreator::VecIndexCreator(DataType data_type, + const char* serialized_type_params, + const char* serialized_index_params) + : data_type_(data_type) { + milvus::index::ParseFromString(type_params_, std::string(serialized_type_params)); + milvus::index::ParseFromString(index_params_, std::string(serialized_index_params)); - for (auto i = 0; i < params.params_size(); ++i) { - const auto& param = params.params(i); - const auto& key = param.key(); - const auto& value = param.value(); - conf[key] = value; + for (auto i = 0; i < type_params_.params_size(); ++i) { + const auto& param = type_params_.params(i); + config_[param.key()] = param.value(); } - auto stoi_closure = [](const std::string& s) -> int { return std::stoi(s); }; - auto stof_closure = [](const std::string& s) -> float { return std::stof(s); }; - - /***************************** meta *******************************/ - check_parameter(conf, knowhere::meta::SLICE_SIZE, stoi_closure, std::optional{4}); - check_parameter(conf, knowhere::meta::DIM, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::meta::TOPK, stoi_closure, std::nullopt); - - /***************************** IVF Params *******************************/ - check_parameter(conf, knowhere::indexparam::NPROBE, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::NLIST, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::M, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::NBITS, stoi_closure, std::nullopt); - - /************************** PQ Params *****************************/ - check_parameter(conf, knowhere::indexparam::PQ_M, stoi_closure, std::nullopt); - - /************************** HNSW Params *****************************/ - check_parameter(conf, knowhere::indexparam::EFCONSTRUCTION, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::HNSW_M, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::EF, stoi_closure, std::nullopt); - - /************************** Annoy Params *****************************/ - check_parameter(conf, knowhere::indexparam::N_TREES, stoi_closure, std::nullopt); - check_parameter(conf, knowhere::indexparam::SEARCH_K, stoi_closure, std::nullopt); -} - -void -VecIndexCreator::parse() { - namespace indexcgo = milvus::proto::indexcgo; - - parse_impl(type_params_, type_config_); - parse_impl(index_params_, index_config_); - - config_.update(type_config_); // just like dict().update in Python, amazing - config_.update(index_config_); -} - -template -void -VecIndexCreator::check_parameter(knowhere::Config& conf, - const std::string& key, - std::function fn, - std::optional default_v) { - if (!conf.contains(key)) { - if (default_v.has_value()) { - conf[key] = default_v.value(); - } - } else { - auto value = conf[key]; - conf[key] = fn(value); + for (auto i = 0; i < index_params_.params_size(); ++i) { + const auto& param = index_params_.params(i); + config_[param.key()] = param.value(); } -} -template -std::optional -VecIndexCreator::get_config_by_name(const std::string& name) { - if (config_.contains(name)) { - return knowhere::GetValueFromConfig(config_, name); + index::CreateIndexInfo index_info; + index_info.field_type = data_type_; + index_info.index_mode = index::GetIndexModeFromConfig(config_); + index_info.index_type = index::GetIndexTypeFromConfig(config_); + index_info.metric_type = index::GetMetricTypeFromConfig(config_); + + std::shared_ptr file_manager = nullptr; +#ifdef BUILD_DISK_ANN + if (index::is_in_disk_list(index_info.index_type)) { + // For now, only support diskann index + file_manager = std::make_shared(index::GetFieldDataMetaFromConfig(config_), + index::GetIndexMetaFromConfig(config_)); } - return std::nullopt; +#endif + + index_ = index::IndexFactory::GetInstance().CreateIndex(index_info, file_manager); + AssertInfo(index_ != nullptr, "[VecIndexCreator]Index is null after create index"); } int64_t VecIndexCreator::dim() { - auto dimension = get_config_by_name(knowhere::meta::DIM); - AssertInfo(dimension.has_value(), "[VecIndexCreator]Dimension doesn't have value"); - return (dimension.value()); -} - -void -VecIndexCreator::BuildWithoutIds(const knowhere::DatasetPtr& dataset) { - auto index_type = get_index_type(); - auto index_mode = get_index_mode(); - knowhere::SetMetaRows(config_, knowhere::GetDatasetRows(dataset)); - if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFPQ) { - if (!config_.contains(knowhere::indexparam::NBITS)) { - knowhere::SetIndexParamNbits(config_, 8); - } - } - auto conf_adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_type); - // TODO: Use easylogging instead, if you really need to keep this log. - // std::cout << "Konwhere BuildWithoutIds config_ is " << config_ << std::endl; - AssertInfo(conf_adapter->CheckTrain(config_, index_mode), "something wrong in index parameters!"); - - if (is_in_need_id_list(index_type)) { - PanicInfo(std::string(index_type) + " doesn't support build without ids yet!"); - } - knowhere::TimeRecorder rc("BuildWithoutIds", 1); - // if (is_in_need_build_all_list(index_type)) { - // index_->BuildAll(dataset, config_); - // } else { - // index_->Train(dataset, config_); - // index_->AddWithoutIds(dataset, config_); - // } - index_->BuildAll(dataset, config_); - rc.RecordSection("TrainAndAdd"); - - if (is_in_nm_list(index_type)) { - StoreRawData(dataset); - rc.RecordSection("StoreRawData"); - } - rc.ElapseFromBegin("Done"); -} - -void -VecIndexCreator::BuildWithIds(const knowhere::DatasetPtr& dataset) { - auto index_type = get_index_type(); - auto index_mode = get_index_mode(); - knowhere::SetMetaRows(config_, knowhere::GetDatasetRows(dataset)); - if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFPQ) { - if (!config_.contains(knowhere::indexparam::NBITS)) { - knowhere::SetIndexParamNbits(config_, 8); - } - } - auto conf_adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_type); - AssertInfo(conf_adapter->CheckTrain(config_, index_mode), "something wrong in index parameters!"); - // index_->Train(dataset, config_); - // index_->Add(dataset, config_); - index_->BuildAll(dataset, config_); - - if (is_in_nm_list(get_index_type())) { - StoreRawData(dataset); - } + return index::GetDimFromConfig(config_); } void -VecIndexCreator::StoreRawData(const knowhere::DatasetPtr& dataset) { - auto index_type = get_index_type(); - if (is_in_nm_list(index_type)) { - auto tensor = knowhere::GetDatasetTensor(dataset); - auto row_num = knowhere::GetDatasetRows(dataset); - auto dim = knowhere::GetDatasetDim(dataset); - int64_t data_size; - if (is_in_bin_list(index_type)) { - data_size = dim / 8 * row_num; - } else { - data_size = dim * row_num * sizeof(float); - } - raw_data_.resize(data_size); - memcpy(raw_data_.data(), tensor, data_size); - } +VecIndexCreator::Build(const milvus::DatasetPtr& dataset) { + index_->BuildWithDataset(dataset, config_); } -knowhere::BinarySet +milvus::BinarySet VecIndexCreator::Serialize() { - auto ret = index_->Serialize(config_); - auto index_type = get_index_type(); - - if (is_in_nm_list(index_type)) { - std::shared_ptr raw_data(new uint8_t[raw_data_.size()], std::default_delete()); - memcpy(raw_data.get(), raw_data_.data(), raw_data_.size()); - ret.Append(RAW_DATA, raw_data, raw_data_.size()); - // https://github.com/milvus-io/milvus/issues/6421 - // Disassemble will only divide the raw vectors, other keys were already divided - knowhere::Disassemble(ret, config_); - } - return ret; + return index_->Serialize(config_); } void -VecIndexCreator::Load(const knowhere::BinarySet& binary_set) { - auto& map_ = binary_set.binary_map_; - for (auto it = map_.begin(); it != map_.end(); ++it) { - if (it->first == RAW_DATA) { - raw_data_.clear(); - auto data_size = it->second->size; - raw_data_.resize(data_size); - memcpy(raw_data_.data(), it->second->data.get(), data_size); - break; - } - } - index_->Load(binary_set); -} - -std::string -VecIndexCreator::get_index_type() { - // return index_->index_type(); - // knowhere bug here - // the index_type of all ivf-based index will change to ivf flat after loaded - auto type = get_config_by_name("index_type"); - return type.has_value() ? type.value() : knowhere::IndexEnum::INDEX_FAISS_IVFPQ; -} - -std::string -VecIndexCreator::get_metric_type() { - auto type = get_config_by_name(knowhere::meta::METRIC_TYPE); - if (type.has_value()) { - return type.value(); - } else { - auto index_type = get_index_type(); - if (is_in_bin_list(index_type)) { - return knowhere::metric::JACCARD; - } else { - return knowhere::metric::L2; - } - } +VecIndexCreator::Load(const milvus::BinarySet& binary_set) { + index_->Load(binary_set, config_); } -knowhere::IndexMode -VecIndexCreator::get_index_mode() { - static std::map mode_map = { - {"CPU", knowhere::IndexMode::MODE_CPU}, - {"GPU", knowhere::IndexMode::MODE_GPU}, - }; - auto mode = get_config_by_name("index_mode"); - return mode.has_value() ? mode_map[mode.value()] : knowhere::IndexMode::MODE_CPU; -} - -int64_t -VecIndexCreator::get_index_file_slice_size() { - if (knowhere::CheckKeyInConfig(config_, knowhere::meta::SLICE_SIZE)) { - return knowhere::GetMetaSliceSize(config_); - } - return knowhere::index_file_slice_size; // by default -} - -std::unique_ptr -VecIndexCreator::Query(const knowhere::DatasetPtr& dataset) { - return std::move(QueryImpl(dataset, config_)); -} - -std::unique_ptr -VecIndexCreator::QueryWithParam(const knowhere::DatasetPtr& dataset, const char* serialized_search_params) { - namespace indexcgo = milvus::proto::indexcgo; - knowhere::Config search_conf; - parse_impl(std::string(serialized_search_params), search_conf); - - return std::move(QueryImpl(dataset, search_conf)); -} - -std::unique_ptr -VecIndexCreator::QueryImpl(const knowhere::DatasetPtr& dataset, const knowhere::Config& conf) { - auto load_raw_data_closure = [&]() { LoadRawData(); }; // hide this pointer - auto index_type = get_index_type(); - if (is_in_nm_list(index_type)) { - std::call_once(raw_data_loaded_, load_raw_data_closure); - } - - auto res = index_->Query(dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(res); - auto distances = knowhere::GetDatasetDistance(res); - auto nq = knowhere::GetDatasetRows(dataset); - auto k = knowhere::GetMetaTopk(config_); - - auto query_res = std::make_unique(); - query_res->nq = nq; - query_res->topk = k; - query_res->ids.resize(nq * k); - query_res->distances.resize(nq * k); - memcpy(query_res->ids.data(), ids, sizeof(int64_t) * nq * k); - memcpy(query_res->distances.data(), distances, sizeof(float) * nq * k); - - return std::move(query_res); +std::unique_ptr +VecIndexCreator::Query(const milvus::DatasetPtr& dataset, const SearchInfo& search_info, const BitsetView& bitset) { + auto vector_index = dynamic_cast(index_.get()); + return vector_index->Query(dataset, search_info, bitset); } void -VecIndexCreator::LoadRawData() { - auto index_type = get_index_type(); - if (is_in_nm_list(index_type)) { - auto bs = index_->Serialize(config_); - auto bptr = std::make_shared(); - auto deleter = [&](uint8_t*) {}; // avoid repeated deconstruction - bptr->data = std::shared_ptr(static_cast(raw_data_.data()), deleter); - bptr->size = raw_data_.size(); - bs.Append(RAW_DATA, bptr); - index_->Load(bs); - } +VecIndexCreator::CleanLocalData() { + auto vector_index = dynamic_cast(index_.get()); + vector_index->CleanLocalData(); } } // namespace milvus::indexbuilder diff --git a/internal/core/src/indexbuilder/VecIndexCreator.h b/internal/core/src/indexbuilder/VecIndexCreator.h index d1a6ce50316f3..14cfe30dc9762 100644 --- a/internal/core/src/indexbuilder/VecIndexCreator.h +++ b/internal/core/src/indexbuilder/VecIndexCreator.h @@ -17,101 +17,44 @@ #include #include "indexbuilder/IndexCreatorBase.h" -#include "knowhere/common/BinarySet.h" -#include "knowhere/index/VecIndex.h" +#include "index/VectorIndex.h" +#include "index/IndexInfo.h" +#include "pb/index_cgo_msg.pb.h" namespace milvus::indexbuilder { // TODO: better to distinguish binary vec & float vec. class VecIndexCreator : public IndexCreatorBase { public: - explicit VecIndexCreator(const char* serialized_type_params, const char* serialized_index_params); + explicit VecIndexCreator(DataType data_type, + const char* serialized_type_params, + const char* serialized_index_params); void - Build(const knowhere::DatasetPtr& dataset) override { - BuildWithoutIds(dataset); - } + Build(const milvus::DatasetPtr& dataset) override; - knowhere::BinarySet + milvus::BinarySet Serialize() override; void - Load(const knowhere::BinarySet& binary_set) override; + Load(const milvus::BinarySet& binary_set) override; int64_t dim(); - public: - // used for tests - struct QueryResult { - std::vector ids; - std::vector distances; - int64_t nq; - int64_t topk; - }; - - std::unique_ptr - Query(const knowhere::DatasetPtr& dataset); - - std::unique_ptr - QueryWithParam(const knowhere::DatasetPtr& dataset, const char* serialized_search_params); - - private: - void - parse(); - - std::string - get_index_type(); - - std::string - get_metric_type(); - - knowhere::IndexMode - get_index_mode(); - - int64_t - get_index_file_slice_size(); - - template - std::optional - get_config_by_name(const std::string& name); - - void - StoreRawData(const knowhere::DatasetPtr& dataset); - - void - LoadRawData(); - - template - void - check_parameter(knowhere::Config& conf, - const std::string& key, - std::function fn, - std::optional default_v = std::nullopt); - - template - void - parse_impl(const std::string& serialized_params_str, knowhere::Config& conf); - - std::unique_ptr - QueryImpl(const knowhere::DatasetPtr& dataset, const knowhere::Config& conf); + std::unique_ptr + Query(const milvus::DatasetPtr& dataset, const SearchInfo& search_info, const BitsetView& bitset); public: void - BuildWithIds(const knowhere::DatasetPtr& dataset); - - void - BuildWithoutIds(const knowhere::DatasetPtr& dataset); + CleanLocalData(); private: - knowhere::VecIndexPtr index_ = nullptr; - std::string type_params_; - std::string index_params_; - knowhere::Config type_config_; - knowhere::Config index_config_; - knowhere::Config config_; - std::vector raw_data_; - std::once_flag raw_data_loaded_; + milvus::index::IndexBasePtr index_ = nullptr; + proto::indexcgo::TypeParams type_params_; + proto::indexcgo::IndexParams index_params_; + Config config_; + DataType data_type_; }; } // namespace milvus::indexbuilder diff --git a/internal/core/src/indexbuilder/helper.h b/internal/core/src/indexbuilder/helper.h deleted file mode 100644 index dd8efba40ba8c..0000000000000 --- a/internal/core/src/indexbuilder/helper.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License - -#pragma once - -#include "pb/index_cgo_msg.pb.h" -#include "exceptions/EasyAssert.h" -#include -#include -#include - -namespace milvus::indexbuilder { - -using MapParams = std::map; - -struct Helper { - static void - ParseFromString(google::protobuf::Message& params, const std::string& str) { - auto ok = google::protobuf::TextFormat::ParseFromString(str, ¶ms); - AssertInfo(ok, "failed to parse params from string"); - } - - static void - ParseParams(google::protobuf::Message& params, const void* data, const size_t size) { - auto ok = params.ParseFromArray(data, size); - AssertInfo(ok, "failed to parse params from array"); - } -}; - -} // namespace milvus::indexbuilder diff --git a/internal/core/src/indexbuilder/index_c.cpp b/internal/core/src/indexbuilder/index_c.cpp index 1ca4e37415f57..0d13e2a68dde2 100644 --- a/internal/core/src/indexbuilder/index_c.cpp +++ b/internal/core/src/indexbuilder/index_c.cpp @@ -159,146 +159,13 @@ LoadIndexFromBinarySet(CIndex index, CBinarySet c_binary_set) { } CStatus -QueryOnFloatVecIndex(CIndex index, int64_t float_value_num, const float* vectors, CIndexQueryResult* res) { +CleanLocalData(CIndex index) { auto status = CStatus(); try { - auto cIndex = (milvus::indexbuilder::VecIndexCreator*)index; - auto dim = cIndex->dim(); - auto row_nums = float_value_num / dim; - auto query_ds = knowhere::GenDataset(row_nums, dim, vectors); - auto query_res = cIndex->Query(query_ds); - *res = query_res.release(); - - status.error_code = Success; - status.error_msg = ""; - } catch (std::exception& e) { - status.error_code = UnexpectedError; - status.error_msg = strdup(e.what()); - } - return status; -} - -CStatus -QueryOnFloatVecIndexWithParam(CIndex index, - int64_t float_value_num, - const float* vectors, - const char* serialized_search_params, - CIndexQueryResult* res) { - auto status = CStatus(); - try { - auto cIndex = (milvus::indexbuilder::VecIndexCreator*)index; - auto dim = cIndex->dim(); - auto row_nums = float_value_num / dim; - auto query_ds = knowhere::GenDataset(row_nums, dim, vectors); - auto query_res = cIndex->QueryWithParam(query_ds, serialized_search_params); - *res = query_res.release(); - - status.error_code = Success; - status.error_msg = ""; - } catch (std::exception& e) { - status.error_code = UnexpectedError; - status.error_msg = strdup(e.what()); - } - return status; -} - -CStatus -QueryOnBinaryVecIndex(CIndex index, int64_t data_size, const uint8_t* vectors, CIndexQueryResult* res) { - auto status = CStatus(); - try { - auto cIndex = (milvus::indexbuilder::VecIndexCreator*)index; - auto dim = cIndex->dim(); - auto row_nums = (data_size * 8) / dim; - auto query_ds = knowhere::GenDataset(row_nums, dim, vectors); - auto query_res = cIndex->Query(query_ds); - *res = query_res.release(); - - status.error_code = Success; - status.error_msg = ""; - } catch (std::exception& e) { - status.error_code = UnexpectedError; - status.error_msg = strdup(e.what()); - } - return status; -} - -CStatus -QueryOnBinaryVecIndexWithParam(CIndex index, - int64_t data_size, - const uint8_t* vectors, - const char* serialized_search_params, - CIndexQueryResult* res) { - auto status = CStatus(); - try { - auto cIndex = (milvus::indexbuilder::VecIndexCreator*)index; - auto dim = cIndex->dim(); - auto row_nums = (data_size * 8) / dim; - auto query_ds = knowhere::GenDataset(row_nums, dim, vectors); - auto query_res = cIndex->QueryWithParam(query_ds, serialized_search_params); - *res = query_res.release(); - - status.error_code = Success; - status.error_msg = ""; - } catch (std::exception& e) { - status.error_code = UnexpectedError; - status.error_msg = strdup(e.what()); - } - return status; -} - -CStatus -CreateQueryResult(CIndexQueryResult* res) { - auto status = CStatus(); - try { - auto query_result = std::make_unique(); - *res = query_result.release(); - - status.error_code = Success; - status.error_msg = ""; - } catch (std::exception& e) { - status.error_code = UnexpectedError; - status.error_msg = strdup(e.what()); - } - return status; -} - -int64_t -NqOfQueryResult(CIndexQueryResult res) { - auto c_res = (milvus::indexbuilder::VecIndexCreator::QueryResult*)res; - return c_res->nq; -} - -int64_t -TopkOfQueryResult(CIndexQueryResult res) { - auto c_res = (milvus::indexbuilder::VecIndexCreator::QueryResult*)res; - return c_res->topk; -} - -void -GetIdsOfQueryResult(CIndexQueryResult res, int64_t* ids) { - auto c_res = (milvus::indexbuilder::VecIndexCreator::QueryResult*)res; - auto nq = c_res->nq; - auto k = c_res->topk; - // TODO: how could we avoid memory copy whenever this called - memcpy(ids, c_res->ids.data(), sizeof(int64_t) * nq * k); -} - -void -GetDistancesOfQueryResult(CIndexQueryResult res, float* distances) { - auto c_res = (milvus::indexbuilder::VecIndexCreator::QueryResult*)res; - auto nq = c_res->nq; - auto k = c_res->topk; - // TODO: how could we avoid memory copy whenever this called - memcpy(distances, c_res->distances.data(), sizeof(float) * nq * k); -} - -CStatus -DeleteIndexQueryResult(CIndexQueryResult res) { - auto status = CStatus(); - try { - auto c_res = (milvus::indexbuilder::VecIndexCreator::QueryResult*)res; - delete c_res; - + AssertInfo(index, "failed to build float vector index, passed index was null"); + auto real_index = reinterpret_cast(index); + auto cIndex = dynamic_cast(real_index); + cIndex->CleanLocalData(); status.error_code = Success; status.error_msg = ""; } catch (std::exception& e) { diff --git a/internal/core/src/indexbuilder/index_c.h b/internal/core/src/indexbuilder/index_c.h index 6468530625a11..4f3b71632964b 100644 --- a/internal/core/src/indexbuilder/index_c.h +++ b/internal/core/src/indexbuilder/index_c.h @@ -17,7 +17,7 @@ extern "C" { #include #include "common/type_c.h" -#include "common/vector_index_c.h" +#include "common/binary_set_c.h" #include "indexbuilder/type_c.h" CStatus @@ -50,42 +50,7 @@ CStatus LoadIndexFromBinarySet(CIndex index, CBinarySet c_binary_set); CStatus -QueryOnFloatVecIndex(CIndex index, int64_t float_value_num, const float* vectors, CIndexQueryResult* res); - -CStatus -QueryOnFloatVecIndexWithParam(CIndex index, - int64_t float_value_num, - const float* vectors, - const char* serialized_search_params, - CIndexQueryResult* res); - -CStatus -QueryOnBinaryVecIndex(CIndex index, int64_t data_size, const uint8_t* vectors, CIndexQueryResult* res); - -CStatus -QueryOnBinaryVecIndexWithParam(CIndex index, - int64_t data_size, - const uint8_t* vectors, - const char* serialized_search_params, - CIndexQueryResult* res); - -CStatus -CreateQueryResult(CIndexQueryResult* res); - -int64_t -NqOfQueryResult(CIndexQueryResult res); - -int64_t -TopkOfQueryResult(CIndexQueryResult res); - -void -GetIdsOfQueryResult(CIndexQueryResult res, int64_t* ids); - -void -GetDistancesOfQueryResult(CIndexQueryResult res, float* distances); - -CStatus -DeleteIndexQueryResult(CIndexQueryResult res); +CleanLocalData(CIndex index); #ifdef __cplusplus }; diff --git a/internal/core/src/indexbuilder/utils.cpp b/internal/core/src/indexbuilder/utils.cpp deleted file mode 100644 index 12fd3b99bfa98..0000000000000 --- a/internal/core/src/indexbuilder/utils.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License - -#include "indexbuilder/utils.h" - -#include -#include -#include -#include - -namespace milvus::indexbuilder { - -std::vector -NM_List() { - static std::vector ret{ - knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, - }; - return ret; -} - -std::vector -BIN_List() { - static std::vector ret{ - knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP, - knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, - }; - return ret; -} - -std::vector -Need_ID_List() { - static std::vector ret{ - // knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, - }; - - return ret; -} - -std::vector> -unsupported_index_combinations() { - static std::vector> ret{ - std::make_tuple(knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, knowhere::metric::L2), - }; - return ret; -} - -template -bool -is_in_list(const T& t, std::function()> list_func) { - auto l = list_func(); - return std::find(l.begin(), l.end(), t) != l.end(); -} - -bool -is_in_bin_list(const knowhere::IndexType& index_type) { - return is_in_list(index_type, BIN_List); -} - -bool -is_in_nm_list(const knowhere::IndexType& index_type) { - return is_in_list(index_type, NM_List); -} - -bool -is_in_need_id_list(const knowhere::IndexType& index_type) { - return is_in_list(index_type, Need_ID_List); -} - -bool -is_unsupported(const knowhere::IndexType& index_type, const knowhere::MetricType& metric_type) { - return is_in_list>(std::make_tuple(index_type, metric_type), - unsupported_index_combinations); -} - -} // namespace milvus::indexbuilder diff --git a/internal/core/src/indexbuilder/utils.h b/internal/core/src/indexbuilder/utils.h deleted file mode 100644 index 312bbe89e69e2..0000000000000 --- a/internal/core/src/indexbuilder/utils.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2019-2020 Zilliz. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under the License -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -// or implied. See the License for the specific language governing permissions and limitations under the License - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include "knowhere/index/IndexType.h" -#include "knowhere/index/vector_index/helpers/IndexParameter.h" - -namespace milvus::indexbuilder { - -std::vector -NM_List(); - -std::vector -BIN_List(); - -std::vector -Need_ID_List(); - -std::vector> -unsupported_index_combinations(); - -template -bool -is_in_list(const T& t, std::function()> list_func); - -bool -is_in_bin_list(const knowhere::IndexType& index_type); - -bool -is_in_nm_list(const knowhere::IndexType& index_type); - -bool -is_in_need_id_list(const knowhere::IndexType& index_type); - -bool -is_unsupported(const knowhere::IndexType& index_type, const knowhere::MetricType& metric_type); - -} // namespace milvus::indexbuilder diff --git a/internal/core/src/query/CMakeLists.txt b/internal/core/src/query/CMakeLists.txt index 75ab75207c349..e98013925cfaa 100644 --- a/internal/core/src/query/CMakeLists.txt +++ b/internal/core/src/query/CMakeLists.txt @@ -31,4 +31,4 @@ set(MILVUS_QUERY_SRCS PlanProto.cpp ) add_library(milvus_query ${MILVUS_QUERY_SRCS}) -target_link_libraries(milvus_query milvus_index milvus_common) +target_link_libraries(milvus_query milvus_index) diff --git a/internal/core/src/query/PlanNode.h b/internal/core/src/query/PlanNode.h index a9e1dbdd903aa..2a2e6d4a582f3 100644 --- a/internal/core/src/query/PlanNode.h +++ b/internal/core/src/query/PlanNode.h @@ -17,7 +17,8 @@ #include #include -#include "Expr.h" +#include "common/QueryInfo.h" +#include "query/Expr.h" #include "knowhere/common/Config.h" namespace milvus::query { @@ -34,14 +35,6 @@ struct PlanNode { using PlanNodePtr = std::unique_ptr; -struct SearchInfo { - int64_t topk_; - int64_t round_decimal_; - FieldId field_id_; - knowhere::MetricType metric_type_; - knowhere::Config search_params_; -}; - struct VectorPlanNode : PlanNode { std::optional predicate_; SearchInfo search_info_; diff --git a/internal/core/src/query/ScalarIndex.h b/internal/core/src/query/ScalarIndex.h index 684baf629a839..33794da454eed 100644 --- a/internal/core/src/query/ScalarIndex.h +++ b/internal/core/src/query/ScalarIndex.h @@ -22,22 +22,22 @@ namespace milvus::query { template -inline scalar::ScalarIndexPtr +inline index::ScalarIndexPtr generate_scalar_index(Span data) { - auto indexing = std::make_unique>(); + auto indexing = std::make_unique>(); indexing->Build(data.row_count(), data.data()); return indexing; } template <> -inline scalar::ScalarIndexPtr +inline index::ScalarIndexPtr generate_scalar_index(Span data) { - auto indexing = scalar::CreateStringIndexSort(); + auto indexing = index::CreateStringIndexSort(); indexing->Build(data.row_count(), data.data()); return indexing; } -inline std::unique_ptr +inline index::IndexBasePtr generate_scalar_index(SpanBase data, DataType data_type) { Assert(!datatype_is_vector(data_type)); switch (data_type) { diff --git a/internal/core/src/query/SearchOnGrowing.cpp b/internal/core/src/query/SearchOnGrowing.cpp index a14c919ce2fdf..9fe33c7e09554 100644 --- a/internal/core/src/query/SearchOnGrowing.cpp +++ b/internal/core/src/query/SearchOnGrowing.cpp @@ -10,6 +10,7 @@ // or implied. See the License for the specific language governing permissions and limitations under the License #include "common/BitsetView.h" +#include "common/QueryInfo.h" #include "SearchOnGrowing.h" #include "query/SearchBruteForce.h" #include "query/SearchOnIndex.h" @@ -22,7 +23,7 @@ namespace milvus::query { // - Query::ExecWithoutPredicate int32_t FloatIndexSearch(const segcore::SegmentGrowingImpl& segment, - const query::SearchInfo& info, + const SearchInfo& info, const void* query_data, int64_t num_queries, int64_t ins_barrier, @@ -44,7 +45,9 @@ FloatIndexSearch(const segcore::SegmentGrowingImpl& segment, if (indexing_record.is_in(vecfield_id)) { auto max_indexed_id = indexing_record.get_finished_ack(); const auto& field_indexing = indexing_record.get_vec_field_indexing(vecfield_id); - auto search_conf = field_indexing.get_search_params(info.topk_); + auto search_params = field_indexing.get_search_params(info.topk_); + SearchInfo search_conf(info); + search_conf.search_params_ = search_params; AssertInfo(vec_ptr->get_size_per_chunk() == field_indexing.get_size_per_chunk(), "[FloatSearch]Chunk size of vector not equal to chunk size of field index"); @@ -56,7 +59,8 @@ FloatIndexSearch(const segcore::SegmentGrowingImpl& segment, auto indexing = field_indexing.get_chunk_indexing(chunk_id); auto sub_view = bitset.subview(chunk_id * size_per_chunk, size_per_chunk); - auto sub_qr = SearchOnIndex(search_dataset, *indexing, search_conf, sub_view); + auto vec_index = (index::VectorIndex*)(indexing); + auto sub_qr = SearchOnIndex(search_dataset, *vec_index, search_conf, sub_view); // convert chunk uid to segment uid for (auto& x : sub_qr.mutable_seg_offsets()) { @@ -74,7 +78,7 @@ FloatIndexSearch(const segcore::SegmentGrowingImpl& segment, void SearchOnGrowing(const segcore::SegmentGrowingImpl& segment, - const query::SearchInfo& info, + const SearchInfo& info, const void* query_data, int64_t num_queries, Timestamp timestamp, diff --git a/internal/core/src/query/SearchOnGrowing.h b/internal/core/src/query/SearchOnGrowing.h index dfb419b8b03a9..63aef06f900ea 100644 --- a/internal/core/src/query/SearchOnGrowing.h +++ b/internal/core/src/query/SearchOnGrowing.h @@ -18,7 +18,7 @@ namespace milvus::query { void SearchOnGrowing(const segcore::SegmentGrowingImpl& segment, - const query::SearchInfo& info, + const SearchInfo& info, const void* query_data, int64_t num_queries, Timestamp timestamp, diff --git a/internal/core/src/query/SearchOnIndex.cpp b/internal/core/src/query/SearchOnIndex.cpp index f13edcc58a70c..7bec75a73f52d 100644 --- a/internal/core/src/query/SearchOnIndex.cpp +++ b/internal/core/src/query/SearchOnIndex.cpp @@ -15,8 +15,8 @@ namespace milvus::query { SubSearchResult SearchOnIndex(const dataset::SearchDataset& search_dataset, - const knowhere::VecIndex& indexing, - const knowhere::Config& search_conf, + const index::VectorIndex& indexing, + const SearchInfo& search_conf, const BitsetView& bitset) { auto num_queries = search_dataset.num_queries; auto topK = search_dataset.topk; @@ -27,15 +27,12 @@ SearchOnIndex(const dataset::SearchDataset& search_dataset, // NOTE: VecIndex Query API forget to add const qualifier // NOTE: use const_cast as a workaround - auto& indexing_nonconst = const_cast(indexing); + auto& indexing_nonconst = const_cast(indexing); auto ans = indexing_nonconst.Query(dataset, search_conf, bitset); - auto dis = knowhere::GetDatasetDistance(ans); - auto uids = knowhere::GetDatasetIDs(ans); - SubSearchResult sub_qr(num_queries, topK, metric_type, round_decimal); - std::copy_n(dis, num_queries * topK, sub_qr.get_distances()); - std::copy_n(uids, num_queries * topK, sub_qr.get_seg_offsets()); + std::copy_n(ans->distances_.data(), num_queries * topK, sub_qr.get_distances()); + std::copy_n(ans->seg_offsets_.data(), num_queries * topK, sub_qr.get_seg_offsets()); sub_qr.round_values(); return sub_qr; } diff --git a/internal/core/src/query/SearchOnIndex.h b/internal/core/src/query/SearchOnIndex.h index 541bcfb161859..3f10390c517f8 100644 --- a/internal/core/src/query/SearchOnIndex.h +++ b/internal/core/src/query/SearchOnIndex.h @@ -15,13 +15,15 @@ #include "knowhere/index/VecIndex.h" #include "query/SubSearchResult.h" #include "query/helper.h" +#include "common/QueryInfo.h" +#include "index/VectorIndex.h" namespace milvus::query { SubSearchResult SearchOnIndex(const dataset::SearchDataset& search_dataset, - const knowhere::VecIndex& indexing, - const knowhere::Config& search_conf, + const index::VectorIndex& indexing, + const SearchInfo& search_conf, const BitsetView& bitset); } // namespace milvus::query diff --git a/internal/core/src/query/SearchOnSealed.cpp b/internal/core/src/query/SearchOnSealed.cpp index be1190790397f..8f561bec78d51 100644 --- a/internal/core/src/query/SearchOnSealed.cpp +++ b/internal/core/src/query/SearchOnSealed.cpp @@ -11,11 +11,7 @@ #include -#include "knowhere/index/VecIndex.h" -#include "knowhere/index/vector_index/ConfAdapter.h" -#include "knowhere/index/vector_index/ConfAdapterMgr.h" -#include "knowhere/index/vector_index/helpers/IndexParameter.h" -#include "knowhere/index/vector_index/adapter/VectorAdapter.h" +#include "common/QueryInfo.h" #include "query/SearchBruteForce.h" #include "query/SearchOnSealed.h" #include "query/helper.h" @@ -49,18 +45,13 @@ SearchOnSealedIndex(const Schema& schema, auto conf = search_info.search_params_; knowhere::SetMetaTopk(conf, search_info.topk_); knowhere::SetMetaMetricType(conf, field_indexing->metric_type_); - auto index_type = field_indexing->indexing_->index_type(); - auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_type); - try { - adapter->CheckSearch(conf, index_type, field_indexing->indexing_->index_mode()); - } catch (std::exception& e) { - AssertInfo(false, e.what()); - } - return field_indexing->indexing_->Query(ds, conf, bitset); + auto vec_index = dynamic_cast(field_indexing->indexing_.get()); + auto index_type = vec_index->GetIndexType(); + return vec_index->Query(ds, search_info, bitset); }(); - auto ids = knowhere::GetDatasetIDs(final); - float* distances = (float*)knowhere::GetDatasetDistance(final); + auto ids = final->seg_offsets_.data(); + float* distances = final->distances_.data(); auto total_num = num_queries * topk; if (round_decimal != -1) { diff --git a/internal/core/src/query/SubSearchResult.h b/internal/core/src/query/SubSearchResult.h index 61f5e0925b60b..cac498cb7d058 100644 --- a/internal/core/src/query/SubSearchResult.h +++ b/internal/core/src/query/SubSearchResult.h @@ -20,7 +20,7 @@ namespace milvus::query { class SubSearchResult { public: - SubSearchResult(int64_t num_queries, int64_t topk, const knowhere::MetricType& metric_type, int64_t round_decimal) + SubSearchResult(int64_t num_queries, int64_t topk, const MetricType& metric_type, int64_t round_decimal) : num_queries_(num_queries), topk_(topk), round_decimal_(round_decimal), @@ -40,12 +40,12 @@ class SubSearchResult { public: static float - init_value(const knowhere::MetricType& metric_type) { + init_value(const MetricType& metric_type) { return (is_descending(metric_type) ? -1 : 1) * std::numeric_limits::max(); } static bool - is_descending(const knowhere::MetricType& metric_type) { + is_descending(const MetricType& metric_type) { // TODO(dog): more types if (metric_type == knowhere::metric::IP) { return true; diff --git a/internal/core/src/query/visitors/ExecExprVisitor.cpp b/internal/core/src/query/visitors/ExecExprVisitor.cpp index f825df4e8e99e..235bad2c94107 100644 --- a/internal/core/src/query/visitors/ExecExprVisitor.cpp +++ b/internal/core/src/query/visitors/ExecExprVisitor.cpp @@ -154,7 +154,7 @@ ExecExprVisitor::ExecRangeVisitorImpl(FieldId field_id, IndexFunc index_func, El auto num_chunk = upper_div(row_count_, size_per_chunk); std::deque results; - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; for (auto chunk_id = 0; chunk_id < indexing_barrier; ++chunk_id) { const Index& indexing = segment_.chunk_scalar_index(field_id, chunk_id); // NOTE: knowhere is not const-ready @@ -211,7 +211,7 @@ ExecExprVisitor::ExecDataRangeVisitorImpl(FieldId field_id, IndexFunc index_func // if sealed segment has loaded scalar index for this field, then index_barrier = 1 and data_barrier = 0 // in this case, sealed segment execute expr plan using scalar index - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; for (auto chunk_id = data_barrier; chunk_id < indexing_barrier; ++chunk_id) { auto& indexing = segment_.chunk_scalar_index(field_id, chunk_id); auto this_size = const_cast(&indexing)->Count(); @@ -233,7 +233,7 @@ template auto ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType { auto& expr = static_cast&>(expr_raw); - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; auto op = expr.op_type_; auto val = expr.value_; switch (op) { @@ -270,8 +270,8 @@ ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> Bi case OpType::PrefixMatch: { auto index_func = [val](Index* index) { auto dataset = std::make_unique(); - dataset->Set(scalar::OPERATOR_TYPE, OpType::PrefixMatch); - dataset->Set(scalar::PREFIX_VALUE, val); + dataset->Set(milvus::index::OPERATOR_TYPE, OpType::PrefixMatch); + dataset->Set(milvus::index::PREFIX_VALUE, val); return index->Query(std::move(dataset)); }; auto elem_func = [val, op](T x) { return Match(x, val, op); }; @@ -291,7 +291,7 @@ template auto ExecExprVisitor::ExecBinaryArithOpEvalRangeVisitorDispatcher(BinaryArithOpEvalRangeExpr& expr_raw) -> BitsetType { auto& expr = static_cast&>(expr_raw); - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; auto arith_op = expr.arith_op_; auto right_operand = expr.right_operand_; auto op = expr.op_type_; @@ -409,7 +409,7 @@ template auto ExecExprVisitor::ExecBinaryRangeVisitorDispatcher(BinaryRangeExpr& expr_raw) -> BitsetType { auto& expr = static_cast&>(expr_raw); - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; bool lower_inclusive = expr.lower_inclusive_; bool upper_inclusive = expr.upper_inclusive_; T val1 = expr.lower_value_; @@ -824,7 +824,7 @@ auto ExecExprVisitor::ExecTermVisitorImpl(TermExpr& expr_raw) -> BitsetType { using T = std::string; auto& expr = static_cast&>(expr_raw); - using Index = scalar::ScalarIndex; + using Index = index::ScalarIndex; const auto& terms = expr.terms_; auto n = terms.size(); std::unordered_set term_set(expr.terms_.begin(), expr.terms_.end()); diff --git a/internal/core/src/query/visitors/VerifyPlanNodeVisitor.cpp b/internal/core/src/query/visitors/VerifyPlanNodeVisitor.cpp index de8e90c3a079a..ba7a4a964a5fc 100644 --- a/internal/core/src/query/visitors/VerifyPlanNodeVisitor.cpp +++ b/internal/core/src/query/visitors/VerifyPlanNodeVisitor.cpp @@ -11,7 +11,6 @@ #include "knowhere/index/vector_index/ConfAdapterMgr.h" #include "knowhere/index/vector_index/ConfAdapter.h" -#include "knowhere/index/vector_index/helpers/IndexParameter.h" #include "query/generated/VerifyPlanNodeVisitor.h" namespace milvus::query { @@ -29,13 +28,14 @@ class VerifyPlanNodeVisitor : PlanNodeVisitor { }; } // namespace impl -static knowhere::IndexType +static IndexType InferIndexType(const Json& search_params) { // ivf -> nprobe // hnsw -> ef // annoy -> search_k - static const std::map key_list = [] { - std::map list; + // ngtpanng / ngtonng -> max_search_edges / epsilon + static const std::map key_list = [] { + std::map list; namespace ip = knowhere::indexparam; namespace ie = knowhere::IndexEnum; list.emplace(ip::NPROBE, ie::INDEX_FAISS_IVFFLAT); @@ -53,7 +53,7 @@ InferIndexType(const Json& search_params) { PanicCodeInfo(ErrorCodeEnum::IllegalArgument, "failed to infer index type"); } -static knowhere::IndexType +static IndexType InferBinaryIndexType(const Json& search_params) { namespace ip = knowhere::indexparam; namespace ie = knowhere::IndexEnum; diff --git a/internal/core/src/segcore/CMakeLists.txt b/internal/core/src/segcore/CMakeLists.txt index 09861114deeb4..1b58ab37b110c 100644 --- a/internal/core/src/segcore/CMakeLists.txt +++ b/internal/core/src/segcore/CMakeLists.txt @@ -46,9 +46,7 @@ endif () target_link_libraries(milvus_segcore milvus_query - milvus_common ${PLATFORM_LIBS} - pthread ${TBB} ${OpenMP_CXX_FLAGS} # gperftools diff --git a/internal/core/src/segcore/FieldIndexing.cpp b/internal/core/src/segcore/FieldIndexing.cpp index 380faace445e6..3239f6cadec04 100644 --- a/internal/core/src/segcore/FieldIndexing.cpp +++ b/internal/core/src/segcore/FieldIndexing.cpp @@ -15,9 +15,8 @@ #include "index/StringIndexSort.h" #include "common/SystemProperty.h" -#include "knowhere/index/vector_index/IndexIVF.h" -#include "knowhere/index/vector_index/adapter/VectorAdapter.h" #include "segcore/FieldIndexing.h" +#include "index/VectorMemIndex.h" namespace milvus::segcore { @@ -34,11 +33,10 @@ VectorFieldIndexing::BuildIndexRange(int64_t ack_beg, int64_t ack_end, const Vec data_.grow_to_at_least(ack_end); for (int chunk_id = ack_beg; chunk_id < ack_end; chunk_id++) { const auto& chunk = source->get_chunk(chunk_id); - // build index for chunk - auto indexing = std::make_unique(); + auto indexing = std::make_unique(knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, + knowhere::metric::L2, IndexMode::MODE_CPU); auto dataset = knowhere::GenDataset(source->get_size_per_chunk(), dim, chunk.data()); - indexing->Train(dataset, conf); - indexing->AddWithoutIds(dataset, conf); + indexing->BuildWithDataset(dataset, conf); data_[chunk_id] = std::move(indexing); } } @@ -53,8 +51,8 @@ VectorFieldIndexing::get_build_params() const { auto base_params = config.build_params; AssertInfo(base_params.count("nlist"), "Can't get nlist from index params"); - knowhere::SetMetaDim(base_params, field_meta_.get_dim()); - knowhere::SetMetaMetricType(base_params, metric_type); + base_params[knowhere::meta::DIM] = std::to_string(field_meta_.get_dim()); + base_params[knowhere::meta::METRIC_TYPE] = metric_type; return base_params; } @@ -111,11 +109,11 @@ ScalarFieldIndexing::BuildIndexRange(int64_t ack_beg, int64_t ack_end, const // build index for chunk // TODO if constexpr (std::is_same_v) { - auto indexing = scalar::CreateStringIndexSort(); + auto indexing = index::CreateStringIndexSort(); indexing->Build(vec_base->get_size_per_chunk(), chunk.data()); data_[chunk_id] = std::move(indexing); } else { - auto indexing = scalar::CreateScalarIndexSort(); + auto indexing = index::CreateScalarIndexSort(); indexing->Build(vec_base->get_size_per_chunk(), chunk.data()); data_[chunk_id] = std::move(indexing); } diff --git a/internal/core/src/segcore/FieldIndexing.h b/internal/core/src/segcore/FieldIndexing.h index 6fa13a70ea826..44c5d4f0a9b65 100644 --- a/internal/core/src/segcore/FieldIndexing.h +++ b/internal/core/src/segcore/FieldIndexing.h @@ -22,8 +22,8 @@ #include "AckResponder.h" #include "InsertRecord.h" #include "common/Schema.h" -#include "knowhere/index/VecIndex.h" #include "segcore/SegcoreConfig.h" +#include "index/VectorIndex.h" namespace milvus::segcore { @@ -53,7 +53,7 @@ class FieldIndexing { return segcore_config_.get_chunk_rows(); } - virtual knowhere::Index* + virtual index::IndexBase* get_chunk_indexing(int64_t chunk_id) const = 0; protected: @@ -71,14 +71,14 @@ class ScalarFieldIndexing : public FieldIndexing { BuildIndexRange(int64_t ack_beg, int64_t ack_end, const VectorBase* vec_base) override; // concurrent - scalar::ScalarIndex* + index::ScalarIndex* get_chunk_indexing(int64_t chunk_id) const override { Assert(!field_meta_.is_vector()); return data_.at(chunk_id).get(); } private: - tbb::concurrent_vector> data_; + tbb::concurrent_vector> data_; }; class VectorFieldIndexing : public FieldIndexing { @@ -89,7 +89,7 @@ class VectorFieldIndexing : public FieldIndexing { BuildIndexRange(int64_t ack_beg, int64_t ack_end, const VectorBase* vec_base) override; // concurrent - knowhere::VecIndex* + index::IndexBase* get_chunk_indexing(int64_t chunk_id) const override { Assert(field_meta_.is_vector()); return data_.at(chunk_id).get(); @@ -102,7 +102,7 @@ class VectorFieldIndexing : public FieldIndexing { get_search_params(int top_k) const; private: - tbb::concurrent_vector> data_; + tbb::concurrent_vector> data_; }; std::unique_ptr diff --git a/internal/core/src/segcore/SealedIndexingRecord.h b/internal/core/src/segcore/SealedIndexingRecord.h index 3b25c979158f1..a862331881c56 100644 --- a/internal/core/src/segcore/SealedIndexingRecord.h +++ b/internal/core/src/segcore/SealedIndexingRecord.h @@ -20,22 +20,22 @@ #include "common/Types.h" #include "exceptions/EasyAssert.h" -#include "knowhere/index/VecIndex.h" +#include "index/VectorIndex.h" namespace milvus::segcore { struct SealedIndexingEntry { - knowhere::MetricType metric_type_; - knowhere::VecIndexPtr indexing_; + MetricType metric_type_; + index::IndexBasePtr indexing_; }; using SealedIndexingEntryPtr = std::unique_ptr; struct SealedIndexingRecord { void - append_field_indexing(FieldId field_id, const knowhere::MetricType& metric_type, knowhere::VecIndexPtr indexing) { + append_field_indexing(FieldId field_id, const MetricType& metric_type, index::IndexBasePtr indexing) { auto ptr = std::make_unique(); - ptr->indexing_ = indexing; + ptr->indexing_ = std::move(indexing); ptr->metric_type_ = metric_type; std::unique_lock lck(mutex_); field_indexings_[field_id] = std::move(ptr); diff --git a/internal/core/src/segcore/SegcoreConfig.h b/internal/core/src/segcore/SegcoreConfig.h index f6ba3286ce4f1..5c56fe3b3786c 100644 --- a/internal/core/src/segcore/SegcoreConfig.h +++ b/internal/core/src/segcore/SegcoreConfig.h @@ -31,7 +31,7 @@ class SegcoreConfig { SegcoreConfig() { // hard code configurations for small index SmallIndexConf sub_conf; - sub_conf.build_params["nlist"] = nlist_; + sub_conf.build_params["nlist"] = std::to_string(nlist_); sub_conf.search_params["nprobe"] = nprobe_; sub_conf.index_type = "IVF"; table_[knowhere::metric::L2] = sub_conf; @@ -50,7 +50,7 @@ class SegcoreConfig { parse_from(const std::string& string_path); const SmallIndexConf& - at(const knowhere::MetricType& metric_type) const { + at(const MetricType& metric_type) const { Assert(table_.count(metric_type)); return table_.at(metric_type); } @@ -76,7 +76,7 @@ class SegcoreConfig { } void - set_small_index_config(const knowhere::MetricType& metric_type, const SmallIndexConf& small_index_conf) { + set_small_index_config(const MetricType& metric_type, const SmallIndexConf& small_index_conf) { table_[metric_type] = small_index_conf; } diff --git a/internal/core/src/segcore/SegmentGrowingImpl.cpp b/internal/core/src/segcore/SegmentGrowingImpl.cpp index 94aaa6eb08ccd..b4e3bf22230fd 100644 --- a/internal/core/src/segcore/SegmentGrowingImpl.cpp +++ b/internal/core/src/segcore/SegmentGrowingImpl.cpp @@ -16,11 +16,8 @@ #include #include "common/Consts.h" -#include "knowhere/index/vector_index/adapter/VectorAdapter.h" #include "query/PlanNode.h" #include "query/SearchOnSealed.h" -#include "query/generated/ExecPlanNodeVisitor.h" -#include "segcore/Reduce.h" #include "segcore/SegmentGrowingImpl.h" #include "segcore/Utils.h" @@ -176,7 +173,7 @@ SegmentGrowingImpl::num_chunk() const { } void -SegmentGrowingImpl::vector_search(query::SearchInfo& search_info, +SegmentGrowingImpl::vector_search(SearchInfo& search_info, const void* query_data, int64_t query_count, Timestamp timestamp, diff --git a/internal/core/src/segcore/SegmentGrowingImpl.h b/internal/core/src/segcore/SegmentGrowingImpl.h index ab279f080f997..adc9525dd4f9c 100644 --- a/internal/core/src/segcore/SegmentGrowingImpl.h +++ b/internal/core/src/segcore/SegmentGrowingImpl.h @@ -109,7 +109,7 @@ class SegmentGrowingImpl : public SegmentGrowing { } // deprecated - const knowhere::Index* + const index::IndexBase* chunk_index_impl(FieldId field_id, int64_t chunk_id) const final { return indexing_record_.get_field_indexing(field_id).get_chunk_indexing(chunk_id); } @@ -174,7 +174,7 @@ class SegmentGrowingImpl : public SegmentGrowing { mask_with_timestamps(BitsetType& bitset_chunk, Timestamp timestamp) const override; void - vector_search(query::SearchInfo& search_info, + vector_search(SearchInfo& search_info, const void* query_data, int64_t query_count, Timestamp timestamp, diff --git a/internal/core/src/segcore/SegmentInterface.h b/internal/core/src/segcore/SegmentInterface.h index c7fe4301a0e42..a2db775e3863f 100644 --- a/internal/core/src/segcore/SegmentInterface.h +++ b/internal/core/src/segcore/SegmentInterface.h @@ -27,10 +27,12 @@ #include "common/LoadInfo.h" #include "common/BitsetView.h" #include "common/QueryResult.h" +#include "common/QueryInfo.h" #include "query/Plan.h" #include "query/PlanNode.h" #include "pb/schema.pb.h" #include "pb/segcore.pb.h" +#include "index/IndexInfo.h" namespace milvus::segcore { @@ -91,10 +93,10 @@ class SegmentInternalInterface : public SegmentInterface { } template - const scalar::ScalarIndex& + const index::ScalarIndex& chunk_scalar_index(FieldId field_id, int64_t chunk_id) const { static_assert(IsScalar); - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto base_ptr = chunk_index_impl(field_id, chunk_id); auto ptr = dynamic_cast(base_ptr); AssertInfo(ptr, "entry mismatch"); @@ -129,7 +131,7 @@ class SegmentInternalInterface : public SegmentInterface { public: virtual void - vector_search(query::SearchInfo& search_info, + vector_search(SearchInfo& search_info, const void* query_data, int64_t query_count, Timestamp timestamp, @@ -176,7 +178,7 @@ class SegmentInternalInterface : public SegmentInterface { chunk_data_impl(FieldId field_id, int64_t chunk_id) const = 0; // internal API: return chunk_index in span, support scalar index only - virtual const knowhere::Index* + virtual const index::IndexBase* chunk_index_impl(FieldId field_id, int64_t chunk_id) const = 0; // TODO remove system fields diff --git a/internal/core/src/segcore/SegmentSealed.h b/internal/core/src/segcore/SegmentSealed.h index eb17689dcaa70..bac359b600f05 100644 --- a/internal/core/src/segcore/SegmentSealed.h +++ b/internal/core/src/segcore/SegmentSealed.h @@ -23,7 +23,7 @@ namespace milvus::segcore { class SegmentSealed : public SegmentInternalInterface { public: virtual void - LoadIndex(const LoadIndexInfo& info) = 0; + LoadIndex(const index::LoadIndexInfo& info) = 0; virtual void LoadSegmentMeta(const milvus::proto::segcore::LoadSegmentMeta& meta) = 0; virtual void diff --git a/internal/core/src/segcore/SegmentSealedImpl.cpp b/internal/core/src/segcore/SegmentSealedImpl.cpp index a294ed354727f..7231693aacc32 100644 --- a/internal/core/src/segcore/SegmentSealedImpl.cpp +++ b/internal/core/src/segcore/SegmentSealedImpl.cpp @@ -39,31 +39,7 @@ SegmentSealedImpl::PreDelete(int64_t size) { } void -print(const std::map& m) { - for (const auto& [k, v] : m) { - std::cout << k << ": " << v << std::endl; - } -} - -void -print(const LoadIndexInfo& info) { - std::cout << "------------------LoadIndexInfo----------------------" << std::endl; - std::cout << "field_id: " << info.field_id << std::endl; - std::cout << "field_type: " << info.field_type << std::endl; - std::cout << "index_params:" << std::endl; - print(info.index_params); - std::cout << "------------------LoadIndexInfo----------------------" << std::endl; -} - -void -print(const LoadFieldDataInfo& info) { - std::cout << "------------------LoadFieldDataInfo----------------------" << std::endl; - std::cout << "field_id: " << info.field_id << std::endl; - std::cout << "------------------LoadFieldDataInfo----------------------" << std::endl; -} - -void -SegmentSealedImpl::LoadIndex(const LoadIndexInfo& info) { +SegmentSealedImpl::LoadIndex(const index::LoadIndexInfo& info) { // print(info); // NOTE: lock only when data is ready to avoid starvation auto field_id = FieldId(info.field_id); @@ -77,15 +53,14 @@ SegmentSealedImpl::LoadIndex(const LoadIndexInfo& info) { } void -SegmentSealedImpl::LoadVecIndex(const LoadIndexInfo& info) { +SegmentSealedImpl::LoadVecIndex(const index::LoadIndexInfo& info) { // NOTE: lock only when data is ready to avoid starvation auto field_id = FieldId(info.field_id); auto& field_meta = schema_->operator[](field_id); - auto index = std::dynamic_pointer_cast(info.index); AssertInfo(info.index_params.count("metric_type"), "Can't get metric_type in index_params"); auto metric_type = info.index_params.at("metric_type"); - auto row_count = index->Count(); + auto row_count = info.index->Count(); AssertInfo(row_count > 0, "Index count is 0"); std::unique_lock lck(mutex_); @@ -101,7 +76,8 @@ SegmentSealedImpl::LoadVecIndex(const LoadIndexInfo& info) { std::to_string(row_count_opt_.value()) + ")"); } AssertInfo(!vector_indexings_.is_ready(field_id), "vec index is not ready"); - vector_indexings_.append_field_indexing(field_id, metric_type, index); + vector_indexings_.append_field_indexing(field_id, metric_type, + std::move(const_cast(info).index)); set_bit(index_ready_bitset_, field_id, true); update_row_count(row_count); @@ -109,13 +85,12 @@ SegmentSealedImpl::LoadVecIndex(const LoadIndexInfo& info) { } void -SegmentSealedImpl::LoadScalarIndex(const LoadIndexInfo& info) { +SegmentSealedImpl::LoadScalarIndex(const index::LoadIndexInfo& info) { // NOTE: lock only when data is ready to avoid starvation auto field_id = FieldId(info.field_id); auto& field_meta = schema_->operator[](field_id); - auto index = std::dynamic_pointer_cast(info.index); - auto row_count = index->Count(); + auto row_count = info.index->Count(); AssertInfo(row_count > 0, "Index count is 0"); std::unique_lock lck(mutex_); @@ -131,21 +106,21 @@ SegmentSealedImpl::LoadScalarIndex(const LoadIndexInfo& info) { std::to_string(row_count_opt_.value()) + ")"); } - scalar_indexings_[field_id] = index; + scalar_indexings_[field_id] = std::move(const_cast(info).index); // reverse pk from scalar index and set pks to offset if (schema_->get_primary_field_id() == field_id) { AssertInfo(field_id.get() != -1, "Primary key is -1"); AssertInfo(insert_record_.empty_pks(), "already exists"); switch (field_meta.get_data_type()) { case DataType::INT64: { - auto int64_index = std::dynamic_pointer_cast>(info.index); + auto int64_index = dynamic_cast*>(scalar_indexings_[field_id].get()); for (int i = 0; i < row_count; ++i) { insert_record_.insert_pk(int64_index->Reverse_Lookup(i), i); } break; } case DataType::VARCHAR: { - auto string_index = std::dynamic_pointer_cast>(info.index); + auto string_index = dynamic_cast*>(scalar_indexings_[field_id].get()); for (int i = 0; i < row_count; ++i) { insert_record_.insert_pk(string_index->Reverse_Lookup(i), i); } @@ -300,7 +275,7 @@ SegmentSealedImpl::chunk_data_impl(FieldId field_id, int64_t chunk_id) const { return field_data->get_span_base(0); } -const knowhere::Index* +const index::IndexBase* SegmentSealedImpl::chunk_index_impl(FieldId field_id, int64_t chunk_id) const { AssertInfo(scalar_indexings_.find(field_id) != scalar_indexings_.end(), "Cannot find scalar_indexing with field_id: " + std::to_string(field_id.get())); @@ -349,7 +324,7 @@ SegmentSealedImpl::mask_with_delete(BitsetType& bitset, int64_t ins_barrier, Tim } void -SegmentSealedImpl::vector_search(query::SearchInfo& search_info, +SegmentSealedImpl::vector_search(SearchInfo& search_info, const void* query_data, int64_t query_count, Timestamp timestamp, diff --git a/internal/core/src/segcore/SegmentSealedImpl.h b/internal/core/src/segcore/SegmentSealedImpl.h index 41bee3a333467..7cc846d68048f 100644 --- a/internal/core/src/segcore/SegmentSealedImpl.h +++ b/internal/core/src/segcore/SegmentSealedImpl.h @@ -27,6 +27,7 @@ #include "SealedIndexingRecord.h" #include "SegmentSealed.h" #include "TimestampIndex.h" +#include "index/ScalarIndex.h" namespace milvus::segcore { @@ -34,7 +35,7 @@ class SegmentSealedImpl : public SegmentSealed { public: explicit SegmentSealedImpl(SchemaPtr schema, int64_t segment_id); void - LoadIndex(const LoadIndexInfo& info) override; + LoadIndex(const index::LoadIndexInfo& info) override; void LoadFieldData(const LoadFieldDataInfo& info) override; void @@ -97,7 +98,7 @@ class SegmentSealedImpl : public SegmentSealed { SpanBase chunk_data_impl(FieldId field_id, int64_t chunk_id) const override; - const knowhere::Index* + const index::IndexBase* chunk_index_impl(FieldId field_id, int64_t chunk_id) const override; // Calculate: output[i] = Vec[seg_offset[i]], @@ -141,7 +142,7 @@ class SegmentSealedImpl : public SegmentSealed { mask_with_timestamps(BitsetType& bitset_chunk, Timestamp timestamp) const override; void - vector_search(query::SearchInfo& search_info, + vector_search(SearchInfo& search_info, const void* query_data, int64_t query_count, Timestamp timestamp, @@ -171,10 +172,10 @@ class SegmentSealedImpl : public SegmentSealed { search_ids(const BitsetType& view, Timestamp timestamp) const override; void - LoadVecIndex(const LoadIndexInfo& info); + LoadVecIndex(const index::LoadIndexInfo& info); void - LoadScalarIndex(const LoadIndexInfo& info); + LoadScalarIndex(const index::LoadIndexInfo& info); private: // segment loading state @@ -187,7 +188,7 @@ class SegmentSealedImpl : public SegmentSealed { std::optional row_count_opt_; // scalar field index - std::unordered_map scalar_indexings_; + std::unordered_map scalar_indexings_; // vector field index SealedIndexingRecord vector_indexings_; diff --git a/internal/core/src/segcore/SimilarityCorelation.h b/internal/core/src/segcore/SimilarityCorelation.h index 02be934778bec..8ccf84e6c0545 100644 --- a/internal/core/src/segcore/SimilarityCorelation.h +++ b/internal/core/src/segcore/SimilarityCorelation.h @@ -11,11 +11,11 @@ #pragma once -#include +#include "common/Types.h" namespace milvus::segcore { static inline bool -PositivelyRelated(const knowhere::MetricType& metric_type) { +PositivelyRelated(const MetricType& metric_type) { return metric_type == knowhere::metric::IP; } } // namespace milvus::segcore diff --git a/internal/core/src/segcore/Utils.cpp b/internal/core/src/segcore/Utils.cpp index e14063027d886..1a54774949c32 100644 --- a/internal/core/src/segcore/Utils.cpp +++ b/internal/core/src/segcore/Utils.cpp @@ -259,7 +259,7 @@ MergeDataArray(std::vector>& result_of // TODO: split scalar IndexBase with knowhere::Index std::unique_ptr -ReverseDataFromIndex(const knowhere::Index* index, +ReverseDataFromIndex(const index::IndexBase* index, const int64_t* seg_offsets, int64_t count, const FieldMeta& field_meta) { @@ -271,7 +271,7 @@ ReverseDataFromIndex(const knowhere::Index* index, auto scalar_array = data_array->mutable_scalars(); switch (data_type) { case DataType::BOOL: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -282,7 +282,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::INT8: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -293,7 +293,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::INT16: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -304,7 +304,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::INT32: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -315,7 +315,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::INT64: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -326,7 +326,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::FLOAT: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -337,7 +337,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::DOUBLE: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { @@ -348,7 +348,7 @@ ReverseDataFromIndex(const knowhere::Index* index, break; } case DataType::VARCHAR: { - using IndexType = scalar::ScalarIndex; + using IndexType = index::ScalarIndex; auto ptr = dynamic_cast(index); std::vector raw_data(count); for (int64_t i = 0; i < count; ++i) { diff --git a/internal/core/src/segcore/Utils.h b/internal/core/src/segcore/Utils.h index 922c4180ab5ae..fe286672593c2 100644 --- a/internal/core/src/segcore/Utils.h +++ b/internal/core/src/segcore/Utils.h @@ -18,9 +18,9 @@ #include #include "common/QueryResult.h" -#include "knowhere/index/Index.h" #include "segcore/DeletedRecord.h" #include "segcore/InsertRecord.h" +#include "index/Index.h" namespace milvus::segcore { @@ -56,7 +56,7 @@ get_deleted_bitmap(int64_t del_barrier, Timestamp query_timestamp); std::unique_ptr -ReverseDataFromIndex(const knowhere::Index* index, +ReverseDataFromIndex(const index::IndexBase* index, const int64_t* seg_offsets, int64_t count, const FieldMeta& field_meta); diff --git a/internal/core/src/segcore/load_index_c.cpp b/internal/core/src/segcore/load_index_c.cpp index 7270325456767..2833b62928f65 100644 --- a/internal/core/src/segcore/load_index_c.cpp +++ b/internal/core/src/segcore/load_index_c.cpp @@ -10,17 +10,19 @@ // or implied. See the License for the specific language governing permissions and limitations under the License #include "common/CDataType.h" -#include "common/LoadInfo.h" -#include "exceptions/EasyAssert.h" +#include "common/FieldMeta.h" +#include "common/Utils.h" +#include "index/Meta.h" +#include "index/Utils.h" #include "index/IndexFactory.h" -#include "knowhere/common/BinarySet.h" -#include "knowhere/index/VecIndexFactory.h" +#include "storage/Util.h" #include "segcore/load_index_c.h" +#include "pb/index_cgo_msg.pb.h" CStatus NewLoadIndexInfo(CLoadIndexInfo* c_load_index_info) { try { - auto load_index_info = std::make_unique(); + auto load_index_info = std::make_unique(); *c_load_index_info = load_index_info.release(); auto status = CStatus(); status.error_code = Success; @@ -36,14 +38,14 @@ NewLoadIndexInfo(CLoadIndexInfo* c_load_index_info) { void DeleteLoadIndexInfo(CLoadIndexInfo c_load_index_info) { - auto info = (LoadIndexInfo*)c_load_index_info; + auto info = (milvus::index::LoadIndexInfo*)c_load_index_info; delete info; } CStatus AppendIndexParam(CLoadIndexInfo c_load_index_info, const char* c_index_key, const char* c_index_value) { try { - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; std::string index_key(c_index_key); std::string index_value(c_index_value); load_index_info->index_params[index_key] = index_value; @@ -61,11 +63,19 @@ AppendIndexParam(CLoadIndexInfo c_load_index_info, const char* c_index_key, cons } CStatus -AppendFieldInfo(CLoadIndexInfo c_load_index_info, int64_t field_id, enum CDataType field_type) { +AppendFieldInfo(CLoadIndexInfo c_load_index_info, + int64_t collection_id, + int64_t partition_id, + int64_t segment_id, + int64_t field_id, + enum CDataType field_type) { try { - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; + load_index_info->collection_id = collection_id; + load_index_info->partition_id = partition_id; + load_index_info->segment_id = segment_id; load_index_info->field_id = field_id; - load_index_info->field_type = field_type; + load_index_info->field_type = milvus::DataType(field_type); auto status = CStatus(); status.error_code = Success; @@ -82,23 +92,39 @@ AppendFieldInfo(CLoadIndexInfo c_load_index_info, int64_t field_id, enum CDataTy CStatus appendVecIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set) { try { - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; auto binary_set = (knowhere::BinarySet*)c_binary_set; auto& index_params = load_index_info->index_params; - bool find_index_type = index_params.count("index_type") > 0 ? true : false; - bool find_index_mode = index_params.count("index_mode") > 0 ? true : false; - AssertInfo(find_index_type == true, "Can't find index type in index_params"); - knowhere::IndexMode mode; - if (find_index_mode) { - std::string index_mode = index_params["index_mode"]; - mode = (index_mode == "CPU" || index_mode == "cpu") ? knowhere::IndexMode::MODE_CPU - : knowhere::IndexMode::MODE_GPU; - } else { - mode = knowhere::IndexMode::MODE_CPU; + + milvus::index::CreateIndexInfo index_info; + index_info.field_type = load_index_info->field_type; + + // get index type + AssertInfo(index_params.find("index_type") != index_params.end(), "index type is empty"); + index_info.index_type = index_params.at("index_type"); + + // get metric type + AssertInfo(index_params.find("metric_type") != index_params.end(), "metric type is empty"); + index_info.metric_type = index_params.at("metric_type"); + + // set default index mode + index_info.index_mode = milvus::IndexMode::MODE_CPU; + if (index_params.count("index_mode")) { + index_info.index_mode = milvus::index::GetIndexMode(index_params["index_mode"]); } - load_index_info->index = - knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_params["index_type"], mode); - load_index_info->index->Load(*binary_set); + + // init file manager + milvus::storage::FieldDataMeta field_meta{load_index_info->collection_id, load_index_info->partition_id, + load_index_info->segment_id, load_index_info->field_id}; + milvus::storage::IndexMeta index_meta{load_index_info->segment_id, load_index_info->field_id, + load_index_info->index_build_id, load_index_info->index_version}; + auto file_manager = milvus::storage::CreateFileManager(index_info.index_type, field_meta, index_meta); + + auto config = milvus::index::ParseConfigFromIndexParams(load_index_info->index_params); + config["index_files"] = load_index_info->index_files; + + load_index_info->index = milvus::index::IndexFactory::GetInstance().CreateIndex(index_info, file_manager); + load_index_info->index->Load(*binary_set, config); auto status = CStatus(); status.error_code = Success; status.error_msg = ""; @@ -114,14 +140,23 @@ appendVecIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set) { CStatus appendScalarIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set) { try { - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; auto field_type = load_index_info->field_type; auto binary_set = (knowhere::BinarySet*)c_binary_set; auto& index_params = load_index_info->index_params; bool find_index_type = index_params.count("index_type") > 0 ? true : false; AssertInfo(find_index_type == true, "Can't find index type in index_params"); - load_index_info->index = - milvus::scalar::IndexFactory::GetInstance().CreateIndex(field_type, index_params["index_type"]); + + milvus::index::CreateIndexInfo index_info; + index_info.field_type = milvus::DataType(field_type); + index_info.index_type = index_params["index_type"]; + // set default index mode + index_info.index_mode = milvus::IndexMode::MODE_CPU; + if (index_params.count("index_mode")) { + index_info.index_mode = milvus::index::GetIndexMode(index_params["index_mode"]); + } + + load_index_info->index = milvus::index::IndexFactory::GetInstance().CreateIndex(index_info, nullptr); load_index_info->index->Load(*binary_set); auto status = CStatus(); status.error_code = Success; @@ -137,10 +172,78 @@ appendScalarIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set) { CStatus AppendIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set) { - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; auto field_type = load_index_info->field_type; - if (milvus::IsVectorType(field_type)) { + if (milvus::datatype_is_vector(field_type)) { return appendVecIndex(c_load_index_info, c_binary_set); } return appendScalarIndex(c_load_index_info, c_binary_set); } + +CStatus +AppendIndexFilePath(CLoadIndexInfo c_load_index_info, const char* c_file_path) { + try { + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; + std::string index_file_path(c_file_path); + load_index_info->index_files.emplace_back(index_file_path); + + auto status = CStatus(); + status.error_code = Success; + status.error_msg = ""; + return status; + } catch (std::exception& e) { + auto status = CStatus(); + status.error_code = UnexpectedError; + status.error_msg = strdup(e.what()); + return status; + } +} + +CStatus +AppendIndexInfo( + CLoadIndexInfo c_load_index_info, int64_t index_id, int64_t build_id, int64_t version, const char* c_index_params) { + try { + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; + load_index_info->index_id = index_id; + load_index_info->index_build_id = build_id; + load_index_info->index_version = version; + milvus::proto::indexcgo::IndexParams index_params; + milvus::index::ParseFromString(index_params, c_index_params); + + for (auto i = 0; i < index_params.params().size(); i++) { + auto& param = index_params.params(i); + load_index_info->index_params[param.key()] = param.value(); + } + + auto status = CStatus(); + status.error_code = Success; + status.error_msg = ""; + return status; + } catch (std::exception& e) { + auto status = CStatus(); + status.error_code = UnexpectedError; + status.error_msg = strdup(e.what()); + return status; + } +} + +CStatus +CleanLoadedIndex(CLoadIndexInfo c_load_index_info) { + try { + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; + auto index_file_path_prefix = + milvus::storage::GenLocalIndexPathPrefix(load_index_info->index_build_id, load_index_info->index_version); +#ifdef BUILD_DISK_ANN + milvus::storage::LocalChunkManager::GetInstance().RemoveDir(index_file_path_prefix); +#endif + auto status = CStatus(); + status.error_code = Success; + status.error_msg = ""; + return status; + } catch (std::exception& e) { + auto status = CStatus(); + status.error_code = UnexpectedError; + status.error_msg = strdup(e.what()); + return status; + } +} diff --git a/internal/core/src/segcore/load_index_c.h b/internal/core/src/segcore/load_index_c.h index d54fbe6a6813d..dbcab1ea25840 100644 --- a/internal/core/src/segcore/load_index_c.h +++ b/internal/core/src/segcore/load_index_c.h @@ -17,7 +17,7 @@ extern "C" { #include #include -#include "common/vector_index_c.h" +#include "common/binary_set_c.h" #include "common/type_c.h" #include "segcore/collection_c.h" @@ -33,11 +33,26 @@ CStatus AppendIndexParam(CLoadIndexInfo c_load_index_info, const char* index_key, const char* index_value); CStatus -AppendFieldInfo(CLoadIndexInfo c_load_index_info, int64_t field_id, enum CDataType field_type); +AppendFieldInfo(CLoadIndexInfo c_load_index_info, + int64_t collection_id, + int64_t partition_id, + int64_t segment_id, + int64_t field_id, + enum CDataType field_type); + +CStatus +AppendIndexInfo( + CLoadIndexInfo c_load_index_info, int64_t index_id, int64_t build_id, int64_t version, const char* index_params); CStatus AppendIndex(CLoadIndexInfo c_load_index_info, CBinarySet c_binary_set); +CStatus +AppendIndexFilePath(CLoadIndexInfo c_load_index_info, const char* file_path); + +CStatus +CleanLoadedIndex(CLoadIndexInfo c_load_index_info); + #ifdef __cplusplus } #endif diff --git a/internal/core/src/segcore/segment_c.cpp b/internal/core/src/segcore/segment_c.cpp index edacaa961d9f9..8ad40ecdf32fa 100644 --- a/internal/core/src/segcore/segment_c.cpp +++ b/internal/core/src/segcore/segment_c.cpp @@ -20,6 +20,7 @@ #include "segcore/SegmentSealedImpl.h" #include "segcore/SimilarityCorelation.h" #include "segcore/segment_c.h" +#include "index/IndexInfo.h" #include "google/protobuf/text_format.h" ////////////////////////////// common interfaces ////////////////////////////// @@ -238,7 +239,7 @@ UpdateSealedSegmentIndex(CSegmentInterface c_segment, CLoadIndexInfo c_load_inde auto segment_interface = reinterpret_cast(c_segment); auto segment = dynamic_cast(segment_interface); AssertInfo(segment != nullptr, "segment conversion failed"); - auto load_index_info = (LoadIndexInfo*)c_load_index_info; + auto load_index_info = (milvus::index::LoadIndexInfo*)c_load_index_info; segment->LoadIndex(*load_index_info); return milvus::SuccessCStatus(); } catch (std::exception& e) { diff --git a/internal/core/src/storage/CMakeLists.txt b/internal/core/src/storage/CMakeLists.txt index 535528872eb74..80245ef9bcfd4 100644 --- a/internal/core/src/storage/CMakeLists.txt +++ b/internal/core/src/storage/CMakeLists.txt @@ -34,10 +34,23 @@ set(STORAGE_FILES IndexData.cpp InsertData.cpp Event.cpp - ) + storage_c.cpp) + +if ( BUILD_DISK_ANN STREQUAL "ON" ) + set(STORAGE_FILES + ${STORAGE_FILES} + LocalChunkManager.cpp + MinioChunkManager.cpp + DiskFileManagerImpl.cpp) +endif () + add_library(milvus_storage SHARED ${STORAGE_FILES}) -#target_link_libraries( milvus_storage PUBLIC milvus_common boost_system boost_filesystem aws-cpp-sdk-s3 pthread) -target_link_libraries( milvus_storage PUBLIC milvus_common pthread) + +if ( BUILD_DISK_ANN STREQUAL "ON" ) + target_link_libraries( milvus_storage PUBLIC milvus_common boost_system boost_filesystem aws-cpp-sdk-s3 pthread) +else() + target_link_libraries( milvus_storage PUBLIC milvus_common pthread) +endif() if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/internal/core/src/storage/DiskANNFileManagerImpl.cpp b/internal/core/src/storage/DiskFileManagerImpl.cpp similarity index 88% rename from internal/core/src/storage/DiskANNFileManagerImpl.cpp rename to internal/core/src/storage/DiskFileManagerImpl.cpp index 40e22da5428ae..befd4992535ea 100644 --- a/internal/core/src/storage/DiskANNFileManagerImpl.cpp +++ b/internal/core/src/storage/DiskFileManagerImpl.cpp @@ -19,14 +19,14 @@ #include #include "common/Consts.h" -#include "storage/DiskANNFileManagerImpl.h" +#include "log/Log.h" +#include "config/ConfigKnowhere.h" +#include "storage/DiskFileManagerImpl.h" #include "storage/LocalChunkManager.h" #include "storage/MinioChunkManager.h" #include "storage/Exception.h" -#include "log/Log.h" #include "storage/FieldData.h" #include "storage/IndexData.h" -#include "config/ConfigKnowhere.h" #include "storage/Util.h" #define FILEMANAGER_TRY try { @@ -58,22 +58,22 @@ using WriteLock = std::lock_guard; namespace milvus::storage { -DiskANNFileManagerImpl::DiskANNFileManagerImpl(const FieldDataMeta& field_mata, const IndexMeta& index_meta) +DiskFileManagerImpl::DiskFileManagerImpl(const FieldDataMeta& field_mata, const IndexMeta& index_meta) : field_meta_(field_mata), index_meta_(index_meta) { } -DiskANNFileManagerImpl::~DiskANNFileManagerImpl() { +DiskFileManagerImpl::~DiskFileManagerImpl() { auto& local_chunk_manager = LocalChunkManager::GetInstance(); local_chunk_manager.RemoveDir(GetLocalIndexPathPrefixWithBuildID(index_meta_.build_id)); } bool -DiskANNFileManagerImpl::LoadFile(const std::string& file) noexcept { +DiskFileManagerImpl::LoadFile(const std::string& file) noexcept { return true; } bool -DiskANNFileManagerImpl::AddFile(const std::string& file) noexcept { +DiskFileManagerImpl::AddFile(const std::string& file) noexcept { auto& local_chunk_manager = LocalChunkManager::GetInstance(); auto& remote_chunk_manager = MinioChunkManager::GetInstance(); FILEMANAGER_TRY @@ -119,7 +119,7 @@ DiskANNFileManagerImpl::AddFile(const std::string& file) noexcept { } // namespace knowhere void -DiskANNFileManagerImpl::CacheIndexToDisk(std::vector remote_files) { +DiskFileManagerImpl::CacheIndexToDisk(std::vector remote_files) { auto& local_chunk_manager = LocalChunkManager::GetInstance(); auto& remote_chunk_manager = MinioChunkManager::GetInstance(); @@ -157,30 +157,30 @@ DiskANNFileManagerImpl::CacheIndexToDisk(std::vector remote_files) } std::string -DiskANNFileManagerImpl::GetFileName(const std::string& localfile) { +DiskFileManagerImpl::GetFileName(const std::string& localfile) { boost::filesystem::path localPath(localfile); return localPath.filename().string(); } std::string -DiskANNFileManagerImpl::GetRemoteIndexObjectPrefix() { - return "files/" + std::string(INDEX_ROOT_PATH) + "/" + std::to_string(index_meta_.build_id) + "/" + - std::to_string(index_meta_.index_version) + "/" + std::to_string(field_meta_.partition_id) + "/" + - std::to_string(field_meta_.segment_id); +DiskFileManagerImpl::GetRemoteIndexObjectPrefix() { + return ChunkMangerConfig::GetRemoteRootPath() + "/" + std::string(INDEX_ROOT_PATH) + "/" + + std::to_string(index_meta_.build_id) + "/" + std::to_string(index_meta_.index_version) + "/" + + std::to_string(field_meta_.partition_id) + "/" + std::to_string(field_meta_.segment_id); } std::string -DiskANNFileManagerImpl::GetLocalIndexObjectPrefix() { +DiskFileManagerImpl::GetLocalIndexObjectPrefix() { return GenLocalIndexPathPrefix(index_meta_.build_id, index_meta_.index_version); } std::string -DiskANNFileManagerImpl::GetLocalRawDataObjectPrefix() { - return GenRawDataPathPrefix(field_meta_.segment_id, field_meta_.field_id); +DiskFileManagerImpl::GetLocalRawDataObjectPrefix() { + return GenFieldRawDataPathPrefix(field_meta_.segment_id, field_meta_.field_id); } bool -DiskANNFileManagerImpl::RemoveFile(const std::string& file) noexcept { +DiskFileManagerImpl::RemoveFile(const std::string& file) noexcept { // remove local file bool localExist = false; auto& local_chunk_manager = LocalChunkManager::GetInstance(); @@ -213,7 +213,7 @@ DiskANNFileManagerImpl::RemoveFile(const std::string& file) noexcept { } std::optional -DiskANNFileManagerImpl::IsExisted(const std::string& file) noexcept { +DiskFileManagerImpl::IsExisted(const std::string& file) noexcept { bool isExist = false; auto& local_chunk_manager = LocalChunkManager::GetInstance(); auto& remote_chunk_manager = MinioChunkManager::GetInstance(); diff --git a/internal/core/src/storage/DiskANNFileManagerImpl.h b/internal/core/src/storage/DiskFileManagerImpl.h similarity index 87% rename from internal/core/src/storage/DiskANNFileManagerImpl.h rename to internal/core/src/storage/DiskFileManagerImpl.h index b876687e62d39..7761545d3f9ad 100644 --- a/internal/core/src/storage/DiskANNFileManagerImpl.h +++ b/internal/core/src/storage/DiskFileManagerImpl.h @@ -27,11 +27,11 @@ namespace milvus::storage { -class DiskANNFileManagerImpl : public FileManagerImpl { +class DiskFileManagerImpl : public FileManagerImpl { public: - explicit DiskANNFileManagerImpl(const FieldDataMeta& field_mata, const IndexMeta& index_meta); + explicit DiskFileManagerImpl(const FieldDataMeta& field_mata, const IndexMeta& index_meta); - virtual ~DiskANNFileManagerImpl(); + virtual ~DiskFileManagerImpl(); virtual bool LoadFile(const std::string& filename) noexcept; @@ -48,7 +48,7 @@ class DiskANNFileManagerImpl : public FileManagerImpl { public: virtual std::string GetName() const { - return "DiskANNFileManagerImpl"; + return "DiskFileManagerImpl"; } std::string @@ -61,7 +61,7 @@ class DiskANNFileManagerImpl : public FileManagerImpl { GetLocalRawDataObjectPrefix(); std::map - GetRemotePaths() const { + GetRemotePathsToFileSize() const { return remote_paths_to_size_; } @@ -101,6 +101,6 @@ class DiskANNFileManagerImpl : public FileManagerImpl { std::map remote_paths_to_size_; }; -using DiskANNFileManagerImplPtr = std::shared_ptr; +using DiskANNFileManagerImplPtr = std::shared_ptr; } // namespace milvus::storage diff --git a/internal/core/src/storage/LocalChunkManager.h b/internal/core/src/storage/LocalChunkManager.h index 260e59eb8d57f..685768a6fbd29 100644 --- a/internal/core/src/storage/LocalChunkManager.h +++ b/internal/core/src/storage/LocalChunkManager.h @@ -42,7 +42,7 @@ class LocalChunkManager : public ChunkManager { static LocalChunkManager& GetInstance() { // thread-safe enough after c++ 11 - static LocalChunkManager instance(ChunkMangerConfig::GetLocalBucketName()); + static LocalChunkManager instance(ChunkMangerConfig::GetLocalRootPath()); return instance; } diff --git a/internal/core/src/storage/MinioChunkManager.cpp b/internal/core/src/storage/MinioChunkManager.cpp index b72869e1fcfba..6e95d6bb406a5 100644 --- a/internal/core/src/storage/MinioChunkManager.cpp +++ b/internal/core/src/storage/MinioChunkManager.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -66,7 +68,8 @@ MinioChunkManager::MinioChunkManager(const std::string& endpoint, const std::string& access_key, const std::string& access_value, const std::string& bucket_name, - bool secure) + bool secure, + bool use_iam) : default_bucket_name_(bucket_name) { Aws::InitAPI(sdk_options_); Aws::Client::ClientConfiguration config; @@ -80,9 +83,20 @@ MinioChunkManager::MinioChunkManager(const std::string& endpoint, config.verifySSL = false; } - client_ = std::make_shared( - Aws::Auth::AWSCredentials(ConvertToAwsString(access_key), ConvertToAwsString(access_value)), config, - Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false); + if (use_iam) { + auto provider = std::make_shared(); + client_ = std::make_shared(provider, config, + Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false); + + LOG_SEGCORE_INFO_C << "use iam mode, credentials{ access_id:" + << provider->GetAWSCredentials().GetAWSAccessKeyId() + << " access_key:" << provider->GetAWSCredentials().GetAWSSecretKey() + << " token:" << provider->GetAWSCredentials().GetSessionToken() << "}"; + } else { + client_ = std::make_shared( + Aws::Auth::AWSCredentials(ConvertToAwsString(access_key), ConvertToAwsString(access_value)), config, + Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false); + } LOG_SEGCORE_INFO_C << "init MinioChunkManager with parameter[endpoint: '" << endpoint << "', access_key:'" << access_key << "', access_value:'" << access_value << "', default_bucket_name:'" << bucket_name diff --git a/internal/core/src/storage/MinioChunkManager.h b/internal/core/src/storage/MinioChunkManager.h index 647e79404884e..d3e92711b42fe 100644 --- a/internal/core/src/storage/MinioChunkManager.h +++ b/internal/core/src/storage/MinioChunkManager.h @@ -38,7 +38,8 @@ class MinioChunkManager : public RemoteChunkManager { const std::string& access_key, const std::string& access_value, const std::string& default_bucket_name, - bool sercure = false); + bool serure = false, + bool use_iam = false); MinioChunkManager(const MinioChunkManager&); MinioChunkManager& @@ -52,7 +53,7 @@ class MinioChunkManager : public RemoteChunkManager { // thread-safe enough after c++ 11 static MinioChunkManager instance(ChunkMangerConfig::GetAddress(), ChunkMangerConfig::GetAccessKey(), ChunkMangerConfig::GetAccessValue(), ChunkMangerConfig::GetBucketName(), - ChunkMangerConfig::GetUseSSL()); + ChunkMangerConfig::GetUseSSL(), ChunkMangerConfig::GetUseIAM()); return instance; } diff --git a/internal/core/src/storage/Util.cpp b/internal/core/src/storage/Util.cpp index 6e58f1ace0bac..275ec1e24589d 100644 --- a/internal/core/src/storage/Util.cpp +++ b/internal/core/src/storage/Util.cpp @@ -19,6 +19,10 @@ #include "common/Consts.h" #include "config/ConfigChunkManager.h" +#ifdef BUILD_DISK_ANN +#include "storage/DiskFileManagerImpl.h" +#endif + namespace milvus::storage { StorageType @@ -320,26 +324,51 @@ GetDimensionFromArrowArray(std::shared_ptr data, DataType data_typ std::string GenLocalIndexPathPrefix(int64_t build_id, int64_t index_version) { - return milvus::ChunkMangerConfig::GetLocalBucketName() + "/" + std::string(INDEX_ROOT_PATH) + "/" + + return milvus::ChunkMangerConfig::GetLocalRootPath() + "/" + std::string(INDEX_ROOT_PATH) + "/" + std::to_string(build_id) + "/" + std::to_string(index_version) + "/"; } std::string GetLocalIndexPathPrefixWithBuildID(int64_t build_id) { - return milvus::ChunkMangerConfig::GetLocalBucketName() + "/" + std::string(INDEX_ROOT_PATH) + "/" + + return milvus::ChunkMangerConfig::GetLocalRootPath() + "/" + std::string(INDEX_ROOT_PATH) + "/" + std::to_string(build_id); } std::string -GenRawDataPathPrefix(int64_t segment_id, int64_t field_id) { - return milvus::ChunkMangerConfig::GetLocalBucketName() + "/" + std::string(RAWDATA_ROOT_PATH) + "/" + +GenFieldRawDataPathPrefix(int64_t segment_id, int64_t field_id) { + return milvus::ChunkMangerConfig::GetLocalRootPath() + "/" + std::string(RAWDATA_ROOT_PATH) + "/" + std::to_string(segment_id) + "/" + std::to_string(field_id) + "/"; } std::string -GetLocalRawDataPathPrefixWithBuildID(int64_t segment_id) { - return milvus::ChunkMangerConfig::GetLocalBucketName() + "/" + std::string(RAWDATA_ROOT_PATH) + "/" + +GetSegmentRawDataPathPrefix(int64_t segment_id) { + return milvus::ChunkMangerConfig::GetLocalRootPath() + "/" + std::string(RAWDATA_ROOT_PATH) + "/" + std::to_string(segment_id); } +std::vector +DISK_LIST() { + static std::vector ret{ + knowhere::IndexEnum::INDEX_DISKANN, + }; + return ret; +} + +bool +is_in_disk_list(const IndexType& index_type) { + return is_in_list(index_type, DISK_LIST); +} + +FileManagerImplPtr +CreateFileManager(IndexType index_type, const FieldDataMeta& field_meta, const IndexMeta& index_meta) { + // TODO :: switch case index type to create file manager +#ifdef BUILD_DISK_ANN + if (is_in_disk_list(index_type)) { + return std::make_shared(field_meta, index_meta); + } +#endif + + return nullptr; +} + } // namespace milvus::storage diff --git a/internal/core/src/storage/Util.h b/internal/core/src/storage/Util.h index 79fdd1f69bce6..1e9d561d09536 100644 --- a/internal/core/src/storage/Util.h +++ b/internal/core/src/storage/Util.h @@ -18,6 +18,7 @@ #include #include +#include #include "storage/PayloadStream.h" #include "storage/FileManager.h" @@ -62,12 +63,22 @@ std::string GenLocalIndexPathPrefix(int64_t build_id, int64_t index_version); std::string -GenRawDataPathPrefix(int64_t segment_id, int64_t field_id); +GenFieldRawDataPathPrefix(int64_t segment_id, int64_t field_id); std::string -GetLocalRawDataPathPrefixWithBuildID(int64_t segment_id); +GetSegmentRawDataPathPrefix(int64_t segment_id); + +template +inline bool +is_in_list(const T& t, std::function()> list_func) { + auto l = list_func(); + return std::find(l.begin(), l.end(), t) != l.end(); +} + +bool +is_in_disk_list(const IndexType& index_type); FileManagerImplPtr -CreateFileManager(knowhere::IndexType index_type, const FieldDataMeta& field_meta, const IndexMeta& index_meta); +CreateFileManager(IndexType index_type, const FieldDataMeta& field_meta, const IndexMeta& index_meta); } // namespace milvus::storage diff --git a/internal/core/src/storage/storage_c.cpp b/internal/core/src/storage/storage_c.cpp new file mode 100644 index 0000000000000..db0e4e038f2f3 --- /dev/null +++ b/internal/core/src/storage/storage_c.cpp @@ -0,0 +1,41 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "storage/storage_c.h" +#include "config/ConfigChunkManager.h" +#include "common/CGoHelper.h" + +#ifdef BUILD_DISK_ANN +#include "storage/LocalChunkManager.h" +#endif + +CStatus +GetLocalUsedSize(int64_t* size) { + try { +#ifdef BUILD_DISK_ANN + auto& local_chunk_manager = milvus::storage::LocalChunkManager::GetInstance(); + auto dir = milvus::ChunkMangerConfig::GetLocalRootPath(); + if (local_chunk_manager.DirExist(dir)) { + *size = local_chunk_manager.GetSizeOfDir(dir); + } else { + *size = 0; + } +#endif + return milvus::SuccessCStatus(); + } catch (std::exception& e) { + return milvus::FailureCStatus(UnexpectedError, e.what()); + } +} diff --git a/internal/core/src/storage/storage_c.h b/internal/core/src/storage/storage_c.h new file mode 100644 index 0000000000000..30d3dc7defb56 --- /dev/null +++ b/internal/core/src/storage/storage_c.h @@ -0,0 +1,29 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common/type_c.h" + +CStatus +GetLocalUsedSize(int64_t* size); + +#ifdef __cplusplus +}; +#endif diff --git a/internal/core/thirdparty/CMakeLists.txt b/internal/core/thirdparty/CMakeLists.txt index f5c40bf71901f..d85e647866732 100644 --- a/internal/core/thirdparty/CMakeLists.txt +++ b/internal/core/thirdparty/CMakeLists.txt @@ -63,7 +63,11 @@ add_subdirectory( protobuf ) add_subdirectory( boost_ext ) add_subdirectory( arrow ) add_subdirectory( rocksdb ) -#add_subdirectory( aws_sdk ) + +# ******************************* Thridparty aws sdk ******************************** +if ( LINUX ) + add_subdirectory( aws_sdk ) +endif() # ******************************* Thridparty marisa ******************************** # TODO: support win. diff --git a/internal/core/thirdparty/knowhere/CMakeLists.txt b/internal/core/thirdparty/knowhere/CMakeLists.txt index b61087a59aade..ec16e3e1d495e 100644 --- a/internal/core/thirdparty/knowhere/CMakeLists.txt +++ b/internal/core/thirdparty/knowhere/CMakeLists.txt @@ -29,9 +29,18 @@ macro(build_knowhere) ${EP_COMMON_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${KNOWHERE_INSTALL_PREFIX} - -DKNOWHERE_WITH_DISKANN=false ) + if ( BUILD_DISK_ANN STREQUAL "ON" ) + set(KNOWHERE_CMAKE_ARGS + ${KNOWHERE_CMAKE_ARGS} + -DKNOWHERE_WITH_DISKANN=true) + else () + set(KNOWHERE_CMAKE_ARGS + ${KNOWHERE_CMAKE_ARGS} + -DKNOWHERE_WITH_DISKANN=false) + endif () + externalproject_add(knowhere_ep # GIT_REPOSITORY "https://github.com/milvus-io/knowhere.git" # GIT_TAG main diff --git a/internal/core/unittest/CMakeLists.txt b/internal/core/unittest/CMakeLists.txt index 1cbc0b28e4154..43057c1d4b3fd 100644 --- a/internal/core/unittest/CMakeLists.txt +++ b/internal/core/unittest/CMakeLists.txt @@ -49,6 +49,15 @@ set(MILVUS_TEST_FILES test_data_codec.cpp ) +if ( BUILD_DISK_ANN STREQUAL "ON" ) + set(MILVUS_TEST_FILES + ${MILVUS_TEST_FILES} +# test_minio_chunk_manager.cpp +# test_disk_file_manager_test.cpp + test_local_chunk_manager.cpp + ) +endif() + if (LINUX OR APPLE) set(MILVUS_TEST_FILES ${MILVUS_TEST_FILES} @@ -74,9 +83,6 @@ if (LINUX) gtest_main milvus_segcore milvus_indexbuilder - milvus_index - milvus_log - pthread ) install(TARGETS index_builder_test DESTINATION unittest) endif() @@ -89,9 +95,6 @@ target_link_libraries(all_tests gtest milvus_segcore milvus_indexbuilder - milvus_index - milvus_log - milvus_storage pthread ) diff --git a/internal/core/unittest/bench/bench_indexbuilder.cpp b/internal/core/unittest/bench/bench_indexbuilder.cpp index 0dea9915e3623..fd61f59958b1d 100644 --- a/internal/core/unittest/bench/bench_indexbuilder.cpp +++ b/internal/core/unittest/bench/bench_indexbuilder.cpp @@ -19,7 +19,6 @@ #include "pb/index_cgo_msg.pb.h" #include "indexbuilder/VecIndexCreator.h" #include "indexbuilder/index_c.h" -#include "indexbuilder/utils.h" #include "test_utils/indexbuilder_test_utils.h" #include "common/Consts.h" @@ -64,9 +63,9 @@ IndexBuilder_build(benchmark::State& state) { auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); for (auto _ : state) { - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - index->BuildWithoutIds(xb_dataset); + auto index = std::make_unique( + milvus::DataType::VECTOR_FLOAT, type_params_str.c_str(), index_params_str.c_str()); + index->Build(xb_dataset); } } @@ -93,10 +92,10 @@ IndexBuilder_build_and_codec(benchmark::State& state) { auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); for (auto _ : state) { - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); + auto index = std::make_unique( + milvus::DataType::VECTOR_FLOAT, type_params_str.c_str(), index_params_str.c_str()); - index->BuildWithoutIds(xb_dataset); + index->Build(xb_dataset); index->Serialize(); } } diff --git a/internal/core/unittest/bench/bench_search.cpp b/internal/core/unittest/bench/bench_search.cpp index 88f58585732fe..0edef079980f5 100644 --- a/internal/core/unittest/bench/bench_search.cpp +++ b/internal/core/unittest/bench/bench_search.cpp @@ -106,8 +106,8 @@ Search_Sealed(benchmark::State& state) { // ivf auto vec = dataset_.get_col(milvus::FieldId(100)); auto indexing = GenVecIndexing(N, dim, vec.data()); - LoadIndexInfo info; - info.index = indexing; + index::LoadIndexInfo info; + info.index = std::move(indexing); info.field_id = (*schema)[FieldName("fakevec")].get_id().get(); info.index_params["index_type"] = "IVF"; info.index_params["index_mode"] = "CPU"; diff --git a/internal/core/unittest/test_bitmap.cpp b/internal/core/unittest/test_bitmap.cpp index 99531c76f604b..e141a00db91ae 100644 --- a/internal/core/unittest/test_bitmap.cpp +++ b/internal/core/unittest/test_bitmap.cpp @@ -22,7 +22,7 @@ TEST(Bitmap, Naive) { int N = 10000; auto raw_data = DataGen(schema, N); auto vec = raw_data.get_col(field_id); - auto sort_index = std::make_shared>(); + auto sort_index = std::make_shared>(); sort_index->Build(N, vec.data()); { auto res = sort_index->Range(0, OpType::LessThan); diff --git a/internal/core/unittest/test_bool_index.cpp b/internal/core/unittest/test_bool_index.cpp index 841d8bd704c44..8b51613e9c94c 100644 --- a/internal/core/unittest/test_bool_index.cpp +++ b/internal/core/unittest/test_bool_index.cpp @@ -26,49 +26,49 @@ class BoolIndexTest : public ::testing::Test { *(half.mutable_data()->Add()) = (i % 2) == 0; } - all_true_ds = GenDsFromPB(all_true); - all_false_ds = GenDsFromPB(all_false); - half_ds = GenDsFromPB(half); + // all_true_ds = GenDsFromPB(all_true); + // all_false_ds = GenDsFromPB(all_false); + // half_ds = GenDsFromPB(half); } void TearDown() override { - delete[](char*)(knowhere::GetDatasetTensor(all_true_ds)); - delete[](char*)(knowhere::GetDatasetTensor(all_false_ds)); - delete[](char*)(knowhere::GetDatasetTensor(half_ds)); + // delete[](char*)(knowhere::GetDatasetTensor(all_true_ds)); + // delete[](char*)(knowhere::GetDatasetTensor(all_false_ds)); + // delete[](char*)(knowhere::GetDatasetTensor(half_ds)); } protected: schemapb::BoolArray all_true; schemapb::BoolArray all_false; schemapb::BoolArray half; - knowhere::DatasetPtr all_true_ds; - knowhere::DatasetPtr all_false_ds; - knowhere::DatasetPtr half_ds; + // knowhere::DatasetPtr all_true_ds; + // knowhere::DatasetPtr all_false_ds; + // knowhere::DatasetPtr half_ds; size_t n; std::vector params; }; TEST_F(BoolIndexTest, Constructor) { - auto index = milvus::scalar::CreateBoolIndex(); + auto index = milvus::index::CreateBoolIndex(); } TEST_F(BoolIndexTest, Count) { { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_true_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_true.data_size(), all_true.data().data()); ASSERT_EQ(n, index->Count()); } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_false_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_false.data_size(), all_false.data().data()); ASSERT_EQ(n, index->Count()); } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(half_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(half.data_size(), half.data().data()); ASSERT_EQ(n, index->Count()); } } @@ -78,8 +78,8 @@ TEST_F(BoolIndexTest, In) { auto false_test = std::make_unique(false); { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_true_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_true.data_size(), all_true.data().data()); auto bitset1 = index->In(1, true_test.get()); ASSERT_TRUE(bitset1->any()); @@ -89,8 +89,8 @@ TEST_F(BoolIndexTest, In) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_false_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_false.data_size(), all_false.data().data()); auto bitset1 = index->In(1, true_test.get()); ASSERT_TRUE(bitset1->none()); @@ -100,8 +100,8 @@ TEST_F(BoolIndexTest, In) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(half_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(half.data_size(), half.data().data()); auto bitset1 = index->In(1, true_test.get()); for (size_t i = 0; i < n; i++) { @@ -120,8 +120,8 @@ TEST_F(BoolIndexTest, NotIn) { auto false_test = std::make_unique(false); { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_true_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_true.data_size(), all_true.data().data()); auto bitset1 = index->NotIn(1, true_test.get()); ASSERT_TRUE(bitset1->none()); @@ -131,8 +131,8 @@ TEST_F(BoolIndexTest, NotIn) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_false_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_false.data_size(), all_false.data().data()); auto bitset1 = index->NotIn(1, true_test.get()); ASSERT_TRUE(bitset1->any()); @@ -142,8 +142,8 @@ TEST_F(BoolIndexTest, NotIn) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(half_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(half.data_size(), half.data().data()); auto bitset1 = index->NotIn(1, true_test.get()); for (size_t i = 0; i < n; i++) { @@ -162,10 +162,10 @@ TEST_F(BoolIndexTest, Codec) { auto false_test = std::make_unique(false); { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_true_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_true.data_size(), all_true.data().data()); - auto copy_index = milvus::scalar::CreateBoolIndex(); + auto copy_index = milvus::index::CreateBoolIndex(); copy_index->Load(index->Serialize(nullptr)); auto bitset1 = copy_index->NotIn(1, true_test.get()); @@ -176,10 +176,10 @@ TEST_F(BoolIndexTest, Codec) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(all_false_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(all_false.data_size(), all_false.data().data()); - auto copy_index = milvus::scalar::CreateBoolIndex(); + auto copy_index = milvus::index::CreateBoolIndex(); copy_index->Load(index->Serialize(nullptr)); auto bitset1 = copy_index->NotIn(1, true_test.get()); @@ -190,10 +190,10 @@ TEST_F(BoolIndexTest, Codec) { } { - auto index = milvus::scalar::CreateBoolIndex(); - index->BuildWithDataset(half_ds); + auto index = milvus::index::CreateBoolIndex(); + index->Build(half.data_size(), half.data().data()); - auto copy_index = milvus::scalar::CreateBoolIndex(); + auto copy_index = milvus::index::CreateBoolIndex(); copy_index->Load(index->Serialize(nullptr)); auto bitset1 = copy_index->NotIn(1, true_test.get()); diff --git a/internal/core/unittest/test_c_api.cpp b/internal/core/unittest/test_c_api.cpp index 19a8823ed7586..7728905e1b4fc 100644 --- a/internal/core/unittest/test_c_api.cpp +++ b/internal/core/unittest/test_c_api.cpp @@ -29,15 +29,20 @@ #include "segcore/reduce_c.h" #include "segcore/Reduce.h" #include "test_utils/DataGen.h" +#include "index/IndexFactory.h" +#include "test_utils/indexbuilder_test_utils.h" namespace chrono = std::chrono; using namespace milvus; using namespace milvus::segcore; +using namespace milvus::index; using namespace knowhere; +using milvus::index::LoadIndexInfo; +using milvus::index::VectorIndex; namespace { -const int DIM = 16; +// const int DIM = 16; const int64_t ROW_COUNT = 100 * 1000; const char* @@ -171,19 +176,38 @@ generate_collection_schema(std::string metric_type, int dim, bool is_binary) { return schema_string; } -VecIndexPtr +// VecIndexPtr +// generate_index( +// void* raw_data, knowhere::Config conf, int64_t dim, int64_t topK, int64_t N, knowhere::IndexType index_type) { +// auto indexing = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type, +// knowhere::IndexMode::MODE_CPU); +// +// auto database = knowhere::GenDataset(N, dim, raw_data); +// indexing->Train(database, conf); +// indexing->AddWithoutIds(database, conf); +// EXPECT_EQ(indexing->Count(), N); +// EXPECT_EQ(indexing->Dim(), dim); +// +// EXPECT_EQ(indexing->Count(), N); +// EXPECT_EQ(indexing->Dim(), dim); +// return indexing; +//} +//} // namespace + +IndexBasePtr generate_index( - void* raw_data, knowhere::Config conf, int64_t dim, int64_t topK, int64_t N, knowhere::IndexType index_type) { - auto indexing = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type, knowhere::IndexMode::MODE_CPU); + void* raw_data, DataType field_type, MetricType metric_type, IndexType index_type, int64_t dim, int64_t N) { + CreateIndexInfo create_index_info{field_type, index_type, metric_type}; + auto indexing = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); auto database = knowhere::GenDataset(N, dim, raw_data); - indexing->Train(database, conf); - indexing->AddWithoutIds(database, conf); - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), dim); + auto build_config = generate_build_conf(index_type, metric_type); + indexing->BuildWithDataset(database, build_config); + + auto vec_indexing = dynamic_cast(indexing.get()); + EXPECT_EQ(vec_indexing->Count(), N); + EXPECT_EQ(vec_indexing->GetDim(), dim); - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), dim); return indexing; } } // namespace @@ -1398,8 +1422,12 @@ TEST(CApiTest, LoadIndexInfo) { std::string index_param_value2 = "cpu"; status = AppendIndexParam(c_load_index_info, index_param_key2.data(), index_param_value2.data()); assert(status.error_code == Success); + std::string index_param_key3 = knowhere::meta::METRIC_TYPE; + std::string index_param_value3 = knowhere::metric::L2; + status = AppendIndexParam(c_load_index_info, index_param_key3.data(), index_param_value3.data()); + assert(status.error_code == Success); std::string field_name = "field0"; - status = AppendFieldInfo(c_load_index_info, 0, CDataType::FloatVector); + status = AppendFieldInfo(c_load_index_info, 0, 0, 0, 0, CDataType::FloatVector); assert(status.error_code == Success); status = AppendIndex(c_load_index_info, c_binary_set); assert(status.error_code == Success); @@ -1434,12 +1462,12 @@ TEST(CApiTest, LoadIndex_Search) { auto binary_set = indexing->Serialize(conf); // fill loadIndexInfo - LoadIndexInfo load_index_info; + milvus::index::LoadIndexInfo load_index_info; auto& index_params = load_index_info.index_params; index_params["index_type"] = "IVF_PQ"; index_params["index_mode"] = "CPU"; auto mode = knowhere::IndexMode::MODE_CPU; - load_index_info.index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_params["index_type"], mode); + load_index_info.index = std::make_unique(index_params["index_type"], knowhere::metric::L2, mode); load_index_info.index->Load(binary_set); // search @@ -1516,21 +1544,17 @@ TEST(CApiTest, Indexing_Without_Predicate) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -1541,7 +1565,7 @@ TEST(CApiTest, Indexing_Without_Predicate) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -1555,7 +1579,7 @@ TEST(CApiTest, Indexing_Without_Predicate) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -1641,21 +1665,17 @@ TEST(CApiTest, Indexing_Expr_Without_Predicate) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -1666,7 +1686,7 @@ TEST(CApiTest, Indexing_Expr_Without_Predicate) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -1680,7 +1700,7 @@ TEST(CApiTest, Indexing_Expr_Without_Predicate) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -1783,22 +1803,17 @@ TEST(CApiTest, Indexing_With_float_Predicate_Range) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -1809,7 +1824,7 @@ TEST(CApiTest, Indexing_With_float_Predicate_Range) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -1823,7 +1838,7 @@ TEST(CApiTest, Indexing_With_float_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -1940,22 +1955,17 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Range) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -1966,7 +1976,7 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Range) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -1980,7 +1990,7 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2081,22 +2091,17 @@ TEST(CApiTest, Indexing_With_float_Predicate_Term) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2107,7 +2112,7 @@ TEST(CApiTest, Indexing_With_float_Predicate_Term) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2121,7 +2126,7 @@ TEST(CApiTest, Indexing_With_float_Predicate_Term) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2231,22 +2236,17 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Term) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2257,7 +2257,7 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Term) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2271,7 +2271,7 @@ TEST(CApiTest, Indexing_Expr_With_float_Predicate_Term) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2373,23 +2373,18 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Range) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{ - {knowhere::meta::METRIC_TYPE, knowhere::metric::JACCARD}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - }; - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_BIN_IVFFLAT); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_BINARY, knowhere::metric::JACCARD, + IndexEnum::INDEX_FAISS_BIN_IVFFLAT, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2400,7 +2395,7 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Range) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2414,7 +2409,7 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::BinaryVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::BinaryVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2529,23 +2524,17 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Range) { ASSERT_TRUE(res_before_load_index.error_code == Success) << res_before_load_index.error_msg; // load index to segment - auto conf = knowhere::Config{ - {knowhere::meta::METRIC_TYPE, knowhere::metric::JACCARD}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - }; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_BIN_IVFFLAT); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_BINARY, knowhere::metric::JACCARD, + IndexEnum::INDEX_FAISS_BIN_IVFFLAT, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2556,7 +2545,7 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Range) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2570,7 +2559,7 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::BinaryVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::BinaryVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2672,23 +2661,17 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Term) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{ - {knowhere::meta::METRIC_TYPE, knowhere::metric::JACCARD}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - }; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_BIN_IVFFLAT); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_BINARY, knowhere::metric::JACCARD, + IndexEnum::INDEX_FAISS_BIN_IVFFLAT, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2699,7 +2682,7 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Term) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2713,7 +2696,7 @@ TEST(CApiTest, Indexing_With_binary_Predicate_Term) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::BinaryVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::BinaryVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -2838,23 +2821,17 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Term) { assert(res_before_load_index.error_code == Success); // load index to segment - auto conf = knowhere::Config{ - {knowhere::meta::METRIC_TYPE, knowhere::metric::JACCARD}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - }; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_BIN_IVFFLAT); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_BINARY, knowhere::metric::JACCARD, + IndexEnum::INDEX_FAISS_BIN_IVFFLAT, DIM, N); // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -2865,7 +2842,7 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Term) { search_result_on_raw_index->seg_offsets_ = vec_ids; search_result_on_raw_index->distances_ = vec_dis; - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -2879,7 +2856,7 @@ TEST(CApiTest, Indexing_Expr_With_binary_Predicate_Term) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::BinaryVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::BinaryVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load index for vec field, load raw data for scalar filed @@ -3022,29 +2999,9 @@ TEST(CApiTest, SealedSegment_search_float_Predicate_Range) { Timestamp time = 10000000; // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); - - // gen query dataset - auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); - std::vector vec_ids(ids, ids + TOPK * num_queries); - std::vector vec_dis; - for (int j = 0; j < TOPK * num_queries; ++j) { - vec_dis.push_back(dis[j] * -1); - } - - auto binary_set = indexing->Serialize(conf); + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -3058,15 +3015,18 @@ TEST(CApiTest, SealedSegment_search_float_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); auto load_index_info = (LoadIndexInfo*)c_load_index_info; - auto query_dataset2 = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto index = std::dynamic_pointer_cast(load_index_info->index); - auto result_on_index2 = index->Query(query_dataset2, conf, nullptr); - auto ids2 = knowhere::GetDatasetIDs(result_on_index2); - auto dis2 = knowhere::GetDatasetDistance(result_on_index2); + auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); + auto vec_index = dynamic_cast(indexing.get()); + SearchInfo search_info; + search_info.topk_ = TOPK; + search_info.metric_type_ = knowhere::metric::L2; + search_info.search_params_ = generate_search_conf(IndexEnum::INDEX_FAISS_IVFPQ, knowhere::metric::L2); + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + EXPECT_EQ(result_on_index->distances_.size(), num_queries * TOPK); auto c_counter_field_data = CLoadFieldDataInfo{ 101, @@ -3317,18 +3277,10 @@ TEST(CApiTest, SealedSegment_search_float_With_Expr_Predicate_Range) { Timestamp time = 10000000; // load index to segment - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}}; + auto indexing = generate_index(vec_col.data(), DataType::VECTOR_FLOAT, knowhere::metric::L2, + IndexEnum::INDEX_FAISS_IVFPQ, DIM, N); - auto indexing = generate_index(vec_col.data(), conf, DIM, TOPK, N, IndexEnum::INDEX_FAISS_IVFPQ); - - auto binary_set = indexing->Serialize(conf); + auto binary_set = indexing->Serialize(milvus::Config{}); void* c_load_index_info = nullptr; status = NewLoadIndexInfo(&c_load_index_info); assert(status.error_code == Success); @@ -3342,16 +3294,10 @@ TEST(CApiTest, SealedSegment_search_float_With_Expr_Predicate_Range) { AppendIndexParam(c_load_index_info, index_type_key.c_str(), index_type_value.c_str()); AppendIndexParam(c_load_index_info, index_mode_key.c_str(), index_mode_value.c_str()); AppendIndexParam(c_load_index_info, metric_type_key.c_str(), metric_type_value.c_str()); - AppendFieldInfo(c_load_index_info, 100, CDataType::FloatVector); + AppendFieldInfo(c_load_index_info, 0, 0, 0, 100, CDataType::FloatVector); AppendIndex(c_load_index_info, (CBinarySet)&binary_set); // load vec index - auto load_index_info = (LoadIndexInfo*)c_load_index_info; - auto query_dataset2 = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto index = std::dynamic_pointer_cast(load_index_info->index); - auto result_on_index2 = index->Query(query_dataset2, conf, nullptr); - auto ids2 = knowhere::GetDatasetIDs(result_on_index2); - auto dis2 = knowhere::GetDatasetDistance(result_on_index2); status = UpdateSealedSegmentIndex(segment, c_load_index_info); assert(status.error_code == Success); @@ -3385,9 +3331,12 @@ TEST(CApiTest, SealedSegment_search_float_With_Expr_Predicate_Range) { // gen query dataset auto query_dataset = knowhere::GenDataset(num_queries, DIM, query_ptr); - auto result_on_index = indexing->Query(query_dataset, conf, nullptr); - auto ids = knowhere::GetDatasetIDs(result_on_index); - auto dis = knowhere::GetDatasetDistance(result_on_index); + auto vec_index = dynamic_cast(indexing.get()); + auto search_plan = reinterpret_cast(plan); + SearchInfo search_info = search_plan->plan_node_->search_info_; + auto result_on_index = vec_index->Query(query_dataset, search_info, nullptr); + auto ids = result_on_index->seg_offsets_.data(); + auto dis = result_on_index->distances_.data(); std::vector vec_ids(ids, ids + TOPK * num_queries); std::vector vec_dis; for (int j = 0; j < TOPK * num_queries; ++j) { @@ -3451,61 +3400,61 @@ TEST(CApiTest, RetriveScalarFieldFromSealedSegmentWithIndex) { // load index for int8 field auto age8_col = raw_data.get_col(i8_fid); GenScalarIndexing(N, age8_col.data()); - auto age8_index = milvus::scalar::CreateScalarIndexSort(); + auto age8_index = milvus::index::CreateScalarIndexSort(); age8_index->Build(N, age8_col.data()); load_index_info.field_id = i8_fid.get(); - load_index_info.field_type = Int8; - load_index_info.index = std::shared_ptr>(age8_index.release()); + load_index_info.field_type = DataType::INT8; + load_index_info.index = std::move(age8_index); segment->LoadIndex(load_index_info); // load index for 16 field auto age16_col = raw_data.get_col(i16_fid); GenScalarIndexing(N, age16_col.data()); - auto age16_index = milvus::scalar::CreateScalarIndexSort(); + auto age16_index = milvus::index::CreateScalarIndexSort(); age16_index->Build(N, age16_col.data()); load_index_info.field_id = i16_fid.get(); - load_index_info.field_type = Int16; - load_index_info.index = std::shared_ptr>(age16_index.release()); + load_index_info.field_type = DataType::INT16; + load_index_info.index = std::move(age16_index); segment->LoadIndex(load_index_info); // load index for int32 field auto age32_col = raw_data.get_col(i32_fid); GenScalarIndexing(N, age32_col.data()); - auto age32_index = milvus::scalar::CreateScalarIndexSort(); + auto age32_index = milvus::index::CreateScalarIndexSort(); age32_index->Build(N, age32_col.data()); load_index_info.field_id = i32_fid.get(); - load_index_info.field_type = Int32; - load_index_info.index = std::shared_ptr>(age32_index.release()); + load_index_info.field_type = DataType::INT32; + load_index_info.index = std::move(age32_index); segment->LoadIndex(load_index_info); // load index for int64 field auto age64_col = raw_data.get_col(i64_fid); GenScalarIndexing(N, age64_col.data()); - auto age64_index = milvus::scalar::CreateScalarIndexSort(); + auto age64_index = milvus::index::CreateScalarIndexSort(); age64_index->Build(N, age64_col.data()); load_index_info.field_id = i64_fid.get(); - load_index_info.field_type = Int64; - load_index_info.index = std::shared_ptr>(age64_index.release()); + load_index_info.field_type = DataType::INT64; + load_index_info.index = std::move(age64_index); segment->LoadIndex(load_index_info); // load index for float field auto age_float_col = raw_data.get_col(float_fid); GenScalarIndexing(N, age_float_col.data()); - auto age_float_index = milvus::scalar::CreateScalarIndexSort(); + auto age_float_index = milvus::index::CreateScalarIndexSort(); age_float_index->Build(N, age_float_col.data()); load_index_info.field_id = float_fid.get(); - load_index_info.field_type = Float; - load_index_info.index = std::shared_ptr>(age_float_index.release()); + load_index_info.field_type = DataType::FLOAT; + load_index_info.index = std::move(age_float_index); segment->LoadIndex(load_index_info); // load index for double field auto age_double_col = raw_data.get_col(double_fid); GenScalarIndexing(N, age_double_col.data()); - auto age_double_index = milvus::scalar::CreateScalarIndexSort(); + auto age_double_index = milvus::index::CreateScalarIndexSort(); age_double_index->Build(N, age_double_col.data()); load_index_info.field_id = double_fid.get(); - load_index_info.field_type = Float; - load_index_info.index = std::shared_ptr>(age_double_index.release()); + load_index_info.field_type = DataType::FLOAT; + load_index_info.index = std::move(age_double_index); segment->LoadIndex(load_index_info); // create retrieve plan diff --git a/internal/core/unittest/test_diskann_filemanager_test.cpp b/internal/core/unittest/test_disk_file_manager_test.cpp similarity index 93% rename from internal/core/unittest/test_diskann_filemanager_test.cpp rename to internal/core/unittest/test_disk_file_manager_test.cpp index 74ab40dd98a40..f3c9bea4b257d 100644 --- a/internal/core/unittest/test_diskann_filemanager_test.cpp +++ b/internal/core/unittest/test_disk_file_manager_test.cpp @@ -22,7 +22,7 @@ #include "storage/Event.h" #include "storage/MinioChunkManager.h" #include "storage/LocalChunkManager.h" -#include "storage/DiskANNFileManagerImpl.h" +#include "storage/DiskFileManagerImpl.h" #include "config/ConfigChunkManager.h" #include "config/ConfigKnowhere.h" @@ -85,6 +85,7 @@ class DiskAnnFileManagerTest : public testing::Test { auto accessValue = minioConfig["secretAccessKey"].as(); auto useSSL = minioConfig["useSSL"].as(); auto bucketName = minioConfig["bucketName"].as(); + ChunkMangerConfig::SetAddress(endpoint); ChunkMangerConfig::SetAccessKey(accessKey); ChunkMangerConfig::SetAccessValue(accessValue); @@ -94,7 +95,7 @@ class DiskAnnFileManagerTest : public testing::Test { void InitLocalChunkManager() { - ChunkMangerConfig::SetLocalBucketName("/tmp/diskann"); + ChunkMangerConfig::SetLocalRootPath("/tmp/diskann"); config::KnowhereSetIndexSliceSize(5); } @@ -131,12 +132,13 @@ TEST_F(DiskAnnFileManagerTest, AddFilePositive) { IndexMeta index_meta = {3, 100, 1000, 1, "index"}; int64_t slice_size = config::KnowhereGetIndexSliceSize() << 20; - auto diskAnnFileManager = std::make_shared(filed_data_meta, index_meta); + auto diskAnnFileManager = std::make_shared(filed_data_meta, index_meta); diskAnnFileManager->AddFile(indexFilePath); // check result auto remotePrefix = diskAnnFileManager->GetRemoteIndexObjectPrefix(); auto remoteIndexFiles = rcm.ListWithPrefix(remotePrefix); + auto num_slice = index_size / slice_size; EXPECT_EQ(remoteIndexFiles.size(), index_size % slice_size == 0 ? num_slice : num_slice + 1); @@ -149,7 +151,14 @@ TEST_F(DiskAnnFileManagerTest, AddFilePositive) { auto payload = index->GetPayload(); auto rows = payload->rows; auto rawData = payload->raw_data; + EXPECT_EQ(rows, index_size); EXPECT_EQ(rawData[0], data[0]); EXPECT_EQ(rawData[4], data[4]); + + auto files = diskAnnFileManager->GetRemotePathsToFileSize(); + for (auto& value : files) { + rcm.Remove(value.first); + } + rcm.DeleteBucket(testBucketName); } diff --git a/internal/core/unittest/test_expr.cpp b/internal/core/unittest/test_expr.cpp index 099473fa82ed4..76efe66d5205e 100644 --- a/internal/core/unittest/test_expr.cpp +++ b/internal/core/unittest/test_expr.cpp @@ -630,28 +630,28 @@ TEST(Expr, TestCompareWithScalarIndex) { auto seg = CreateSealedSegment(schema); int N = 1000; auto raw_data = DataGen(schema, N); - LoadIndexInfo load_index_info; + index::LoadIndexInfo load_index_info; // load index for int32 field auto age32_col = raw_data.get_col(i32_fid); age32_col[0] = 1000; GenScalarIndexing(N, age32_col.data()); - auto age32_index = milvus::scalar::CreateScalarIndexSort(); + auto age32_index = milvus::index::CreateScalarIndexSort(); age32_index->Build(N, age32_col.data()); load_index_info.field_id = i32_fid.get(); - load_index_info.field_type = Int32; - load_index_info.index = std::shared_ptr>(age32_index.release()); + load_index_info.field_type = DataType::INT32; + load_index_info.index = std::move(age32_index); seg->LoadIndex(load_index_info); // load index for int64 field auto age64_col = raw_data.get_col(i64_fid); age64_col[0] = 2000; GenScalarIndexing(N, age64_col.data()); - auto age64_index = milvus::scalar::CreateScalarIndexSort(); + auto age64_index = milvus::index::CreateScalarIndexSort(); age64_index->Build(N, age64_col.data()); load_index_info.field_id = i64_fid.get(); - load_index_info.field_type = Int64; - load_index_info.index = std::shared_ptr>(age64_index.release()); + load_index_info.field_type = DataType::INT64; + load_index_info.index = std::move(age64_index); seg->LoadIndex(load_index_info); ExecExprVisitor visitor(*seg, seg->get_row_count(), MAX_TIMESTAMP); @@ -720,26 +720,26 @@ TEST(Expr, TestCompareWithScalarIndexMaris) { auto seg = CreateSealedSegment(schema); int N = 1000; auto raw_data = DataGen(schema, N); - LoadIndexInfo load_index_info; + index::LoadIndexInfo load_index_info; // load index for int32 field auto str1_col = raw_data.get_col(str1_fid); GenScalarIndexing(N, str1_col.data()); - auto str1_index = milvus::scalar::CreateScalarIndexSort(); + auto str1_index = milvus::index::CreateScalarIndexSort(); str1_index->Build(N, str1_col.data()); load_index_info.field_id = str1_fid.get(); - load_index_info.field_type = VarChar; - load_index_info.index = std::shared_ptr>(str1_index.release()); + load_index_info.field_type = DataType::VARCHAR; + load_index_info.index = std::move(str1_index); seg->LoadIndex(load_index_info); // load index for int64 field auto str2_col = raw_data.get_col(str2_fid); GenScalarIndexing(N, str2_col.data()); - auto str2_index = milvus::scalar::CreateScalarIndexSort(); + auto str2_index = milvus::index::CreateScalarIndexSort(); str2_index->Build(N, str2_col.data()); load_index_info.field_id = str2_fid.get(); - load_index_info.field_type = VarChar; - load_index_info.index = std::shared_ptr>(str2_index.release()); + load_index_info.field_type = DataType::VARCHAR; + load_index_info.index = std::move(str2_index); seg->LoadIndex(load_index_info); ExecExprVisitor visitor(*seg, seg->get_row_count(), MAX_TIMESTAMP); @@ -1300,72 +1300,72 @@ TEST(Expr, TestBinaryArithOpEvalRangeWithScalarSortIndex) { auto seg = CreateSealedSegment(schema); int N = 1000; auto raw_data = DataGen(schema, N); - LoadIndexInfo load_index_info; + index::LoadIndexInfo load_index_info; // load index for int8 field auto age8_col = raw_data.get_col(i8_fid); age8_col[0] = 4; GenScalarIndexing(N, age8_col.data()); - auto age8_index = milvus::scalar::CreateScalarIndexSort(); + auto age8_index = milvus::index::CreateScalarIndexSort(); age8_index->Build(N, age8_col.data()); load_index_info.field_id = i8_fid.get(); - load_index_info.field_type = Int8; - load_index_info.index = std::shared_ptr>(age8_index.release()); + load_index_info.field_type = DataType::INT8; + load_index_info.index = std::move(age8_index); seg->LoadIndex(load_index_info); // load index for 16 field auto age16_col = raw_data.get_col(i16_fid); age16_col[0] = 2000; GenScalarIndexing(N, age16_col.data()); - auto age16_index = milvus::scalar::CreateScalarIndexSort(); + auto age16_index = milvus::index::CreateScalarIndexSort(); age16_index->Build(N, age16_col.data()); load_index_info.field_id = i16_fid.get(); - load_index_info.field_type = Int16; - load_index_info.index = std::shared_ptr>(age16_index.release()); + load_index_info.field_type = DataType::INT16; + load_index_info.index = std::move(age16_index); seg->LoadIndex(load_index_info); // load index for int32 field auto age32_col = raw_data.get_col(i32_fid); age32_col[0] = 2000; GenScalarIndexing(N, age32_col.data()); - auto age32_index = milvus::scalar::CreateScalarIndexSort(); + auto age32_index = milvus::index::CreateScalarIndexSort(); age32_index->Build(N, age32_col.data()); load_index_info.field_id = i32_fid.get(); - load_index_info.field_type = Int32; - load_index_info.index = std::shared_ptr>(age32_index.release()); + load_index_info.field_type = DataType::INT32; + load_index_info.index = std::move(age32_index); seg->LoadIndex(load_index_info); // load index for int64 field auto age64_col = raw_data.get_col(i64_fid); age64_col[0] = 2000; GenScalarIndexing(N, age64_col.data()); - auto age64_index = milvus::scalar::CreateScalarIndexSort(); + auto age64_index = milvus::index::CreateScalarIndexSort(); age64_index->Build(N, age64_col.data()); load_index_info.field_id = i64_fid.get(); - load_index_info.field_type = Int64; - load_index_info.index = std::shared_ptr>(age64_index.release()); + load_index_info.field_type = DataType::INT64; + load_index_info.index = std::move(age64_index); seg->LoadIndex(load_index_info); // load index for float field auto age_float_col = raw_data.get_col(float_fid); age_float_col[0] = 2000; GenScalarIndexing(N, age_float_col.data()); - auto age_float_index = milvus::scalar::CreateScalarIndexSort(); + auto age_float_index = milvus::index::CreateScalarIndexSort(); age_float_index->Build(N, age_float_col.data()); load_index_info.field_id = float_fid.get(); - load_index_info.field_type = Float; - load_index_info.index = std::shared_ptr>(age_float_index.release()); + load_index_info.field_type = DataType::FLOAT; + load_index_info.index = std::move(age_float_index); seg->LoadIndex(load_index_info); // load index for double field auto age_double_col = raw_data.get_col(double_fid); age_double_col[0] = 2000; GenScalarIndexing(N, age_double_col.data()); - auto age_double_index = milvus::scalar::CreateScalarIndexSort(); + auto age_double_index = milvus::index::CreateScalarIndexSort(); age_double_index->Build(N, age_double_col.data()); load_index_info.field_id = double_fid.get(); - load_index_info.field_type = Float; - load_index_info.index = std::shared_ptr>(age_double_index.release()); + load_index_info.field_type = DataType::FLOAT; + load_index_info.index = std::move(age_double_index); seg->LoadIndex(load_index_info); auto seg_promote = dynamic_cast(seg.get()); diff --git a/internal/core/unittest/test_index_c_api.cpp b/internal/core/unittest/test_index_c_api.cpp index 6e63005f0110c..9321d08c835b3 100644 --- a/internal/core/unittest/test_index_c_api.cpp +++ b/internal/core/unittest/test_index_c_api.cpp @@ -21,7 +21,6 @@ #include "indexbuilder/VecIndexCreator.h" #include "indexbuilder/index_c.h" -#include "indexbuilder/utils.h" #include "test_utils/DataGen.h" #include "test_utils/indexbuilder_test_utils.h" #include "indexbuilder/ScalarIndexCreator.h" diff --git a/internal/core/unittest/test_index_wrapper.cpp b/internal/core/unittest/test_index_wrapper.cpp index d70baee4b65f5..aaafca18db175 100644 --- a/internal/core/unittest/test_index_wrapper.cpp +++ b/internal/core/unittest/test_index_wrapper.cpp @@ -13,20 +13,17 @@ #include #include #include -#include -#include -#include -#include +#include +#include "indexbuilder/IndexFactory.h" #include "indexbuilder/VecIndexCreator.h" -#include "indexbuilder/index_c.h" -#include "indexbuilder/utils.h" -#include "pb/index_cgo_msg.pb.h" -#include "test_utils/DataGen.h" +#include "common/QueryResult.h" #include "test_utils/indexbuilder_test_utils.h" +#include "knowhere/archive/KnowhereConfig.h" -constexpr int64_t NB = 1000; -namespace indexcgo = milvus::proto::indexcgo; +using namespace milvus; +using namespace milvus::segcore; +using namespace milvus::proto::indexcgo; using Param = std::pair; @@ -35,11 +32,19 @@ class IndexWrapperTest : public ::testing::TestWithParam { void SetUp() override { knowhere::KnowhereConfig::SetStatisticsLevel(3); + knowhere::KnowhereConfig::SetIndexFileSliceSize(16); auto param = GetParam(); index_type = param.first; metric_type = param.second; std::tie(type_params, index_params) = generate_params(index_type, metric_type); + bool ok; + ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); + assert(ok); + ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); + assert(ok); + + search_conf = generate_search_conf(index_type, metric_type); std::map is_binary_map = { {knowhere::IndexEnum::INDEX_FAISS_IDMAP, false}, @@ -53,24 +58,21 @@ class IndexWrapperTest : public ::testing::TestWithParam { }; is_binary = is_binary_map[index_type]; - - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); + if (is_binary) { + vec_field_data_type = CDataType::FloatVector; + } else { + vec_field_data_type = CDataType::BinaryVector; + } auto dataset = GenDataset(NB, metric_type, is_binary); if (!is_binary) { xb_data = dataset.get_col(milvus::FieldId(100)); xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - xq_data = dataset.get_col(milvus::FieldId(100)); - xq_dataset = knowhere::GenDataset(NQ, DIM, xq_data.data()); + xq_dataset = knowhere::GenDataset(NQ, DIM, xb_data.data() + DIM * query_offset); } else { xb_bin_data = dataset.get_col(milvus::FieldId(100)); xb_dataset = knowhere::GenDataset(NB, DIM, xb_bin_data.data()); - xq_bin_data = dataset.get_col(milvus::FieldId(100)); - xq_dataset = knowhere::GenDataset(NQ, DIM, xq_bin_data.data()); + xq_dataset = knowhere::GenDataset(NQ, DIM, xb_bin_data.data() + DIM * query_offset); } } @@ -83,271 +85,17 @@ class IndexWrapperTest : public ::testing::TestWithParam { indexcgo::TypeParams type_params; indexcgo::IndexParams index_params; std::string type_params_str, index_params_str; + milvus::Config search_conf; bool is_binary; + CDataType vec_field_data_type; knowhere::DatasetPtr xb_dataset; std::vector xb_data; std::vector xb_bin_data; - std::vector ids; knowhere::DatasetPtr xq_dataset; - std::vector xq_data; - std::vector xq_bin_data; + int64_t query_offset = 100; + int64_t NB = 10000; }; -TEST(PQ, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFPQ; - auto metric_type = knowhere::metric::L2; - auto conf = generate_conf(index_type, metric_type); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto dataset = GenDataset(NB, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - ASSERT_NO_THROW(index->Train(xb_dataset, conf)); - ASSERT_NO_THROW(index->AddWithoutIds(xb_dataset, conf)); -} - -TEST(IVFFLATNM, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; - auto metric_type = knowhere::metric::L2; - auto conf = generate_conf(index_type, metric_type); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto dataset = GenDataset(NB, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - ASSERT_NO_THROW(index->Train(xb_dataset, conf)); - ASSERT_NO_THROW(index->AddWithoutIds(xb_dataset, conf)); -} - -TEST(IVFFLATNM, Query) { - knowhere::KnowhereConfig::SetStatisticsLevel(3); - - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; - auto metric_type = knowhere::metric::L2; - auto conf = generate_conf(index_type, metric_type); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto dataset = GenDataset(NB, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - ASSERT_NO_THROW(index->Train(xb_dataset, conf)); - ASSERT_NO_THROW(index->AddWithoutIds(xb_dataset, conf)); - auto bs = index->Serialize(conf); - auto bptr = std::make_shared(); - bptr->data = std::shared_ptr((uint8_t*)xb_data.data(), [&](uint8_t*) {}); - bptr->size = DIM * NB * sizeof(float); - bs.Append(RAW_DATA, bptr); - index->Load(bs); - auto xq_data = dataset.get_col(milvus::FieldId(100)); - auto xq_dataset = knowhere::GenDataset(NQ, DIM, xq_data.data()); - auto result = index->Query(xq_dataset, conf, nullptr); - - ASSERT_GT(index->Size(), 0); - - auto stats = index->GetStatistics(); - ASSERT_TRUE(stats != nullptr); - index->ClearStatistics(); -} - -TEST(BINFLAT, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT; - auto metric_type = knowhere::metric::JACCARD; - auto conf = generate_conf(index_type, metric_type); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto dataset = GenDataset(NB, metric_type, true); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - std::vector ids(NB, 0); - std::iota(ids.begin(), ids.end(), 0); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - ASSERT_NO_THROW(index->BuildAll(xb_dataset, conf)); -} - -void -print_query_result(const std::unique_ptr& result) { - for (auto i = 0; i < result->nq; i++) { - printf("result of %dth query:\n", i); - for (auto j = 0; j < result->topk; j++) { - auto offset = i * result->topk + j; - printf("id: %ld, distance: %f\n", result->ids[offset], result->distances[offset]); - } - } -} - -// test for: https://github.com/milvus-io/milvus/issues/6569 -TEST(BinIVFFlat, Build_and_Query) { - knowhere::KnowhereConfig::SetStatisticsLevel(2); - - auto index_type = knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT; - auto metric_type = knowhere::metric::TANIMOTO; - auto conf = generate_conf(index_type, metric_type); - auto topk = 10; - knowhere::SetMetaTopk(conf, topk); - knowhere::SetIndexParamNlist(conf, 1); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto nb = 2; - auto dim = 128; - auto nq = 10; - auto dataset = GenDataset(std::max(nq, nb), metric_type, true); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - std::vector ids(nb, 0); - std::iota(ids.begin(), ids.end(), 0); - auto xb_dataset = knowhere::GenDataset(nb, dim, xb_data.data()); - index->BuildAll(xb_dataset, conf); - auto xq_data = dataset.get_col(milvus::FieldId(100)); - auto xq_dataset = knowhere::GenDataset(nq, dim, xq_data.data()); - auto result = index->Query(xq_dataset, conf, nullptr); - - auto hit_ids = knowhere::GetDatasetIDs(result); - auto distances = knowhere::GetDatasetDistance(result); - - auto query_res = std::make_unique(); - query_res->nq = nq; - query_res->topk = topk; - query_res->ids.resize(nq * topk); - query_res->distances.resize(nq * topk); - memcpy(query_res->ids.data(), hit_ids, sizeof(int64_t) * nq * topk); - memcpy(query_res->distances.data(), distances, sizeof(float) * nq * topk); - - print_query_result(query_res); - - ASSERT_GT(index->Size(), 0); - - auto stats = index->GetStatistics(); - ASSERT_TRUE(stats != nullptr); - index->ClearStatistics(); -} - -TEST(BINIDMAP, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP; - auto metric_type = knowhere::metric::JACCARD; - auto conf = generate_conf(index_type, metric_type); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(index_type); - auto dataset = GenDataset(NB, metric_type, true); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - std::vector ids(NB, 0); - std::iota(ids.begin(), ids.end(), 0); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - ASSERT_NO_THROW(index->BuildAll(xb_dataset, conf)); -} - -TEST(PQWrapper, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFPQ; - auto metric_type = knowhere::metric::L2; - indexcgo::TypeParams type_params; - indexcgo::IndexParams index_params; - std::tie(type_params, index_params) = generate_params(index_type, metric_type); - std::string type_params_str, index_params_str; - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); - auto dataset = GenDataset(NB, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index->BuildWithoutIds(xb_dataset)); -} - -TEST(IVFFLATNMWrapper, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; - auto metric_type = knowhere::metric::L2; - indexcgo::TypeParams type_params; - indexcgo::IndexParams index_params; - std::tie(type_params, index_params) = generate_params(index_type, metric_type); - std::string type_params_str, index_params_str; - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); - auto dataset = GenDataset(NB, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index->BuildWithoutIds(xb_dataset)); -} - -TEST(IVFFLATNMWrapper, Codec) { - int64_t flat_nb = 100000; - auto index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; - auto metric_type = knowhere::metric::L2; - indexcgo::TypeParams type_params; - indexcgo::IndexParams index_params; - std::tie(type_params, index_params) = generate_params(index_type, metric_type); - std::string type_params_str, index_params_str; - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); - auto dataset = GenDataset(flat_nb, metric_type, false); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - auto xb_dataset = knowhere::GenDataset(flat_nb, DIM, xb_data.data()); - auto index_wrapper = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index_wrapper->BuildWithoutIds(xb_dataset)); - - auto binary_set = index_wrapper->Serialize(); - auto copy_index_wrapper = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - - ASSERT_NO_THROW(copy_index_wrapper->Load(binary_set)); - ASSERT_EQ(copy_index_wrapper->dim(), copy_index_wrapper->dim()); - - auto copy_binary_set = copy_index_wrapper->Serialize(); - ASSERT_EQ(binary_set.binary_map_.size(), copy_binary_set.binary_map_.size()); - - for (const auto& [k, v] : binary_set.binary_map_) { - ASSERT_TRUE(copy_binary_set.Contains(k)); - } -} - -TEST(BinFlatWrapper, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT; - auto metric_type = knowhere::metric::JACCARD; - indexcgo::TypeParams type_params; - indexcgo::IndexParams index_params; - std::tie(type_params, index_params) = generate_params(index_type, metric_type); - std::string type_params_str, index_params_str; - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); - auto dataset = GenDataset(NB, metric_type, true); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - std::vector ids(NB, 0); - std::iota(ids.begin(), ids.end(), 0); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index->BuildWithoutIds(xb_dataset)); - // ASSERT_NO_THROW(index->BuildWithIds(xb_dataset)); -} - -TEST(BinIdMapWrapper, Build) { - auto index_type = knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP; - auto metric_type = knowhere::metric::JACCARD; - indexcgo::TypeParams type_params; - indexcgo::IndexParams index_params; - std::tie(type_params, index_params) = generate_params(index_type, metric_type); - std::string type_params_str, index_params_str; - bool ok; - ok = google::protobuf::TextFormat::PrintToString(type_params, &type_params_str); - assert(ok); - ok = google::protobuf::TextFormat::PrintToString(index_params, &index_params_str); - assert(ok); - auto dataset = GenDataset(NB, metric_type, true); - auto xb_data = dataset.get_col(milvus::FieldId(100)); - std::vector ids(NB, 0); - std::iota(ids.begin(), ids.end(), 0); - auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index->BuildWithoutIds(xb_dataset)); - // ASSERT_NO_THROW(index->BuildWithIds(xb_dataset)); -} - INSTANTIATE_TEST_CASE_P( IndexTypeParameters, IndexWrapperTest, @@ -361,54 +109,32 @@ INSTANTIATE_TEST_CASE_P( std::pair(knowhere::IndexEnum::INDEX_HNSW, knowhere::metric::L2), std::pair(knowhere::IndexEnum::INDEX_ANNOY, knowhere::metric::L2))); -TEST_P(IndexWrapperTest, Constructor) { - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); -} - -TEST_P(IndexWrapperTest, Dim) { - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); +TEST_P(IndexWrapperTest, BuildAndQuery) { + auto index = milvus::indexbuilder::IndexFactory::GetInstance().CreateIndex( + vec_field_data_type, type_params_str.c_str(), index_params_str.c_str()); - ASSERT_EQ(index->dim(), DIM); -} - -TEST_P(IndexWrapperTest, BuildWithoutIds) { - auto index = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - ASSERT_NO_THROW(index->BuildWithoutIds(xb_dataset)); -} - -TEST_P(IndexWrapperTest, Codec) { - auto index_wrapper = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - - ASSERT_NO_THROW(index_wrapper->BuildWithoutIds(xb_dataset)); - - auto binary_set = index_wrapper->Serialize(); - auto copy_index_wrapper = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - - ASSERT_NO_THROW(copy_index_wrapper->Load(binary_set)); - ASSERT_EQ(copy_index_wrapper->dim(), copy_index_wrapper->dim()); - - auto copy_binary_set = copy_index_wrapper->Serialize(); - ASSERT_EQ(binary_set.binary_map_.size(), copy_binary_set.binary_map_.size()); - - for (const auto& [k, v] : binary_set.binary_map_) { - ASSERT_TRUE(copy_binary_set.Contains(k)); + auto dataset = GenDataset(NB, metric_type, is_binary); + auto xb_data = dataset.get_col(milvus::FieldId(100)); + auto xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); + ASSERT_NO_THROW(index->Build(xb_dataset)); + auto binary_set = index->Serialize(); + auto copy_index = milvus::indexbuilder::IndexFactory::GetInstance().CreateIndex( + vec_field_data_type, type_params_str.c_str(), index_params_str.c_str()); + auto vec_index = static_cast(copy_index.get()); + ASSERT_EQ(vec_index->dim(), DIM); + ASSERT_NO_THROW(vec_index->Load(binary_set)); + + milvus::SearchInfo search_info; + search_info.topk_ = K; + search_info.metric_type_ = metric_type; + search_info.search_params_ = search_conf; + auto result = vec_index->Query(xq_dataset, search_info, nullptr); + + EXPECT_EQ(result->total_nq_, NQ); + EXPECT_EQ(result->unity_topK_, K); + EXPECT_EQ(result->distances_.size(), NQ * K); + EXPECT_EQ(result->seg_offsets_.size(), NQ * K); + if (!is_binary) { + EXPECT_EQ(result->seg_offsets_[0], query_offset); } } - -TEST_P(IndexWrapperTest, Query) { - auto index_wrapper = - std::make_unique(type_params_str.c_str(), index_params_str.c_str()); - - index_wrapper->BuildWithoutIds(xb_dataset); - - std::unique_ptr query_result = index_wrapper->Query(xq_dataset); - ASSERT_EQ(query_result->topk, K); - ASSERT_EQ(query_result->nq, NQ); - ASSERT_EQ(query_result->distances.size(), query_result->topk * query_result->nq); - ASSERT_EQ(query_result->ids.size(), query_result->topk * query_result->nq); -} diff --git a/internal/core/unittest/test_indexing.cpp b/internal/core/unittest/test_indexing.cpp index 4661652ad8109..1e510bf06a24d 100644 --- a/internal/core/unittest/test_indexing.cpp +++ b/internal/core/unittest/test_indexing.cpp @@ -15,15 +15,26 @@ #include #include #include +#include #include "faiss/utils/distances.h" -#include "knowhere/index/vector_index/IndexIVF.h" -#include "knowhere/index/vector_offset_index/IndexIVF_NM.h" #include "query/SearchBruteForce.h" #include "segcore/Reduce.h" +#include "index/IndexFactory.h" +#include "knowhere/archive/KnowhereConfig.h" +#include "common/QueryResult.h" +#include "test_utils/indexbuilder_test_utils.h" #include "test_utils/DataGen.h" #include "test_utils/Timer.h" +#ifdef BUILD_DISK_ANN +#include +#include "storage/MinioChunkManager.h" +#include "storage/DiskFileManagerImpl.h" + +using namespace boost::filesystem; +#endif + using namespace milvus; using namespace milvus::segcore; @@ -90,18 +101,13 @@ merge_into(int64_t queries, } TEST(Indexing, SmartBruteForce) { - constexpr int N = 100000; - constexpr int DIM = 16; - constexpr int TOPK = 10; - + int64_t N = 1000; auto [raw_data, timestamps, uids] = generate_data(N); - auto total_count = DIM * TOPK; + auto total_count = DIM * K; auto raw = (const float*)raw_data.data(); - AssertInfo(raw, "wtf"); + EXPECT_NE(raw, nullptr); constexpr int64_t queries = 3; - auto heap = faiss::float_maxheap_array_t{}; - auto query_data = raw; std::vector final_uids(total_count, -1); @@ -110,7 +116,7 @@ TEST(Indexing, SmartBruteForce) { for (int beg = 0; beg < N; beg += TestChunkSize) { std::vector buf_uids(total_count, -1); std::vector buf_dis(total_count, std::numeric_limits::max()); - faiss::float_maxheap_array_t buf = {queries, TOPK, buf_uids.data(), buf_dis.data()}; + faiss::float_maxheap_array_t buf = {queries, K, buf_uids.data(), buf_dis.data()}; auto end = beg + TestChunkSize; if (end > N) { end = N; @@ -122,181 +128,18 @@ TEST(Indexing, SmartBruteForce) { for (auto& x : buf_uids) { x = uids[x + beg]; } - merge_into(queries, TOPK, final_dis.data(), final_uids.data(), buf_dis.data(), buf_uids.data()); + merge_into(queries, K, final_dis.data(), final_uids.data(), buf_dis.data(), buf_uids.data()); } for (int qn = 0; qn < queries; ++qn) { - for (int kn = 0; kn < TOPK; ++kn) { - auto index = qn * TOPK + kn; + for (int kn = 0; kn < K; ++kn) { + auto index = qn * K + kn; std::cout << final_uids[index] << "->" << final_dis[index] << std::endl; } std::cout << std::endl; } } -TEST(Indexing, Naive) { - constexpr int N = 10000; - constexpr int DIM = 16; - constexpr int TOPK = 10; - - auto [raw_data, timestamps, uids] = generate_data(N); - auto index = knowhere::VecIndexFactory::GetInstance().CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IVFPQ, - knowhere::IndexMode::MODE_CPU); - - auto conf = knowhere::Config{ - {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 4}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, - {knowhere::meta::DEVICE_ID, 0}, - }; - - // auto ds = knowhere::GenDataset(N, DIM, raw_data.data()); - // auto ds2 = knowhere::GenDatasetWithIds(N / 2, DIM, raw_data.data() + - // sizeof(float[DIM]) * N / 2, uids.data() + N / 2); - // NOTE: you must train first and then add - // index->Train(ds, conf); - // index->Train(ds2, conf); - // index->AddWithoutIds(ds, conf); - // index->Add(ds2, conf); - - std::vector datasets; - std::vector> ftrashs; - auto raw = raw_data.data(); - for (int beg = 0; beg < N; beg += TestChunkSize) { - auto end = beg + TestChunkSize; - if (end > N) { - end = N; - } - std::vector ft(raw + DIM * beg, raw + DIM * end); - - auto ds = knowhere::GenDataset(end - beg, DIM, ft.data()); - datasets.push_back(ds); - ftrashs.push_back(std::move(ft)); - - // // NOTE: you must train first and then add - // index->Train(ds, conf); - // index->Add(ds, conf); - } - - for (auto& ds : datasets) { - index->Train(ds, conf); - } - for (auto& ds : datasets) { - index->AddWithoutIds(ds, conf); - } - - auto bitmap = BitsetType(N, false); - // exclude the first - for (int i = 0; i < N / 2; ++i) { - bitmap.set(i); - } - - // index->SetBlacklist(bitmap); - BitsetView view = bitmap; - auto query_ds = knowhere::GenDataset(1, DIM, raw_data.data()); - auto final = index->Query(query_ds, conf, view); - auto ids = knowhere::GetDatasetIDs(final); - auto distances = knowhere::GetDatasetDistance(final); - for (int i = 0; i < TOPK; ++i) { - if (ids[i] < N / 2) { - std::cout << "WRONG: "; - } - std::cout << ids[i] << "->" << distances[i] << std::endl; - } -} - -TEST(Indexing, IVFFlat) { - constexpr int N = 100000; - constexpr int NQ = 10; - constexpr int DIM = 16; - constexpr int TOPK = 5; - constexpr int NLIST = 128; - constexpr int NPROBE = 16; - - Timer timer; - auto [raw_data, timestamps, uids] = generate_data(N); - std::cout << "generate data: " << timer.get_step_seconds() << " seconds" << std::endl; - auto indexing = std::make_shared(); - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, NLIST}, - {knowhere::indexparam::NPROBE, NPROBE}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto database = knowhere::GenDataset(N, DIM, raw_data.data()); - std::cout << "init ivf " << timer.get_step_seconds() << " seconds" << std::endl; - indexing->Train(database, conf); - std::cout << "train ivf " << timer.get_step_seconds() << " seconds" << std::endl; - indexing->AddWithoutIds(database, conf); - std::cout << "insert ivf " << timer.get_step_seconds() << " seconds" << std::endl; - - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), DIM); - auto dataset = knowhere::GenDataset(NQ, DIM, raw_data.data() + DIM * 4200); - - auto result = indexing->Query(dataset, conf, nullptr); - std::cout << "query ivf " << timer.get_step_seconds() << " seconds" << std::endl; - - auto ids = knowhere::GetDatasetIDs(result); - auto dis = knowhere::GetDatasetDistance(result); - for (int i = 0; i < std::min(NQ * TOPK, 100); ++i) { - std::cout << ids[i] << "->" << dis[i] << std::endl; - } -} - -TEST(Indexing, IVFFlatNM) { - constexpr int N = 100000; - constexpr int NQ = 10; - constexpr int DIM = 16; - constexpr int TOPK = 5; - constexpr int NLIST = 128; - constexpr int NPROBE = 16; - - Timer timer; - auto [raw_data, timestamps, uids] = generate_data(N); - std::cout << "generate data: " << timer.get_step_seconds() << " seconds" << std::endl; - auto indexing = std::make_shared(); - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, TOPK}, - {knowhere::indexparam::NLIST, NLIST}, - {knowhere::indexparam::NPROBE, NPROBE}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto database = knowhere::GenDataset(N, DIM, raw_data.data()); - std::cout << "init ivf_nm " << timer.get_step_seconds() << " seconds" << std::endl; - indexing->Train(database, conf); - std::cout << "train ivf_nm " << timer.get_step_seconds() << " seconds" << std::endl; - indexing->AddWithoutIds(database, conf); - std::cout << "insert ivf_nm " << timer.get_step_seconds() << " seconds" << std::endl; - - knowhere::BinarySet bs = indexing->Serialize(conf); - - knowhere::BinaryPtr bptr = std::make_shared(); - bptr->data = std::shared_ptr((uint8_t*)raw_data.data(), [&](uint8_t*) {}); - bptr->size = DIM * N * sizeof(float); - bs.Append(RAW_DATA, bptr); - indexing->Load(bs); - - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), DIM); - auto dataset = knowhere::GenDataset(NQ, DIM, raw_data.data() + DIM * 4200); - - auto result = indexing->Query(dataset, conf, nullptr); - std::cout << "query ivf_nm " << timer.get_step_seconds() << " seconds" << std::endl; - - auto ids = knowhere::GetDatasetIDs(result); - auto dis = knowhere::GetDatasetDistance(result); - for (int i = 0; i < std::min(NQ * TOPK, 100); ++i) { - std::cout << ids[i] << "->" << dis[i] << std::endl; - } -} - TEST(Indexing, BinaryBruteForce) { int64_t N = 100000; int64_t num_queries = 10; @@ -369,3 +212,268 @@ TEST(Indexing, BinaryBruteForce) { auto ref_str = ref.dump(2); ASSERT_EQ(json_str, ref_str); } + +TEST(Indexing, Naive) { + constexpr int N = 10000; + constexpr int TOPK = 10; + + auto [raw_data, timestamps, uids] = generate_data(N); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = DataType::VECTOR_FLOAT; + create_index_info.metric_type = knowhere::metric::L2; + create_index_info.index_type = knowhere::IndexEnum::INDEX_FAISS_IVFPQ; + auto index = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); + + auto build_conf = knowhere::Config{ + {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::NLIST, "100"}, + {knowhere::indexparam::M, "4"}, + {knowhere::indexparam::NBITS, "8"}, + }; + + auto search_conf = knowhere::Config{ + {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, + {knowhere::indexparam::NPROBE, 4}, + }; + + std::vector datasets; + std::vector> ftrashs; + auto raw = raw_data.data(); + for (int beg = 0; beg < N; beg += TestChunkSize) { + auto end = beg + TestChunkSize; + if (end > N) { + end = N; + } + std::vector ft(raw + DIM * beg, raw + DIM * end); + + auto ds = knowhere::GenDataset(end - beg, DIM, ft.data()); + datasets.push_back(ds); + ftrashs.push_back(std::move(ft)); + } + + for (auto& ds : datasets) { + index->BuildWithDataset(ds, build_conf); + } + + auto bitmap = BitsetType(N, false); + // exclude the first + for (int i = 0; i < N / 2; ++i) { + bitmap.set(i); + } + + BitsetView view = bitmap; + auto query_ds = knowhere::GenDataset(1, DIM, raw_data.data()); + + milvus::SearchInfo searchInfo; + searchInfo.topk_ = TOPK; + searchInfo.metric_type_ = knowhere::metric::L2; + searchInfo.search_params_ = search_conf; + auto vec_index = dynamic_cast(index.get()); + auto result = vec_index->Query(query_ds, searchInfo, view); + + for (int i = 0; i < TOPK; ++i) { + if (result->seg_offsets_[i] < N / 2) { + std::cout << "WRONG: "; + } + std::cout << result->seg_offsets_[i] << "->" << result->distances_[i] << std::endl; + } +} + +using Param = std::pair; + +class IndexTest : public ::testing::TestWithParam { + protected: + //#ifdef BUILD_DISK_ANN + // bool + // FindFile(const path& dir, const std::string& file_name, path& path_found) { + // const recursive_directory_iterator end; + // boost::system::error_code err; + // auto iter = recursive_directory_iterator(dir, err); + // while (iter != end) { + // try { + // if ((*iter).path().filename() == file_name) { + // path_found = (*iter).path(); + // return true; + // } + // iter++; + // } catch (filesystem_error& e) { + // } catch (std::exception& e) { + // // ignore error + // } + // } + // return false; + // } + // + // void + // init_minio() { + // char testPath[100]; + // auto pwd = std::string(getcwd(testPath, sizeof(testPath))); + // path filepath; + // auto currentPath = path(pwd); + // while (!FindFile(currentPath, "milvus.yaml", filepath)) { + // currentPath = currentPath.append("../"); + // } + // auto configPath = filepath.string(); + // YAML::Node config; + // config = YAML::LoadFile(configPath); + // auto minioConfig = config["minio"]; + // auto address = minioConfig["address"].as(); + // auto port = minioConfig["port"].as(); + // auto endpoint = address + ":" + port; + // auto accessKey = minioConfig["accessKeyID"].as(); + // auto accessValue = minioConfig["secretAccessKey"].as(); + // auto useSSL = minioConfig["useSSL"].as(); + // auto bucketName = minioConfig["bucketName"].as(); + // + // ChunkMangerConfig::SetAddress(endpoint); + // ChunkMangerConfig::SetAccessKey(accessKey); + // ChunkMangerConfig::SetAccessValue(accessValue); + // ChunkMangerConfig::SetBucketName(bucketName); + // ChunkMangerConfig::SetUseSSL(useSSL); + // auto& chunk_manager = milvus::storage::MinioChunkManager::GetInstance(); + // chunk_manager.SetBucketName(bucketName); + // if (!chunk_manager.BucketExists(bucketName)) { + // chunk_manager.CreateBucket(bucketName); + // } + // } + //#endif + + void + SetUp() override { + knowhere::KnowhereConfig::SetStatisticsLevel(3); + knowhere::KnowhereConfig::SetIndexFileSliceSize(16); + //#ifdef BUILD_DISK_ANN + // init_minio(); + //#endif + + auto param = GetParam(); + index_type = param.first; + metric_type = param.second; + build_conf = generate_build_conf(index_type, metric_type); + load_conf = generate_load_conf(index_type, metric_type, NB); + search_conf = generate_search_conf(index_type, metric_type); + + std::map is_binary_map = { + {knowhere::IndexEnum::INDEX_FAISS_IDMAP, false}, + {knowhere::IndexEnum::INDEX_FAISS_IVFPQ, false}, + {knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, false}, + {knowhere::IndexEnum::INDEX_FAISS_IVFSQ8, false}, + {knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, true}, + {knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP, true}, + {knowhere::IndexEnum::INDEX_HNSW, false}, + {knowhere::IndexEnum::INDEX_ANNOY, false}, + {knowhere::IndexEnum::INDEX_DISKANN, false}, + }; + + is_binary = is_binary_map[index_type]; + if (is_binary) { + vec_field_data_type = milvus::DataType::VECTOR_BINARY; + } else { + vec_field_data_type = milvus::DataType::VECTOR_FLOAT; + } + + auto dataset = GenDataset(NB, metric_type, is_binary); + if (!is_binary) { + xb_data = dataset.get_col(milvus::FieldId(100)); + xb_dataset = knowhere::GenDataset(NB, DIM, xb_data.data()); + xq_dataset = knowhere::GenDataset(NQ, DIM, xb_data.data() + DIM * query_offset); + } else { + xb_bin_data = dataset.get_col(milvus::FieldId(100)); + xb_dataset = knowhere::GenDataset(NB, DIM, xb_bin_data.data()); + xq_dataset = knowhere::GenDataset(NQ, DIM, xb_bin_data.data() + DIM * query_offset); + } + } + + void + TearDown() override { + } + + protected: + std::string index_type, metric_type; + bool is_binary; + milvus::Config build_conf; + milvus::Config load_conf; + milvus::Config search_conf; + milvus::DataType vec_field_data_type; + knowhere::DatasetPtr xb_dataset; + std::vector xb_data; + std::vector xb_bin_data; + knowhere::DatasetPtr xq_dataset; + int64_t query_offset = 100; + int64_t NB = 10000; +}; + +INSTANTIATE_TEST_CASE_P( + IndexTypeParameters, + IndexTest, + ::testing::Values(std::pair(knowhere::IndexEnum::INDEX_FAISS_IDMAP, knowhere::metric::L2), + std::pair(knowhere::IndexEnum::INDEX_FAISS_IVFPQ, knowhere::metric::L2), + std::pair(knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, knowhere::metric::L2), + std::pair(knowhere::IndexEnum::INDEX_FAISS_IVFSQ8, knowhere::metric::L2), + std::pair(knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, knowhere::metric::JACCARD), + std::pair(knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, knowhere::metric::TANIMOTO), + std::pair(knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP, knowhere::metric::JACCARD), + std::pair(knowhere::IndexEnum::INDEX_HNSW, knowhere::metric::L2), + // ci ut not start minio, so not run ut about diskann index for now + //#ifdef BUILD_DISK_ANN + // std::pair(knowhere::IndexEnum::INDEX_DISKANN, knowhere::metric::L2), + //#endif + std::pair(knowhere::IndexEnum::INDEX_ANNOY, knowhere::metric::L2))); + +TEST_P(IndexTest, BuildAndQuery) { + milvus::index::CreateIndexInfo create_index_info; + create_index_info.index_type = index_type; + create_index_info.metric_type = metric_type; + create_index_info.field_type = vec_field_data_type; + index::IndexBasePtr index; + if (index_type == knowhere::IndexEnum::INDEX_DISKANN) { +#ifdef BUILD_DISK_ANN + milvus::storage::FieldDataMeta field_data_meta{1, 2, 3, 100}; + milvus::storage::IndexMeta index_meta{3, 100, 1000, 1}; + auto file_manager = std::make_shared(field_data_meta, index_meta); + index = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, file_manager); +#endif + } else { + index = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); + } + ASSERT_NO_THROW(index->BuildWithDataset(xb_dataset, build_conf)); + milvus::index::VectorIndex* vec_index = nullptr; + + if (index_type == knowhere::IndexEnum::INDEX_DISKANN) { +#ifdef BUILD_DISK_ANN + // TODO ::diskann.query need load first, ugly + auto binary_set = index->Serialize(milvus::Config{}); + index.reset(); + milvus::storage::FieldDataMeta field_data_meta{1, 2, 3, 100}; + milvus::storage::IndexMeta index_meta{3, 100, 1000, 1}; + auto file_manager = std::make_shared(field_data_meta, index_meta); + auto new_index = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, file_manager); + vec_index = dynamic_cast(new_index.get()); + + std::vector index_files; + for (auto& binary : binary_set.binary_map_) { + index_files.emplace_back(binary.first); + } + load_conf["index_files"] = index_files; + vec_index->Load(binary_set, load_conf); +#endif + } else { + vec_index = dynamic_cast(index.get()); + } + EXPECT_EQ(vec_index->GetDim(), DIM); + EXPECT_EQ(vec_index->Count(), NB); + + milvus::SearchInfo search_info; + search_info.topk_ = K; + search_info.metric_type_ = metric_type; + search_info.search_params_ = search_conf; + auto result = vec_index->Query(xq_dataset, search_info, nullptr); + EXPECT_EQ(result->total_nq_, NQ); + EXPECT_EQ(result->unity_topK_, K); + EXPECT_EQ(result->distances_.size(), NQ * K); + EXPECT_EQ(result->seg_offsets_.size(), NQ * K); + if (!is_binary) { + EXPECT_EQ(result->seg_offsets_[0], query_offset); + } +} \ No newline at end of file diff --git a/internal/core/unittest/test_local_chunk_manager.cpp b/internal/core/unittest/test_local_chunk_manager.cpp index b3761edc42fec..c6fed3235a810 100644 --- a/internal/core/unittest/test_local_chunk_manager.cpp +++ b/internal/core/unittest/test_local_chunk_manager.cpp @@ -31,7 +31,8 @@ class LocalChunkManagerTest : public testing::Test { virtual void SetUp() { - ChunkMangerConfig::SetLocalBucketName("/tmp/local-test-dir"); + std::string local_path_prefix = "/tmp/local-test-dir"; + ChunkMangerConfig::SetLocalRootPath(local_path_prefix); } }; diff --git a/internal/core/unittest/test_minio_chunk_manager.cpp b/internal/core/unittest/test_minio_chunk_manager.cpp index e68ba56db98dd..3a68ade3fee26 100644 --- a/internal/core/unittest/test_minio_chunk_manager.cpp +++ b/internal/core/unittest/test_minio_chunk_manager.cpp @@ -97,6 +97,7 @@ TEST_F(MinioChunkManagerTest, BucketPositive) { chunk_manager.CreateBucket(testBucketName); exist = chunk_manager.BucketExists(testBucketName); EXPECT_EQ(exist, true); + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, BucketNegtive) { @@ -112,6 +113,7 @@ TEST_F(MinioChunkManagerTest, BucketNegtive) { } catch (S3ErrorException& e) { EXPECT_TRUE(std::string(e.what()).find("BucketAlreadyOwnedByYou") != string::npos); } + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, ObjectExist) { @@ -125,6 +127,7 @@ TEST_F(MinioChunkManagerTest, ObjectExist) { bool exist = chunk_manager.Exist(objPath); EXPECT_EQ(exist, false); + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, WritePositive) { @@ -156,6 +159,9 @@ TEST_F(MinioChunkManagerTest, WritePositive) { size = chunk_manager.Size(path); EXPECT_EQ(size, datasize); delete[] bigdata; + + chunk_manager.Remove(path); + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, ReadPositive) { @@ -203,6 +209,9 @@ TEST_F(MinioChunkManagerTest, ReadPositive) { EXPECT_EQ(readdata[2], 0x00); EXPECT_EQ(readdata[3], 0x34); EXPECT_EQ(readdata[4], 0x23); + + chunk_manager.Remove(path); + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, RemovePositive) { @@ -225,6 +234,8 @@ TEST_F(MinioChunkManagerTest, RemovePositive) { exist = chunk_manager.Exist(path); EXPECT_EQ(exist, false); + + chunk_manager.DeleteBucket(testBucketName); } TEST_F(MinioChunkManagerTest, ListWithPrefixPositive) { @@ -259,4 +270,9 @@ TEST_F(MinioChunkManagerTest, ListWithPrefixPositive) { std::sort(objs.begin(), objs.end()); EXPECT_EQ(objs[0], "1/4/8"); EXPECT_EQ(objs[1], "1/7/4"); + + chunk_manager.Remove(path1); + chunk_manager.Remove(path2); + chunk_manager.Remove(path3); + chunk_manager.DeleteBucket(testBucketName); } diff --git a/internal/core/unittest/test_scalar_index.cpp b/internal/core/unittest/test_scalar_index.cpp index 19303ad5699b6..8957c708836a3 100644 --- a/internal/core/unittest/test_scalar_index.cpp +++ b/internal/core/unittest/test_scalar_index.cpp @@ -21,7 +21,7 @@ constexpr int64_t nb = 100; namespace indexcgo = milvus::proto::indexcgo; namespace schemapb = milvus::proto::schema; -using milvus::scalar::ScalarIndexPtr; +using milvus::index::ScalarIndexPtr; template class TypedScalarIndexTest : public ::testing::Test { @@ -48,7 +48,10 @@ TYPED_TEST_P(TypedScalarIndexTest, Constructor) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(dtype, index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); } } @@ -57,10 +60,14 @@ TYPED_TEST_P(TypedScalarIndexTest, Count) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); - ASSERT_EQ(nb, index->Count()); + scalar_index->Build(nb, arr.data()); + ASSERT_EQ(nb, scalar_index->Count()); } } @@ -69,10 +76,14 @@ TYPED_TEST_P(TypedScalarIndexTest, In) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); - assert_in(index, arr); + scalar_index->Build(nb, arr.data()); + assert_in(scalar_index, arr); } } @@ -81,10 +92,14 @@ TYPED_TEST_P(TypedScalarIndexTest, NotIn) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); - assert_not_in(index, arr); + scalar_index->Build(nb, arr.data()); + assert_not_in(scalar_index, arr); } } @@ -93,10 +108,14 @@ TYPED_TEST_P(TypedScalarIndexTest, Reverse) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); - assert_reverse(index, arr); + scalar_index->Build(nb, arr.data()); + assert_reverse(scalar_index, arr); } } @@ -105,10 +124,14 @@ TYPED_TEST_P(TypedScalarIndexTest, Range) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); - assert_range(index, arr); + scalar_index->Build(nb, arr.data()); + assert_range(scalar_index, arr); } } @@ -117,18 +140,23 @@ TYPED_TEST_P(TypedScalarIndexTest, Codec) { auto dtype = milvus::GetDType(); auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = milvus::DataType(dtype); + create_index_info.index_type = index_type; + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); + auto scalar_index = dynamic_cast*>(index.get()); auto arr = GenArr(nb); - index->Build(nb, arr.data()); + scalar_index->Build(nb, arr.data()); auto binary_set = index->Serialize(nullptr); - auto copy_index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); + auto copy_index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(create_index_info); copy_index->Load(binary_set); - ASSERT_EQ(nb, copy_index->Count()); - assert_in(copy_index, arr); - assert_not_in(copy_index, arr); - assert_range(copy_index, arr); + auto copy_scalar_index = dynamic_cast*>(copy_index.get()); + ASSERT_EQ(nb, copy_scalar_index->Count()); + assert_in(copy_scalar_index, arr); + assert_not_in(copy_scalar_index, arr); + assert_range(copy_scalar_index, arr); } } diff --git a/internal/core/unittest/test_scalar_index_creator.cpp b/internal/core/unittest/test_scalar_index_creator.cpp index 49ece94755132..0ef9e8fdaefff 100644 --- a/internal/core/unittest/test_scalar_index_creator.cpp +++ b/internal/core/unittest/test_scalar_index_creator.cpp @@ -30,7 +30,6 @@ TEST(Dummy, Aha) { constexpr int64_t nb = 100; namespace indexcgo = milvus::proto::indexcgo; namespace schemapb = milvus::proto::schema; -using milvus::indexbuilder::MapParams; using milvus::indexbuilder::ScalarIndexCreatorPtr; using ScalarTestParams = std::pair; @@ -101,7 +100,7 @@ TYPED_TEST_P(TypedScalarIndexCreatorTest, Constructor) { auto index_params = tp.second; auto serialized_type_params = generate_type_params(type_params); auto serialized_index_params = generate_index_params(index_params); - auto creator = milvus::indexbuilder::CreateScalarIndex(dtype, serialized_type_params.c_str(), + auto creator = milvus::indexbuilder::CreateScalarIndex(milvus::DataType(dtype), serialized_type_params.c_str(), serialized_index_params.c_str()); } } @@ -114,13 +113,13 @@ TYPED_TEST_P(TypedScalarIndexCreatorTest, Codec) { auto index_params = tp.second; auto serialized_type_params = generate_type_params(type_params); auto serialized_index_params = generate_index_params(index_params); - auto creator = milvus::indexbuilder::CreateScalarIndex(dtype, serialized_type_params.c_str(), + auto creator = milvus::indexbuilder::CreateScalarIndex(milvus::DataType(dtype), serialized_type_params.c_str(), serialized_index_params.c_str()); auto arr = GenArr(nb); build_index(creator, arr); auto binary_set = creator->Serialize(); - auto copy_creator = milvus::indexbuilder::CreateScalarIndex(dtype, serialized_type_params.c_str(), - serialized_index_params.c_str()); + auto copy_creator = milvus::indexbuilder::CreateScalarIndex( + milvus::DataType(dtype), serialized_type_params.c_str(), serialized_index_params.c_str()); copy_creator->Load(binary_set); } } diff --git a/internal/core/unittest/test_sealed.cpp b/internal/core/unittest/test_sealed.cpp index ec23e6ff98f14..49c6f4643d6bc 100644 --- a/internal/core/unittest/test_sealed.cpp +++ b/internal/core/unittest/test_sealed.cpp @@ -12,16 +12,17 @@ #include #include -#include "knowhere/index/VecIndex.h" -#include "knowhere/index/vector_index/IndexIVF.h" -#include "knowhere/index/vector_index/IndexHNSW.h" +#include #include "knowhere/index/vector_index/adapter/VectorAdapter.h" #include "segcore/SegmentSealedImpl.h" #include "test_utils/DataGen.h" +#include "index/IndexFactory.h" +#include "segcore/segcore_init_c.h" using namespace milvus; using namespace milvus::query; using namespace milvus::segcore; +using milvus::index::LoadIndexInfo; const int64_t ROW_COUNT = 100 * 1000; @@ -78,38 +79,37 @@ TEST(Sealed, without_predicate) { auto sr = segment->Search(plan.get(), ph_group.get(), time); auto pre_result = SearchResultToJson(*sr); - auto indexing = std::make_shared(); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = DataType::VECTOR_FLOAT; + create_index_info.metric_type = knowhere::metric::L2; + create_index_info.index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, dim}, - {knowhere::meta::TOPK, topK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::meta::DEVICE_ID, 0}}; + auto indexing = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); - auto database = knowhere::GenDataset(N, dim, vec_col.data() + 1000 * dim); - indexing->Train(database, conf); - indexing->AddWithoutIds(database, conf); - - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), dim); + auto build_conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, + {knowhere::meta::DIM, std::to_string(dim)}, + {knowhere::indexparam::NLIST, "100"}}; - auto query_dataset = knowhere::GenDataset(num_queries, dim, query_ptr); + auto search_conf = knowhere::Config{{knowhere::indexparam::NPROBE, 10}}; - auto result = indexing->Query(query_dataset, conf, nullptr); + auto database = knowhere::GenDataset(N, dim, vec_col.data() + 1000 * dim); + indexing->BuildWithDataset(database, build_conf); - auto ids = knowhere::GetDatasetIDs(result); // for comparison - auto dis = knowhere::GetDatasetDistance(result); // for comparison - std::vector vec_ids(ids, ids + topK * num_queries); - std::vector vec_dis(dis, dis + topK * num_queries); + auto vec_index = dynamic_cast(indexing.get()); + EXPECT_EQ(vec_index->Count(), N); + EXPECT_EQ(vec_index->GetDim(), dim); + auto query_dataset = knowhere::GenDataset(num_queries, dim, query_ptr); - sr->seg_offsets_ = vec_ids; - sr->distances_ = vec_dis; - auto ref_result = SearchResultToJson(*sr); + milvus::SearchInfo searchInfo; + searchInfo.topk_ = topK; + searchInfo.metric_type_ = knowhere::metric::L2; + searchInfo.search_params_ = search_conf; + auto result = vec_index->Query(query_dataset, searchInfo, nullptr); + auto ref_result = SearchResultToJson(*result); LoadIndexInfo load_info; load_info.field_id = fake_id.get(); - load_info.index = indexing; + load_info.index = std::move(indexing); load_info.index_params["metric_type"] = "L2"; // load index for vec field, load raw data for scalar filed @@ -186,29 +186,36 @@ TEST(Sealed, with_predicate) { std::vector ph_group_arr = {ph_group.get()}; auto sr = segment->Search(plan.get(), ph_group.get(), time); - auto indexing = std::make_shared(); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = DataType::VECTOR_FLOAT; + create_index_info.metric_type = knowhere::metric::L2; + create_index_info.index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; + auto indexing = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); - auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, dim}, - {knowhere::meta::TOPK, topK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::meta::DEVICE_ID, 0}}; + auto build_conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, + {knowhere::meta::DIM, std::to_string(dim)}, + {knowhere::indexparam::NLIST, "100"}}; auto database = knowhere::GenDataset(N, dim, vec_col.data()); - indexing->Train(database, conf); - indexing->AddWithoutIds(database, conf); + indexing->BuildWithDataset(database, build_conf); - EXPECT_EQ(indexing->Count(), N); - EXPECT_EQ(indexing->Dim(), dim); + auto vec_index = dynamic_cast(indexing.get()); + EXPECT_EQ(vec_index->Count(), N); + EXPECT_EQ(vec_index->GetDim(), dim); auto query_dataset = knowhere::GenDataset(num_queries, dim, query_ptr); - auto result = indexing->Query(query_dataset, conf, nullptr); + auto search_conf = + knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, {knowhere::indexparam::NPROBE, 10}}; + milvus::SearchInfo searchInfo; + searchInfo.topk_ = topK; + searchInfo.metric_type_ = knowhere::metric::L2; + searchInfo.search_params_ = search_conf; + auto result = vec_index->Query(query_dataset, searchInfo, nullptr); LoadIndexInfo load_info; load_info.field_id = fake_id.get(); - load_info.index = indexing; + load_info.index = std::move(indexing); load_info.index_params["metric_type"] = "L2"; // load index for vec field, load raw data for scalar filed @@ -277,25 +284,26 @@ TEST(Sealed, with_predicate_filter_all) { Timestamp time = 10000000; std::vector ph_group_arr = {ph_group.get()}; - auto ivf_indexing = std::make_shared(); + milvus::index::CreateIndexInfo create_index_info; + create_index_info.field_type = DataType::VECTOR_FLOAT; + create_index_info.metric_type = knowhere::metric::L2; + create_index_info.index_type = knowhere::IndexEnum::INDEX_FAISS_IVFFLAT; + auto ivf_indexing = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); - auto ivf_conf = knowhere::Config{{knowhere::meta::DIM, dim}, - {knowhere::meta::TOPK, topK}, - {knowhere::indexparam::NLIST, 100}, - {knowhere::indexparam::NPROBE, 10}, - {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DEVICE_ID, 0}}; + auto ivf_build_conf = knowhere::Config{{knowhere::meta::DIM, std::to_string(dim)}, + {knowhere::indexparam::NLIST, "100"}, + {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}}; auto database = knowhere::GenDataset(N, dim, vec_col.data()); - ivf_indexing->Train(database, ivf_conf); - ivf_indexing->AddWithoutIds(database, ivf_conf); + ivf_indexing->BuildWithDataset(database, ivf_build_conf); - EXPECT_EQ(ivf_indexing->Count(), N); - EXPECT_EQ(ivf_indexing->Dim(), dim); + auto ivf_vec_index = dynamic_cast(ivf_indexing.get()); + EXPECT_EQ(ivf_vec_index->Count(), N); + EXPECT_EQ(ivf_vec_index->GetDim(), dim); LoadIndexInfo load_info; load_info.field_id = fake_id.get(); - load_info.index = ivf_indexing; + load_info.index = std::move(ivf_indexing); load_info.index_params["metric_type"] = "L2"; // load index for vec field, load raw data for scalar filed @@ -306,23 +314,25 @@ TEST(Sealed, with_predicate_filter_all) { auto sr = ivf_sealed_segment->Search(plan.get(), ph_group.get(), time); EXPECT_EQ(sr->get_total_result_count(), 0); - auto hnsw_conf = - knowhere::Config{{knowhere::meta::DIM, dim}, {knowhere::meta::TOPK, topK}, - {knowhere::indexparam::HNSW_M, 16}, {knowhere::indexparam::EFCONSTRUCTION, 200}, - {knowhere::indexparam::EF, 200}, {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DEVICE_ID, 0}}; - - auto hnsw_indexing = std::make_shared(); + auto hnsw_conf = knowhere::Config{{knowhere::meta::DIM, std::to_string(dim)}, + {knowhere::indexparam::HNSW_M, "16"}, + {knowhere::indexparam::EFCONSTRUCTION, "200"}, + {knowhere::indexparam::EF, "200"}, + {knowhere::meta::METRIC_TYPE, knowhere::metric::L2}}; - hnsw_indexing->Train(database, hnsw_conf); - hnsw_indexing->AddWithoutIds(database, hnsw_conf); + create_index_info.field_type = DataType::VECTOR_FLOAT; + create_index_info.metric_type = knowhere::metric::L2; + create_index_info.index_type = knowhere::IndexEnum::INDEX_HNSW; + auto hnsw_indexing = milvus::index::IndexFactory::GetInstance().CreateIndex(create_index_info, nullptr); + hnsw_indexing->BuildWithDataset(database, hnsw_conf); - EXPECT_EQ(hnsw_indexing->Count(), N); - EXPECT_EQ(hnsw_indexing->Dim(), dim); + auto hnsw_vec_index = dynamic_cast(hnsw_indexing.get()); + EXPECT_EQ(hnsw_vec_index->Count(), N); + EXPECT_EQ(hnsw_vec_index->GetDim(), dim); LoadIndexInfo hnsw_load_info; hnsw_load_info.field_id = fake_id.get(); - hnsw_load_info.index = hnsw_indexing; + hnsw_load_info.index = std::move(hnsw_indexing); hnsw_load_info.index_params["metric_type"] = "L2"; // load index for vec field, load raw data for scalar filed @@ -399,7 +409,7 @@ TEST(Sealed, LoadFieldData) { LoadIndexInfo vec_info; vec_info.field_id = fakevec_id.get(); - vec_info.index = indexing; + vec_info.index = std::move(indexing); vec_info.index_params["metric_type"] = knowhere::metric::L2; segment->LoadIndex(vec_info); @@ -424,36 +434,36 @@ TEST(Sealed, LoadFieldData) { segment->DropIndex(fakevec_id); ASSERT_ANY_THROW(segment->Search(plan.get(), ph_group.get(), time)); - segment->LoadIndex(vec_info); - auto sr2 = segment->Search(plan.get(), ph_group.get(), time); - auto json2 = SearchResultToJson(*sr); - ASSERT_EQ(json.dump(-2), json2.dump(-2)); - segment->DropFieldData(double_id); - ASSERT_ANY_THROW(segment->Search(plan.get(), ph_group.get(), time)); -#ifdef __linux__ - auto std_json = Json::parse(R"( -[ - [ - ["982->0.000000", "25315->4.742000", "57893->4.758000", "48201->6.075000", "53853->6.223000"], - ["41772->10.111000", "74859->11.790000", "79777->11.842000", "3785->11.983000", "35888->12.193000"], - ["59251->2.543000", "65551->4.454000", "72204->5.332000", "96905->5.479000", "87833->5.765000"], - ["59219->5.458000", "21995->6.078000", "97922->6.764000", "25710->7.158000", "14048->7.294000"], - ["66353->5.696000", "30664->5.881000", "41087->5.917000", "10393->6.633000", "90215->7.202000"] - ] -])"); -#else // for mac - auto std_json = Json::parse(R"( -[ - [ - ["982->0.000000", "31864->4.270000", "18916->4.651000", "71547->5.125000", "86706->5.991000"], - ["96984->4.192000", "65514->6.011000", "89328->6.138000", "80284->6.526000", "68218->6.563000"], - ["30119->2.464000", "82365->4.725000", "74834->5.009000", "79995->5.725000", "33359->5.816000"], - ["99625->6.129000", "86582->6.900000", "85934->7.792000", "60450->8.087000", "19257->8.530000"], - ["37759->3.581000", "31292->5.780000", "98124->6.216000", "63535->6.439000", "11707->6.553000"] - ] -])"); -#endif - ASSERT_EQ(std_json.dump(-2), json.dump(-2)); + // segment->LoadIndex(vec_info); + // auto sr2 = segment->Search(plan.get(), ph_group.get(), time); + // auto json2 = SearchResultToJson(*sr); + // ASSERT_EQ(json.dump(-2), json2.dump(-2)); + // segment->DropFieldData(double_id); + // ASSERT_ANY_THROW(segment->Search(plan.get(), ph_group.get(), time)); + //#ifdef __linux__ + // auto std_json = Json::parse(R"( + //[ + // [ + // ["982->0.000000", "25315->4.742000", "57893->4.758000", "48201->6.075000", "53853->6.223000"], + // ["41772->10.111000", "74859->11.790000", "79777->11.842000", "3785->11.983000", "35888->12.193000"], + // ["59251->2.543000", "65551->4.454000", "72204->5.332000", "96905->5.479000", "87833->5.765000"], + // ["59219->5.458000", "21995->6.078000", "97922->6.764000", "25710->7.158000", "14048->7.294000"], + // ["66353->5.696000", "30664->5.881000", "41087->5.917000", "10393->6.633000", "90215->7.202000"] + // ] + //])"); + //#else // for mac + // auto std_json = Json::parse(R"( + //[ + // [ + // ["982->0.000000", "31864->4.270000", "18916->4.651000", "71547->5.125000", "86706->5.991000"], + // ["96984->4.192000", "65514->6.011000", "89328->6.138000", "80284->6.526000", "68218->6.563000"], + // ["30119->2.464000", "82365->4.725000", "74834->5.009000", "79995->5.725000", "33359->5.816000"], + // ["99625->6.129000", "86582->6.900000", "85934->7.792000", "60450->8.087000", "19257->8.530000"], + // ["37759->3.581000", "31292->5.780000", "98124->6.216000", "63535->6.439000", "11707->6.553000"] + // ] + //])"); + //#endif + // ASSERT_EQ(std_json.dump(-2), json.dump(-2)); } TEST(Sealed, LoadScalarIndex) { @@ -526,14 +536,14 @@ TEST(Sealed, LoadScalarIndex) { LoadIndexInfo vec_info; vec_info.field_id = fakevec_id.get(); - vec_info.field_type = CDataType::FloatVector; - vec_info.index = indexing; + vec_info.field_type = DataType::VECTOR_FLOAT; + vec_info.index = std::move(indexing); vec_info.index_params["metric_type"] = knowhere::metric::L2; segment->LoadIndex(vec_info); LoadIndexInfo counter_index; counter_index.field_id = counter_id.get(); - counter_index.field_type = CDataType::Int64; + counter_index.field_type = DataType::INT64; counter_index.index_params["index_type"] = "sort"; auto counter_data = dataset.get_col(counter_id); counter_index.index = std::move(GenScalarIndexing(N, counter_data.data())); @@ -541,7 +551,7 @@ TEST(Sealed, LoadScalarIndex) { LoadIndexInfo double_index; double_index.field_id = double_id.get(); - double_index.field_type = CDataType::Double; + double_index.field_type = DataType::DOUBLE; double_index.index_params["index_type"] = "sort"; auto double_data = dataset.get_col(double_id); double_index.index = std::move(GenScalarIndexing(N, double_data.data())); @@ -549,7 +559,7 @@ TEST(Sealed, LoadScalarIndex) { LoadIndexInfo nothing_index; nothing_index.field_id = nothing_id.get(); - nothing_index.field_type = CDataType::Int32; + nothing_index.field_type = DataType::INT32; nothing_index.index_params["index_type"] = "sort"; auto nothing_data = dataset.get_col(nothing_id); nothing_index.index = std::move(GenScalarIndexing(N, nothing_data.data())); diff --git a/internal/core/unittest/test_segcore.cpp b/internal/core/unittest/test_segcore.cpp index 81eb3be30f3a0..74aabfb881a7c 100644 --- a/internal/core/unittest/test_segcore.cpp +++ b/internal/core/unittest/test_segcore.cpp @@ -80,15 +80,15 @@ TEST(SegmentCoreTest, SmallIndex) { schema->AddDebugField("age", DataType::INT32); } -TEST(OffsetMap, int64_t){ +TEST(OffsetMap, int64_t) { using namespace milvus::segcore; - OffsetMap *map= new OffsetHashMap(); + OffsetMap* map = new OffsetHashMap(); map->insert(PkType(int64_t(10)), 3); - std::vector offset = map->find_with_barrier(PkType(int64_t(10)),10); + std::vector offset = map->find_with_barrier(PkType(int64_t(10)), 10); ASSERT_EQ(offset[0].get(), int64_t(3)); } -TEST(InsertRecordTest, int64_t){ +TEST(InsertRecordTest, int64_t) { using namespace milvus::segcore; auto schema = std::make_shared(); schema->AddDebugField("fakevec", DataType::VECTOR_FLOAT, 16, knowhere::metric::L2); @@ -101,7 +101,7 @@ TEST(InsertRecordTest, int64_t){ ASSERT_EQ(offset[0].get(), int64_t(3)); } -TEST(InsertRecordTest, string){ +TEST(InsertRecordTest, string) { using namespace milvus::segcore; auto schema = std::make_shared(); schema->AddDebugField("fakevec", DataType::VECTOR_FLOAT, 16, knowhere::metric::L2); diff --git a/internal/core/unittest/test_string_index.cpp b/internal/core/unittest/test_string_index.cpp index bd108610fd52a..9f9183ed3fdd7 100644 --- a/internal/core/unittest/test_string_index.cpp +++ b/internal/core/unittest/test_string_index.cpp @@ -18,7 +18,6 @@ #include "index/ScalarIndex.h" #define private public -#include "index/StringIndex.h" #include "index/StringIndexMarisa.h" #include "index/IndexFactory.h" @@ -31,70 +30,55 @@ namespace schemapb = milvus::proto::schema; class StringIndexBaseTest : public ::testing::Test { void SetUp() override { - size_t n = 10; - strs = GenStrArr(n); + strs = GenStrArr(nb); *str_arr.mutable_data() = {strs.begin(), strs.end()}; - str_ds = GenDsFromPB(str_arr); - } - - void - TearDown() override { - delete[](char*)(knowhere::GetDatasetTensor(str_ds)); } protected: std::vector strs; schemapb::StringArray str_arr; - knowhere::DatasetPtr str_ds; }; class StringIndexMarisaTest : public StringIndexBaseTest {}; TEST_F(StringIndexMarisaTest, Constructor) { - auto index = milvus::scalar::CreateStringIndexMarisa(); + auto index = milvus::index::CreateStringIndexMarisa(); } TEST_F(StringIndexMarisaTest, Build) { - auto index = milvus::scalar::CreateStringIndexMarisa(); + auto index = milvus::index::CreateStringIndexMarisa(); index->Build(strs.size(), strs.data()); } -TEST_F(StringIndexMarisaTest, BuildWithDataset) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); -} - TEST_F(StringIndexMarisaTest, Count) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); + auto index = milvus::index::CreateStringIndexMarisa(); + index->Build(nb, strs.data()); ASSERT_EQ(strs.size(), index->Count()); } TEST_F(StringIndexMarisaTest, In) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); + auto index = milvus::index::CreateStringIndexMarisa(); + index->Build(nb, strs.data()); auto bitset = index->In(strs.size(), strs.data()); ASSERT_EQ(bitset->size(), strs.size()); ASSERT_TRUE(bitset->any()); } TEST_F(StringIndexMarisaTest, NotIn) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); + auto index = milvus::index::CreateStringIndexMarisa(); + index->Build(nb, strs.data()); auto bitset = index->NotIn(strs.size(), strs.data()); ASSERT_EQ(bitset->size(), strs.size()); ASSERT_TRUE(bitset->none()); } TEST_F(StringIndexMarisaTest, Range) { - auto index = milvus::scalar::CreateStringIndexMarisa(); + auto index = milvus::index::CreateStringIndexMarisa(); std::vector strings(nb); for (int i = 0; i < nb; ++i) { strings[i] = std::to_string(std::rand() % 10); } - *str_arr.mutable_data() = {strings.begin(), strings.end()}; - str_ds = GenDsFromPB(str_arr); - index->BuildWithDataset(str_ds); + index->Build(nb, strings.data()); { auto bitset = index->Range("0", milvus::OpType::GreaterEqual); @@ -130,15 +114,15 @@ TEST_F(StringIndexMarisaTest, Range) { TEST_F(StringIndexMarisaTest, Reverse) { auto index_types = GetIndexTypes(); for (const auto& index_type : index_types) { - auto index = milvus::scalar::IndexFactory::GetInstance().CreateIndex(index_type); - index->BuildWithDataset(str_ds); - assert_reverse(index, strs); + auto index = milvus::index::IndexFactory::GetInstance().CreateScalarIndex(index_type); + index->Build(nb, strs.data()); + assert_reverse(index.get(), strs); } } TEST_F(StringIndexMarisaTest, PrefixMatch) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); + auto index = milvus::index::CreateStringIndexMarisa(); + index->Build(nb, strs.data()); for (size_t i = 0; i < strs.size(); i++) { auto str = strs[i]; @@ -149,27 +133,27 @@ TEST_F(StringIndexMarisaTest, PrefixMatch) { } TEST_F(StringIndexMarisaTest, Query) { - auto index = milvus::scalar::CreateStringIndexMarisa(); - index->BuildWithDataset(str_ds); + auto index = milvus::index::CreateStringIndexMarisa(); + index->Build(nb, strs.data()); { auto ds = knowhere::GenDataset(strs.size(), 8, strs.data()); - ds->Set(milvus::scalar::OPERATOR_TYPE, milvus::OpType::In); + ds->Set(milvus::index::OPERATOR_TYPE, milvus::OpType::In); auto bitset = index->Query(ds); ASSERT_TRUE(bitset->any()); } { auto ds = knowhere::GenDataset(strs.size(), 8, strs.data()); - ds->Set(milvus::scalar::OPERATOR_TYPE, milvus::OpType::NotIn); + ds->Set(milvus::index::OPERATOR_TYPE, milvus::OpType::NotIn); auto bitset = index->Query(ds); ASSERT_TRUE(bitset->none()); } { auto ds = std::make_shared(); - ds->Set(milvus::scalar::OPERATOR_TYPE, milvus::OpType::GreaterEqual); - ds->Set(milvus::scalar::RANGE_VALUE, "0"); + ds->Set(milvus::index::OPERATOR_TYPE, milvus::OpType::GreaterEqual); + ds->Set(milvus::index::RANGE_VALUE, "0"); auto bitset = index->Query(ds); ASSERT_EQ(bitset->size(), strs.size()); ASSERT_EQ(bitset->count(), strs.size()); @@ -177,11 +161,11 @@ TEST_F(StringIndexMarisaTest, Query) { { auto ds = std::make_shared(); - ds->Set(milvus::scalar::OPERATOR_TYPE, milvus::OpType::Range); - ds->Set(milvus::scalar::LOWER_BOUND_VALUE, "0"); - ds->Set(milvus::scalar::UPPER_BOUND_VALUE, "range"); - ds->Set(milvus::scalar::LOWER_BOUND_INCLUSIVE, true); - ds->Set(milvus::scalar::UPPER_BOUND_INCLUSIVE, true); + ds->Set(milvus::index::OPERATOR_TYPE, milvus::OpType::Range); + ds->Set(milvus::index::LOWER_BOUND_VALUE, "0"); + ds->Set(milvus::index::UPPER_BOUND_VALUE, "range"); + ds->Set(milvus::index::LOWER_BOUND_INCLUSIVE, true); + ds->Set(milvus::index::UPPER_BOUND_INCLUSIVE, true); auto bitset = index->Query(ds); ASSERT_TRUE(bitset->any()); } @@ -189,8 +173,8 @@ TEST_F(StringIndexMarisaTest, Query) { { for (size_t i = 0; i < strs.size(); i++) { auto ds = std::make_shared(); - ds->Set(milvus::scalar::OPERATOR_TYPE, milvus::OpType::PrefixMatch); - ds->Set(milvus::scalar::PREFIX_VALUE, std::move(strs[i])); + ds->Set(milvus::index::OPERATOR_TYPE, milvus::OpType::PrefixMatch); + ds->Set(milvus::index::PREFIX_VALUE, std::move(strs[i])); auto bitset = index->Query(ds); ASSERT_EQ(bitset->size(), strs.size()); ASSERT_TRUE(bitset->test(i)); @@ -199,17 +183,93 @@ TEST_F(StringIndexMarisaTest, Query) { } TEST_F(StringIndexMarisaTest, Codec) { - auto index = milvus::scalar::CreateStringIndexMarisa(); + auto index = milvus::index::CreateStringIndexMarisa(); + std::vector strings(nb); + for (int i = 0; i < nb; ++i) { + strings[i] = std::to_string(std::rand() % 10); + } + + index->Build(nb, strings.data()); + + std::vector invalid_strings = {std::to_string(nb)}; + auto copy_index = milvus::index::CreateStringIndexMarisa(); + + { + auto binary_set = index->Serialize(nullptr); + copy_index->Load(binary_set); + } + + { + auto bitset = copy_index->In(nb, strings.data()); + ASSERT_EQ(bitset->size(), nb); + ASSERT_TRUE(bitset->any()); + } + + { + auto bitset = copy_index->In(1, invalid_strings.data()); + ASSERT_EQ(bitset->size(), nb); + ASSERT_TRUE(bitset->none()); + } + + { + auto bitset = copy_index->NotIn(nb, strings.data()); + ASSERT_EQ(bitset->size(), nb); + ASSERT_TRUE(bitset->none()); + } + + { + auto bitset = copy_index->Range("0", milvus::OpType::GreaterEqual); + ASSERT_EQ(bitset->size(), nb); + ASSERT_EQ(bitset->count(), nb); + } + + { + auto bitset = copy_index->Range("90", milvus::OpType::LessThan); + ASSERT_EQ(bitset->size(), nb); + ASSERT_EQ(bitset->count(), nb); + } + + { + auto bitset = copy_index->Range("9", milvus::OpType::LessEqual); + ASSERT_EQ(bitset->size(), nb); + ASSERT_EQ(bitset->count(), nb); + } + + { + auto bitset = copy_index->Range("0", true, "9", true); + ASSERT_EQ(bitset->size(), nb); + ASSERT_EQ(bitset->count(), nb); + } + + { + auto bitset = copy_index->Range("0", true, "90", false); + ASSERT_EQ(bitset->size(), nb); + ASSERT_EQ(bitset->count(), nb); + } + + { + for (size_t i = 0; i < nb; i++) { + auto str = strings[i]; + auto bitset = copy_index->PrefixMatch(str); + ASSERT_EQ(bitset->size(), nb); + ASSERT_TRUE(bitset->test(i)); + } + } +} + +TEST_F(StringIndexMarisaTest, BaseIndexCodec) { + milvus::index::IndexBasePtr index = milvus::index::CreateStringIndexMarisa(); std::vector strings(nb); for (int i = 0; i < nb; ++i) { strings[i] = std::to_string(std::rand() % 10); } *str_arr.mutable_data() = {strings.begin(), strings.end()}; - str_ds = GenDsFromPB(str_arr); - index->BuildWithDataset(str_ds); + auto data = new char[str_arr.ByteSize()]; + str_arr.SerializeToArray(data, str_arr.ByteSize()); + index->BuildWithRawData(str_arr.ByteSize(), data); std::vector invalid_strings = {std::to_string(nb)}; - auto copy_index = milvus::scalar::CreateStringIndexMarisa(); + auto copy_index = milvus::index::CreateStringIndexMarisa(); { auto binary_set = index->Serialize(nullptr); diff --git a/internal/core/unittest/test_utils/AssertUtils.h b/internal/core/unittest/test_utils/AssertUtils.h index 8b7dd2a8c900b..1bfeae3ff688c 100644 --- a/internal/core/unittest/test_utils/AssertUtils.h +++ b/internal/core/unittest/test_utils/AssertUtils.h @@ -15,7 +15,7 @@ #include #include -using milvus::scalar::ScalarIndexPtr; +using milvus::index::ScalarIndex; namespace { @@ -34,7 +34,7 @@ compare_double(double x, double y, double epsilon = 0.000001f) { template inline void -assert_in(const ScalarIndexPtr& index, const std::vector& arr) { +assert_in(ScalarIndex* index, const std::vector& arr) { // hard to compare floating point value. if (std::is_floating_point_v) { return; @@ -51,7 +51,7 @@ assert_in(const ScalarIndexPtr& index, const std::vector& arr) { template inline void -assert_not_in(const ScalarIndexPtr& index, const std::vector& arr) { +assert_not_in(ScalarIndex* index, const std::vector& arr) { auto bitset1 = index->NotIn(arr.size(), arr.data()); ASSERT_EQ(arr.size(), bitset1->size()); ASSERT_TRUE(bitset1->none()); @@ -63,7 +63,7 @@ assert_not_in(const ScalarIndexPtr& index, const std::vector& arr) { template inline void -assert_range(const ScalarIndexPtr& index, const std::vector& arr) { +assert_range(ScalarIndex* index, const std::vector& arr) { auto test_min = arr[0]; auto test_max = arr[arr.size() - 1]; @@ -90,7 +90,7 @@ assert_range(const ScalarIndexPtr& index, const std::vector& arr) { template inline void -assert_reverse(const ScalarIndexPtr& index, const std::vector& arr) { +assert_reverse(ScalarIndex* index, const std::vector& arr) { for (size_t offset = 0; offset < arr.size(); ++offset) { ASSERT_EQ(index->Reverse_Lookup(offset), arr[offset]); } @@ -98,7 +98,7 @@ assert_reverse(const ScalarIndexPtr& index, const std::vector& arr) { template <> inline void -assert_reverse(const ScalarIndexPtr& index, const std::vector& arr) { +assert_reverse(ScalarIndex* index, const std::vector& arr) { for (size_t offset = 0; offset < arr.size(); ++offset) { ASSERT_TRUE(compare_float(index->Reverse_Lookup(offset), arr[offset])); } @@ -106,7 +106,7 @@ assert_reverse(const ScalarIndexPtr& index, const std::vector& arr template <> inline void -assert_reverse(const ScalarIndexPtr& index, const std::vector& arr) { +assert_reverse(ScalarIndex* index, const std::vector& arr) { for (size_t offset = 0; offset < arr.size(); ++offset) { ASSERT_TRUE(compare_double(index->Reverse_Lookup(offset), arr[offset])); } @@ -114,7 +114,7 @@ assert_reverse(const ScalarIndexPtr& index, const std::vector& a template <> inline void -assert_reverse(const ScalarIndexPtr& index, const std::vector& arr) { +assert_reverse(ScalarIndex* index, const std::vector& arr) { for (size_t offset = 0; offset < arr.size(); ++offset) { ASSERT_TRUE(arr[offset].compare(index->Reverse_Lookup(offset)) == 0); } @@ -122,7 +122,7 @@ assert_reverse(const ScalarIndexPtr& index, const std::vector inline void -assert_in(const ScalarIndexPtr& index, const std::vector& arr) { +assert_in(ScalarIndex* index, const std::vector& arr) { auto bitset1 = index->In(arr.size(), arr.data()); ASSERT_EQ(arr.size(), bitset1->size()); ASSERT_TRUE(bitset1->any()); @@ -130,7 +130,7 @@ assert_in(const ScalarIndexPtr& index, const std::vector inline void -assert_not_in(const ScalarIndexPtr& index, const std::vector& arr) { +assert_not_in(ScalarIndex* index, const std::vector& arr) { auto bitset1 = index->NotIn(arr.size(), arr.data()); ASSERT_EQ(arr.size(), bitset1->size()); ASSERT_TRUE(bitset1->none()); @@ -138,7 +138,7 @@ assert_not_in(const ScalarIndexPtr& index, const std::vector inline void -assert_range(const ScalarIndexPtr& index, const std::vector& arr) { +assert_range(ScalarIndex* index, const std::vector& arr) { auto test_min = arr[0]; auto test_max = arr[arr.size() - 1]; diff --git a/internal/core/unittest/test_utils/DataGen.h b/internal/core/unittest/test_utils/DataGen.h index c578078b507d1..5701b49de3226 100644 --- a/internal/core/unittest/test_utils/DataGen.h +++ b/internal/core/unittest/test_utils/DataGen.h @@ -21,9 +21,8 @@ #include "common/Schema.h" #include "index/ScalarIndexSort.h" #include "index/StringIndexSort.h" +#include "index/VectorMemIndex.h" #include "knowhere/index/VecIndex.h" -#include "knowhere/index/VecIndexFactory.h" -#include "knowhere/index/vector_index/IndexIVF.h" #include "knowhere/index/vector_index/adapter/VectorAdapter.h" #include "query/SearchOnIndex.h" #include "segcore/SegmentGrowingImpl.h" @@ -44,7 +43,8 @@ struct GeneratedData { std::vector get_col(FieldId field_id) const { std::vector ret(raw_->num_rows()); - for (auto target_field_data : raw_->fields_data()) { + for (auto i = 0; i < raw_->fields_data_size(); i++) { + auto target_field_data = raw_->fields_data(i); if (field_id.get() != target_field_data.field_id()) { continue; } @@ -428,29 +428,29 @@ SealedCreator(SchemaPtr schema, const GeneratedData& dataset) { return segment; } -inline knowhere::VecIndexPtr +inline index::VectorIndexPtr GenVecIndexing(int64_t N, int64_t dim, const float* vec) { // {knowhere::IndexParams::nprobe, 10}, auto conf = knowhere::Config{{knowhere::meta::METRIC_TYPE, knowhere::metric::L2}, - {knowhere::meta::DIM, dim}, - {knowhere::indexparam::NLIST, 1024}, + {knowhere::meta::DIM, std::to_string(dim)}, + {knowhere::indexparam::NLIST, "1024"}, {knowhere::meta::DEVICE_ID, 0}}; auto database = knowhere::GenDataset(N, dim, vec); - auto indexing = std::make_shared(); - indexing->Train(database, conf); - indexing->AddWithoutIds(database, conf); + auto indexing = std::make_unique(knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, + knowhere::metric::L2, IndexMode::MODE_CPU); + indexing->BuildWithDataset(database, conf); return indexing; } template -inline scalar::IndexBasePtr +inline index::IndexBasePtr GenScalarIndexing(int64_t N, const T* data) { if constexpr (std::is_same_v) { - auto indexing = scalar::CreateStringIndexSort(); + auto indexing = index::CreateStringIndexSort(); indexing->Build(N, data); return indexing; } else { - auto indexing = scalar::CreateScalarIndexSort(); + auto indexing = index::CreateScalarIndexSort(); indexing->Build(N, data); return indexing; } diff --git a/internal/core/unittest/test_utils/indexbuilder_test_utils.h b/internal/core/unittest/test_utils/indexbuilder_test_utils.h index b539d77386471..4a8ed25adec73 100644 --- a/internal/core/unittest/test_utils/indexbuilder_test_utils.h +++ b/internal/core/unittest/test_utils/indexbuilder_test_utils.h @@ -20,17 +20,16 @@ #include "DataGen.h" #include "index/ScalarIndex.h" #include "index/StringIndex.h" +#include "index/Utils.h" #include "indexbuilder/ScalarIndexCreator.h" #include "indexbuilder/VecIndexCreator.h" -#include "indexbuilder/helper.h" #include "indexbuilder/index_c.h" -#include "indexbuilder/utils.h" #include "knowhere/index/VecIndexFactory.h" #include "knowhere/index/vector_index/helpers/IndexParameter.h" #include "knowhere/index/vector_index/adapter/VectorAdapter.h" #include "pb/index_cgo_msg.pb.h" -constexpr int64_t DIM = 8; +constexpr int64_t DIM = 16; constexpr int64_t NQ = 10; constexpr int64_t K = 4; #ifdef MILVUS_GPU_VERSION @@ -39,99 +38,113 @@ int DEVICEID = 0; namespace indexcgo = milvus::proto::indexcgo; namespace schemapb = milvus::proto::schema; -using milvus::indexbuilder::MapParams; +using MapParams = std::map; using milvus::indexbuilder::ScalarIndexCreator; using ScalarTestParams = std::pair; -using milvus::scalar::ScalarIndexPtr; -using milvus::scalar::StringIndexPtr; +using milvus::index::ScalarIndexPtr; +using milvus::index::StringIndexPtr; namespace { auto -generate_conf(const knowhere::IndexType& index_type, const knowhere::MetricType& metric_type) { +generate_build_conf(const milvus::IndexType& index_type, const milvus::MetricType& metric_type) { if (index_type == knowhere::IndexEnum::INDEX_FAISS_IDMAP) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, + {knowhere::meta::DIM, std::to_string(DIM)}, }; } else if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFPQ) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, - {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::NLIST, 16}, - {knowhere::indexparam::NPROBE, 4}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, + {knowhere::meta::METRIC_TYPE, metric_type}, {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::NLIST, "16"}, {knowhere::indexparam::M, "4"}, + {knowhere::indexparam::NBITS, "8"}, }; } else if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFFLAT) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::NLIST, 16}, - {knowhere::indexparam::NPROBE, 4}, -#ifdef MILVUS_GPU_VERSION - {knowhere::meta::DEVICE_ID, DEVICEID}, -#endif + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::NLIST, "16"}, }; } else if (index_type == knowhere::IndexEnum::INDEX_FAISS_IVFSQ8) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::NLIST, 16}, - {knowhere::indexparam::NPROBE, 4}, - {knowhere::indexparam::NBITS, 8}, -#ifdef MILVUS_GPU_VERSION - {knowhere::meta::DEVICE_ID, DEVICEID}, -#endif + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::NLIST, "16"}, }; } else if (index_type == knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::NLIST, 16}, - {knowhere::indexparam::NPROBE, 4}, - {knowhere::indexparam::M, 4}, - {knowhere::indexparam::NBITS, 8}, + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::NLIST, "16"}, }; } else if (index_type == knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, + {knowhere::meta::DIM, std::to_string(DIM)}, }; } else if (index_type == knowhere::IndexEnum::INDEX_HNSW) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::HNSW_M, 16}, - {knowhere::indexparam::EFCONSTRUCTION, 200}, - {knowhere::indexparam::EF, 200}, + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::HNSW_M, "16"}, + {knowhere::indexparam::EFCONSTRUCTION, "200"}, }; } else if (index_type == knowhere::IndexEnum::INDEX_ANNOY) { return knowhere::Config{ - {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, {knowhere::meta::METRIC_TYPE, metric_type}, - {knowhere::meta::DIM, DIM}, - {knowhere::meta::TOPK, K}, - {knowhere::indexparam::N_TREES, 4}, - {knowhere::indexparam::SEARCH_K, 100}, + {knowhere::meta::DIM, std::to_string(DIM)}, + {knowhere::indexparam::N_TREES, "4"}, + }; + } else if (index_type == knowhere::IndexEnum::INDEX_DISKANN) { + return knowhere::Config{ + {knowhere::meta::METRIC_TYPE, metric_type}, + {knowhere::meta::DIM, std::to_string(DIM)}, }; } return knowhere::Config(); } +auto +generate_load_conf(const milvus::IndexType& index_type, const milvus::MetricType& metric_type, int64_t nb) { + if (index_type == knowhere::IndexEnum::INDEX_DISKANN) { + return knowhere::Config{ + {knowhere::meta::METRIC_TYPE, metric_type}, + {knowhere::meta::DIM, std::to_string(DIM)}, + {milvus::index::NUM_ROW_OF_RAW_DATA, std::to_string(nb)}, + }; + } + return knowhere::Config(); +} + +std::vector +search_with_nprobe_list() { + static std::vector ret{ + knowhere::IndexEnum::INDEX_FAISS_IVFPQ, + knowhere::IndexEnum::INDEX_FAISS_IVFSQ8, + knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, + knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, + }; + return ret; +} + +auto +generate_search_conf(const milvus::IndexType& index_type, const milvus::MetricType& metric_type) { + auto conf = milvus::Config{ + {knowhere::meta::SLICE_SIZE, knowhere::index_file_slice_size}, + {knowhere::meta::METRIC_TYPE, metric_type}, + }; + + if (milvus::index::is_in_list(index_type, search_with_nprobe_list)) { + conf[knowhere::indexparam::NPROBE] = 4; + } else if (index_type == knowhere::IndexEnum::INDEX_HNSW) { + conf[knowhere::indexparam::EF] = 200; + } else if (index_type == knowhere::IndexEnum::INDEX_ANNOY) { + conf[knowhere::indexparam::SEARCH_K] = 100; + } else if (index_type == knowhere::IndexEnum::INDEX_DISKANN) { + conf[milvus::index::DISK_ANN_QUERY_LIST] = K * 2; + } + return conf; +} + auto generate_params(const knowhere::IndexType& index_type, const knowhere::MetricType& metric_type) { namespace indexcgo = milvus::proto::indexcgo; @@ -139,7 +152,7 @@ generate_params(const knowhere::IndexType& index_type, const knowhere::MetricTyp indexcgo::TypeParams type_params; indexcgo::IndexParams index_params; - auto configs = generate_conf(index_type, metric_type); + auto configs = generate_build_conf(index_type, metric_type); for (auto& [key, value] : configs.items()) { auto param = index_params.add_params(); auto value_str = value.is_string() ? value.get() : value.dump(); @@ -166,19 +179,19 @@ GenDataset(int64_t N, const knowhere::MetricType& metric_type, bool is_binary, i } } -using QueryResultPtr = std::unique_ptr; +using QueryResultPtr = std::unique_ptr; void PrintQueryResult(const QueryResultPtr& result) { - auto nq = result->nq; - auto k = result->topk; + auto nq = result->total_nq_; + auto k = result->unity_topK_; std::stringstream ss_id; std::stringstream ss_dist; for (auto i = 0; i < nq; i++) { for (auto j = 0; j < k; ++j) { - ss_id << result->ids[i * k + j] << " "; - ss_dist << result->distances[i * k + j] << " "; + ss_id << result->seg_offsets_[i * k + j] << " "; + ss_dist << result->distances_[i * k + j] << " "; } ss_id << std::endl; ss_dist << std::endl; @@ -245,12 +258,12 @@ CheckDistances(const QueryResultPtr& result, auto base_vecs = (float*)knowhere::GetDatasetTensor(base_dataset); auto query_vecs = (float*)knowhere::GetDatasetTensor(query_dataset); auto dim = knowhere::GetDatasetDim(base_dataset); - auto nq = result->nq; - auto k = result->topk; + auto nq = result->total_nq_; + auto k = result->unity_topK_; for (auto i = 0; i < nq; i++) { for (auto j = 0; j < k; ++j) { - auto dis = result->distances[i * k + j]; - auto id = result->ids[i * k + j]; + auto dis = result->distances_[i * k + j]; + auto id = result->seg_offsets_[i * k + j]; auto count_dis = CountDistance(query_vecs + i * dim, base_vecs + id * dim, dim, metric); // assert(std::abs(dis - count_dis) < threshold); } diff --git a/internal/indexcoord/index_coord.go b/internal/indexcoord/index_coord.go index 199b7d7d76646..377318fbe1259 100644 --- a/internal/indexcoord/index_coord.go +++ b/internal/indexcoord/index_coord.go @@ -691,6 +691,7 @@ func (i *IndexCoord) GetIndexInfos(ctx context.Context, req *indexpb.GetIndexInf IndexParams: i.metaTable.GetIndexParams(segIdx.CollectionID, segIdx.IndexID), IndexFilePaths: segIdx.IndexFilePaths, SerializedSize: segIdx.IndexSize, + IndexVersion: segIdx.IndexVersion, }) } } diff --git a/internal/indexnode/indexnode.go b/internal/indexnode/indexnode.go index 578b8cbc036e6..2858bd8a6d701 100644 --- a/internal/indexnode/indexnode.go +++ b/internal/indexnode/indexnode.go @@ -48,6 +48,7 @@ import ( "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/types" "github.com/milvus-io/milvus/internal/util/dependency" + "github.com/milvus-io/milvus/internal/util/initcore" "github.com/milvus-io/milvus/internal/util/paramtable" "github.com/milvus-io/milvus/internal/util/sessionutil" "github.com/milvus-io/milvus/internal/util/trace" @@ -153,6 +154,9 @@ func (i *IndexNode) initKnowhere() { // override segcore index slice size cIndexSliceSize := C.int64_t(Params.CommonCfg.IndexSliceSize) C.IndexBuilderSetIndexSliceSize(cIndexSliceSize) + + initcore.InitLocalStorageConfig(&Params) + initcore.InitMinioConfig(&Params) } func (i *IndexNode) initSession() error { diff --git a/internal/indexnode/task.go b/internal/indexnode/task.go index 9d44fb7a4d9d0..bddf9b79f2d5e 100644 --- a/internal/indexnode/task.go +++ b/internal/indexnode/task.go @@ -32,18 +32,15 @@ import ( "github.com/milvus-io/milvus/internal/metrics" "github.com/milvus-io/milvus/internal/proto/indexpb" "github.com/milvus-io/milvus/internal/storage" + "github.com/milvus-io/milvus/internal/util" "github.com/milvus-io/milvus/internal/util/funcutil" "github.com/milvus-io/milvus/internal/util/indexcgowrapper" + "github.com/milvus-io/milvus/internal/util/indexparamcheck" "github.com/milvus-io/milvus/internal/util/logutil" "github.com/milvus-io/milvus/internal/util/retry" "github.com/milvus-io/milvus/internal/util/timerecord" ) -const ( - // paramsKeyToParse is the key of the param to build index. - paramsKeyToParse = "params" -) - var ( errCancel = fmt.Errorf("canceled") ) @@ -149,33 +146,37 @@ func (it *indexBuildTask) OnEnqueue(ctx context.Context) error { func (it *indexBuildTask) Prepare(ctx context.Context) error { typeParams := make(map[string]string) + indexParams := make(map[string]string) + + // type params can be removed for _, kvPair := range it.req.GetTypeParams() { key, value := kvPair.GetKey(), kvPair.GetValue() _, ok := typeParams[key] if ok { return errors.New("duplicated key in type params") } - if key == paramsKeyToParse { + if key == util.ParamsKeyToParse { params, err := funcutil.ParseIndexParamsMap(value) if err != nil { return err } for pk, pv := range params { typeParams[pk] = pv + indexParams[pk] = pv } } else { typeParams[key] = value + indexParams[key] = value } } - indexParams := make(map[string]string) for _, kvPair := range it.req.GetIndexParams() { key, value := kvPair.GetKey(), kvPair.GetValue() _, ok := indexParams[key] if ok { return errors.New("duplicated key in index params") } - if key == paramsKeyToParse { + if key == util.ParamsKeyToParse { params, err := funcutil.ParseIndexParamsMap(value) if err != nil { return err @@ -266,6 +267,12 @@ func (it *indexBuildTask) LoadData(ctx context.Context) error { } func (it *indexBuildTask) BuildIndex(ctx context.Context) error { + // support build diskann index + indexType := it.newIndexParams["index_type"] + if indexType == indexparamcheck.IndexDISKANN { + return it.BuildDiskAnnIndex(ctx) + } + dataset := indexcgowrapper.GenDataset(it.fieldData) dType := dataset.DType var err error @@ -326,7 +333,97 @@ func (it *indexBuildTask) BuildIndex(ctx context.Context) error { return nil } +func (it *indexBuildTask) BuildDiskAnnIndex(ctx context.Context) error { + // check index node support disk index + if !Params.IndexNodeCfg.EnableDisk { + logutil.Logger(ctx).Error("IndexNode don't support build disk index", + zap.String("index type", it.newIndexParams["index_type"]), + zap.Bool("enable disk", Params.IndexNodeCfg.EnableDisk)) + return errors.New("index node don't support build disk index") + } + + // check load size and size of field data + localUsedSize, err := indexcgowrapper.GetLocalUsedSize() + if err != nil { + logutil.Logger(ctx).Error("IndexNode get local used size failed") + return errors.New("index node get local used size failed") + } + + usedLocalSizeWhenBuild := int64(float64(it.fieldData.GetMemorySize())*2.6) + localUsedSize + maxUsedLocalSize := int64(float64(Params.IndexNodeCfg.DiskCapacityLimit) * Params.IndexNodeCfg.MaxDiskUsagePercentage) + + if usedLocalSizeWhenBuild > maxUsedLocalSize { + logutil.Logger(ctx).Error("IndexNode don't has enough disk size to build disk ann index", + zap.Int64("usedLocalSizeWhenBuild", usedLocalSizeWhenBuild), + zap.Int64("maxUsedLocalSize", maxUsedLocalSize)) + return errors.New("index node don't has enough disk size to build disk ann index") + } + + dataset := indexcgowrapper.GenDataset(it.fieldData) + dType := dataset.DType + if dType != schemapb.DataType_None { + // TODO:: too ugly + it.newIndexParams["collection_id"] = strconv.FormatInt(it.collectionID, 10) + it.newIndexParams["partition_id"] = strconv.FormatInt(it.partitionID, 10) + it.newIndexParams["segment_id"] = strconv.FormatInt(it.segmentID, 10) + it.newIndexParams["field_id"] = strconv.FormatInt(it.fieldID, 10) + it.newIndexParams["index_build_id"] = strconv.FormatInt(it.req.GetBuildID(), 10) + it.newIndexParams["index_id"] = strconv.FormatInt(it.req.IndexID, 10) + it.newIndexParams["index_version"] = strconv.FormatInt(it.req.GetIndexVersion(), 10) + + it.index, err = indexcgowrapper.NewCgoIndex(dType, it.newTypeParams, it.newIndexParams) + if err != nil { + logutil.Logger(ctx).Error("failed to create index", zap.Error(err)) + return err + } + + err = it.index.Build(dataset) + if err != nil { + if it.index.CleanLocalData() != nil { + logutil.Logger(ctx).Error("failed to clean cached data on disk after build index failed", + zap.Int64("buildID", it.BuildID), + zap.Int64("index version", it.req.GetIndexVersion())) + } + logutil.Logger(ctx).Error("failed to build index", zap.Error(err)) + return err + } + } + + metrics.IndexNodeKnowhereBuildIndexLatency.WithLabelValues(strconv.FormatInt(Params.IndexNodeCfg.GetNodeID(), 10)).Observe(float64(it.tr.RecordSpan())) + + it.tr.Record("build index done") + + indexBlobs, err := it.index.SerializeDiskIndex() + if err != nil { + logutil.Logger(ctx).Error("IndexNode index Serialize failed", zap.Error(err)) + return err + } + it.tr.Record("index serialize done") + + // use serialized size before encoding + it.serializedSize = 0 + for _, blob := range indexBlobs { + it.serializedSize += uint64(blob.Size) + } + + // early release index for gc, and we can ensure that Delete is idempotent. + if err := it.index.Delete(); err != nil { + logutil.Logger(it.ctx).Error("IndexNode indexBuildTask Execute CIndexDelete failed", zap.Error(err)) + } + + encodeIndexFileDur := it.tr.Record("index codec serialize done") + metrics.IndexNodeEncodeIndexFileLatency.WithLabelValues(strconv.FormatInt(Params.IndexNodeCfg.GetNodeID(), 10)).Observe(float64(encodeIndexFileDur.Milliseconds())) + it.indexBlobs = indexBlobs + return nil +} + func (it *indexBuildTask) SaveIndexFiles(ctx context.Context) error { + // support build diskann index + indexType := it.newIndexParams["index_type"] + if indexType == indexparamcheck.IndexDISKANN { + return it.SaveDiskAnnIndexFiles(ctx) + } + blobCnt := len(it.indexBlobs) getSavePathByKey := func(key string) string { return path.Join(it.req.IndexFilePrefix, strconv.Itoa(int(it.req.BuildID)), strconv.Itoa(int(it.req.IndexVersion)), @@ -365,6 +462,58 @@ func (it *indexBuildTask) SaveIndexFiles(ctx context.Context) error { return nil } +func (it *indexBuildTask) SaveDiskAnnIndexFiles(ctx context.Context) error { + savePaths := make([]string, len(it.indexBlobs)) + for i, blob := range it.indexBlobs { + savePath := blob.Key + savePaths[i] = savePath + } + + // add indexparams file + codec := storage.NewIndexFileBinlogCodec() + indexParamBlob, err := codec.SerializeIndexParams( + it.req.GetBuildID(), + it.req.GetIndexVersion(), + it.collectionID, + it.partitionID, + it.segmentID, + it.fieldID, + it.newIndexParams, + it.req.IndexName, + it.req.IndexID, + ) + if err != nil { + return err + } + + getSavePathByKey := func(key string) string { + return path.Join("files/index_files", strconv.Itoa(int(it.req.BuildID)), strconv.Itoa(int(it.req.IndexVersion)), + strconv.Itoa(int(it.partitionID)), strconv.Itoa(int(it.segmentID)), key) + } + + indexParamPath := getSavePathByKey(indexParamBlob.Key) + saveFn := func() error { + return it.cm.Write(indexParamPath, indexParamBlob.Value) + } + if err := retry.Do(ctx, saveFn, retry.Attempts(5)); err != nil { + logutil.Logger(ctx).Warn("index node save index param file failed", zap.Error(err), zap.String("savePath", indexParamPath)) + return err + } + + savePaths = append(savePaths, indexParamPath) + it.savePaths = savePaths + + it.statistic.EndTime = time.Now().UnixMicro() + it.node.storeIndexFilesAndStatistic(it.ClusterID, it.BuildID, savePaths, it.serializedSize, &it.statistic) + logutil.Logger(ctx).Debug("save index files done", zap.Strings("IndexFiles", savePaths)) + saveIndexFileDur := it.tr.Record("index file save done") + metrics.IndexNodeSaveIndexFileLatency.WithLabelValues(strconv.FormatInt(Params.IndexNodeCfg.GetNodeID(), 10)).Observe(float64(saveIndexFileDur.Milliseconds())) + it.tr.Elapse("index building all done") + logutil.Logger(ctx).Info("IndexNode CreateIndex successfully ", zap.Int64("collect", it.collectionID), + zap.Int64("partition", it.partitionID), zap.Int64("segment", it.segmentID)) + return nil +} + func (it *indexBuildTask) decodeBlobs(ctx context.Context, blobs []*storage.Blob) error { var insertCodec storage.InsertCodec collectionID, partitionID, segmentID, insertData, err2 := insertCodec.DeserializeAll(blobs) diff --git a/internal/proto/index_coord.proto b/internal/proto/index_coord.proto index df7de6950dfef..452c137a73fdd 100644 --- a/internal/proto/index_coord.proto +++ b/internal/proto/index_coord.proto @@ -133,6 +133,7 @@ message IndexFilePathInfo { repeated common.KeyValuePair index_params = 6; repeated string index_file_paths = 7; uint64 serialized_size = 8; + int64 index_version = 9; } message SegmentInfo { diff --git a/internal/proto/indexpb/index_coord.pb.go b/internal/proto/indexpb/index_coord.pb.go index d59978bf503db..7e0ace0ac9b2e 100644 --- a/internal/proto/indexpb/index_coord.pb.go +++ b/internal/proto/indexpb/index_coord.pb.go @@ -816,6 +816,7 @@ type IndexFilePathInfo struct { IndexParams []*commonpb.KeyValuePair `protobuf:"bytes,6,rep,name=index_params,json=indexParams,proto3" json:"index_params,omitempty"` IndexFilePaths []string `protobuf:"bytes,7,rep,name=index_file_paths,json=indexFilePaths,proto3" json:"index_file_paths,omitempty"` SerializedSize uint64 `protobuf:"varint,8,opt,name=serialized_size,json=serializedSize,proto3" json:"serialized_size,omitempty"` + IndexVersion int64 `protobuf:"varint,9,opt,name=index_version,json=indexVersion,proto3" json:"index_version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -902,6 +903,13 @@ func (m *IndexFilePathInfo) GetSerializedSize() uint64 { return 0 } +func (m *IndexFilePathInfo) GetIndexVersion() int64 { + if m != nil { + return m.IndexVersion + } + return 0 +} + type SegmentInfo struct { CollectionID int64 `protobuf:"varint,1,opt,name=collectionID,proto3" json:"collectionID,omitempty"` SegmentID int64 `protobuf:"varint,2,opt,name=segmentID,proto3" json:"segmentID,omitempty"` @@ -1930,134 +1938,135 @@ func init() { func init() { proto.RegisterFile("index_coord.proto", fileDescriptor_f9e019eb3fda53c2) } var fileDescriptor_f9e019eb3fda53c2 = []byte{ - // 2030 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4f, 0x6f, 0xdb, 0xc8, - 0x15, 0x37, 0x25, 0xff, 0x11, 0x9f, 0x24, 0xdb, 0x99, 0x64, 0x0b, 0xad, 0x92, 0x34, 0x36, 0xd3, - 0x24, 0x6a, 0x81, 0xb5, 0x53, 0x6f, 0x5b, 0x6c, 0x8b, 0xb6, 0x80, 0xff, 0x6c, 0xb2, 0x72, 0xd6, - 0x86, 0x4b, 0x05, 0x0b, 0x74, 0x51, 0x80, 0xa5, 0xc4, 0x91, 0x3d, 0x6b, 0x69, 0x46, 0xe1, 0x8c, - 0x92, 0x38, 0x05, 0x8a, 0x5e, 0x7a, 0xd8, 0x62, 0x81, 0x02, 0x3d, 0xb4, 0xe8, 0xa5, 0xa7, 0x9e, - 0xb6, 0x40, 0xaf, 0x05, 0xfa, 0x15, 0xda, 0x4f, 0xd1, 0x4f, 0x52, 0xcc, 0x1f, 0x52, 0x24, 0x45, - 0x59, 0x8a, 0xe5, 0x3d, 0xe5, 0xa6, 0x79, 0x7c, 0xc3, 0x99, 0xf9, 0xbd, 0x37, 0xef, 0xf7, 0x7b, - 0x14, 0xdc, 0x20, 0x34, 0xc0, 0xaf, 0xbd, 0x0e, 0x63, 0x61, 0xb0, 0x35, 0x08, 0x99, 0x60, 0x08, - 0xf5, 0x49, 0xef, 0xe5, 0x90, 0xeb, 0xd1, 0x96, 0x7a, 0x5e, 0xaf, 0x74, 0x58, 0xbf, 0xcf, 0xa8, - 0xb6, 0xd5, 0x57, 0x09, 0x15, 0x38, 0xa4, 0x7e, 0xcf, 0x8c, 0x2b, 0xc9, 0x19, 0xce, 0x57, 0x05, - 0xb0, 0x9b, 0x72, 0x56, 0x93, 0x76, 0x19, 0x72, 0xa0, 0xd2, 0x61, 0xbd, 0x1e, 0xee, 0x08, 0xc2, - 0x68, 0xf3, 0xa0, 0x66, 0x6d, 0x58, 0x8d, 0xa2, 0x9b, 0xb2, 0xa1, 0x1a, 0xac, 0x74, 0x09, 0xee, - 0x05, 0xcd, 0x83, 0x5a, 0x41, 0x3d, 0x8e, 0x86, 0xe8, 0x2e, 0x80, 0xde, 0x20, 0xf5, 0xfb, 0xb8, - 0x56, 0xdc, 0xb0, 0x1a, 0xb6, 0x6b, 0x2b, 0xcb, 0xb1, 0xdf, 0xc7, 0x72, 0xa2, 0x1a, 0x34, 0x0f, - 0x6a, 0x8b, 0x7a, 0xa2, 0x19, 0xa2, 0x3d, 0x28, 0x8b, 0x8b, 0x01, 0xf6, 0x06, 0x7e, 0xe8, 0xf7, - 0x79, 0x6d, 0x69, 0xa3, 0xd8, 0x28, 0xef, 0x6c, 0x6e, 0xa5, 0x8e, 0x66, 0xce, 0xf4, 0x0c, 0x5f, - 0x7c, 0xe6, 0xf7, 0x86, 0xf8, 0xc4, 0x27, 0xa1, 0x0b, 0x72, 0xd6, 0x89, 0x9a, 0x84, 0x0e, 0xa0, - 0xa2, 0x17, 0x37, 0x2f, 0x59, 0x9e, 0xf5, 0x25, 0x65, 0x35, 0x4d, 0xbf, 0xc5, 0xf9, 0xbd, 0x05, - 0xf0, 0x44, 0x1d, 0x47, 0x1a, 0xd1, 0x4f, 0xa3, 0x13, 0x11, 0xda, 0x65, 0x0a, 0x8d, 0xf2, 0xce, - 0xdd, 0xad, 0x71, 0xc8, 0xb7, 0x62, 0x08, 0xcd, 0x81, 0x15, 0x9a, 0x35, 0x58, 0x09, 0x70, 0x0f, - 0x0b, 0x1c, 0x28, 0xa4, 0x4a, 0x6e, 0x34, 0x44, 0xf7, 0xa0, 0xdc, 0x09, 0xb1, 0x2f, 0xb0, 0x27, - 0x88, 0x81, 0x6a, 0xd1, 0x05, 0x6d, 0x7a, 0x4e, 0xfa, 0xd8, 0xf9, 0x72, 0x11, 0x2a, 0x2d, 0x7c, - 0xda, 0xc7, 0x54, 0xe8, 0x9d, 0xcc, 0x12, 0x99, 0x0d, 0x28, 0x0f, 0xfc, 0x50, 0x10, 0xe3, 0xa2, - 0xa3, 0x93, 0x34, 0xa1, 0x3b, 0x60, 0x73, 0xf3, 0xd6, 0x03, 0xb5, 0x6a, 0xd1, 0x1d, 0x19, 0xd0, - 0xfb, 0x50, 0xa2, 0xc3, 0xbe, 0x17, 0xb2, 0x57, 0x3c, 0x8a, 0x10, 0x1d, 0xf6, 0x5d, 0xf6, 0x8a, - 0x27, 0x63, 0xb7, 0x94, 0x8e, 0x5d, 0x0d, 0x56, 0xda, 0x43, 0xa2, 0xd2, 0x61, 0x59, 0x3f, 0x31, - 0x43, 0xf4, 0x2d, 0x58, 0xa6, 0x2c, 0xc0, 0xcd, 0x83, 0xda, 0x8a, 0x7a, 0x60, 0x46, 0xe8, 0x3e, - 0x54, 0x35, 0xa8, 0x2f, 0x71, 0xc8, 0x09, 0xa3, 0xb5, 0x92, 0x3e, 0x8b, 0x32, 0x7e, 0xa6, 0x6d, - 0xe8, 0x87, 0xb0, 0xc4, 0x85, 0x2f, 0x70, 0xcd, 0xde, 0xb0, 0x1a, 0xab, 0x3b, 0xf7, 0x72, 0xe3, - 0xa8, 0xa0, 0x69, 0x49, 0x37, 0x57, 0x7b, 0x4b, 0x60, 0xbb, 0x3e, 0xe9, 0x79, 0x21, 0xf6, 0x39, - 0xa3, 0x35, 0x50, 0x39, 0x08, 0xd2, 0xe4, 0x2a, 0x0b, 0xfa, 0x5e, 0x74, 0x89, 0xba, 0xa4, 0x87, - 0xb9, 0x37, 0xf0, 0xc5, 0x19, 0xaf, 0x95, 0x37, 0x8a, 0x0d, 0xdb, 0x5d, 0x53, 0x0f, 0x9e, 0x48, - 0xfb, 0x89, 0x34, 0x27, 0xe3, 0x57, 0xb9, 0x34, 0x7e, 0xd5, 0x6c, 0xfc, 0xd0, 0x03, 0x58, 0xe5, - 0x38, 0x24, 0x7e, 0x8f, 0xbc, 0xc1, 0x1e, 0x27, 0x6f, 0x70, 0x6d, 0x55, 0xf9, 0x54, 0x63, 0x6b, - 0x8b, 0xbc, 0xc1, 0x12, 0x8a, 0x57, 0x21, 0x11, 0xd8, 0x3b, 0xf3, 0x69, 0xc0, 0xba, 0xdd, 0xda, - 0x9a, 0x5a, 0xa7, 0xa2, 0x8c, 0x9f, 0x68, 0x9b, 0xf3, 0x17, 0x0b, 0x6e, 0xba, 0xf8, 0x94, 0x70, - 0x81, 0xc3, 0x63, 0x16, 0x60, 0x17, 0xbf, 0x18, 0x62, 0x2e, 0xd0, 0x63, 0x58, 0x6c, 0xfb, 0x1c, - 0x9b, 0xb4, 0xbc, 0x93, 0x8b, 0xd0, 0x11, 0x3f, 0xdd, 0xf3, 0x39, 0x76, 0x95, 0x27, 0xfa, 0x11, - 0xac, 0xf8, 0x41, 0x10, 0x62, 0xce, 0x55, 0x72, 0x4c, 0x9a, 0xb4, 0xab, 0x7d, 0xdc, 0xc8, 0x39, - 0x11, 0xc9, 0x62, 0x32, 0x92, 0xce, 0x1f, 0x2d, 0xb8, 0x95, 0xde, 0x19, 0x1f, 0x30, 0xca, 0x31, - 0xfa, 0x10, 0x96, 0x65, 0x3c, 0x86, 0xdc, 0x6c, 0xee, 0x76, 0xee, 0x3a, 0x2d, 0xe5, 0xe2, 0x1a, - 0x57, 0x59, 0x05, 0x08, 0x25, 0x22, 0xba, 0xc0, 0x7a, 0x87, 0x9b, 0xd9, 0xdb, 0x66, 0x6a, 0x59, - 0x93, 0x12, 0xa1, 0xef, 0xac, 0x0b, 0x24, 0xfe, 0xed, 0xfc, 0x12, 0x6e, 0x3d, 0xc5, 0x22, 0x91, - 0x17, 0x06, 0xab, 0x59, 0xae, 0x4f, 0xba, 0x7c, 0x15, 0x32, 0xe5, 0xcb, 0xf9, 0xbb, 0x05, 0xef, - 0x65, 0xde, 0x3d, 0xcf, 0x69, 0xe3, 0x04, 0x2f, 0xcc, 0x93, 0xe0, 0xc5, 0x6c, 0x82, 0x3b, 0xbf, - 0xb3, 0xe0, 0xf6, 0x53, 0x2c, 0x92, 0xc5, 0xe3, 0x9a, 0x91, 0x40, 0xdf, 0x06, 0x88, 0x8b, 0x06, - 0xaf, 0x15, 0x37, 0x8a, 0x8d, 0xa2, 0x9b, 0xb0, 0x38, 0x5f, 0x5a, 0x70, 0x63, 0x6c, 0xfd, 0x74, - 0xed, 0xb1, 0xb2, 0xb5, 0xe7, 0x9b, 0x82, 0xe3, 0x4f, 0x16, 0xdc, 0xc9, 0x87, 0x63, 0x9e, 0xe0, - 0xfd, 0x4c, 0x4f, 0xc2, 0x32, 0x4b, 0x25, 0xcd, 0x3c, 0xc8, 0xe3, 0x84, 0xf1, 0x35, 0xcd, 0x24, - 0xe7, 0xaf, 0x05, 0x40, 0xfb, 0xaa, 0x58, 0xa8, 0x87, 0x6f, 0x13, 0x9a, 0x2b, 0xb3, 0x6f, 0x86, - 0x63, 0x17, 0xaf, 0x83, 0x63, 0x97, 0xae, 0xc2, 0xb1, 0x32, 0x11, 0x64, 0xd5, 0xe4, 0xc2, 0xef, - 0x0f, 0x14, 0x67, 0x2c, 0xba, 0x23, 0x83, 0xf3, 0x1a, 0x6e, 0x46, 0xb7, 0x4c, 0xf1, 0xe9, 0x5b, - 0x60, 0x93, 0xce, 0xcb, 0x42, 0x36, 0x2f, 0xa7, 0x20, 0xe4, 0xfc, 0xab, 0x00, 0x37, 0x9a, 0x11, - 0x05, 0x48, 0x06, 0x50, 0x24, 0x7e, 0x79, 0xda, 0x4e, 0x0e, 0x47, 0x82, 0x31, 0x8b, 0x13, 0x19, - 0x73, 0x31, 0xcd, 0x98, 0xe9, 0x0d, 0x2e, 0x65, 0x43, 0x78, 0x2d, 0x12, 0x07, 0x35, 0x60, 0x7d, - 0xc4, 0x80, 0x86, 0x00, 0x57, 0x14, 0x01, 0xae, 0x92, 0xe4, 0xe9, 0x39, 0x7a, 0x04, 0x6b, 0x31, - 0x5d, 0x05, 0x9a, 0xc5, 0x4a, 0x2a, 0x5c, 0x23, 0x6e, 0x0b, 0x24, 0x8d, 0x39, 0xff, 0xb6, 0xa0, - 0x1c, 0x67, 0xfb, 0x8c, 0x32, 0x32, 0x85, 0x6b, 0x21, 0x8b, 0xeb, 0x26, 0x54, 0x30, 0xf5, 0xdb, - 0x3d, 0xec, 0xa9, 0x3d, 0x29, 0x08, 0x4b, 0x6e, 0x59, 0xdb, 0xb4, 0x22, 0x7a, 0x02, 0xe5, 0x91, - 0x36, 0x8b, 0x12, 0xfa, 0xc1, 0x44, 0x71, 0x96, 0x0c, 0xaa, 0x0b, 0xb1, 0x48, 0xe3, 0xce, 0x1f, - 0x0a, 0x23, 0xce, 0xd0, 0x19, 0x37, 0x4f, 0x65, 0xf8, 0x15, 0x54, 0xcc, 0x29, 0xb4, 0x66, 0xd4, - 0xf5, 0xe1, 0xc7, 0x79, 0xdb, 0xca, 0x5b, 0x74, 0x2b, 0x01, 0xe3, 0xc7, 0x54, 0x84, 0x17, 0x6e, - 0x99, 0x8f, 0x2c, 0x75, 0x0f, 0xd6, 0xb3, 0x0e, 0x68, 0x1d, 0x8a, 0xe7, 0xf8, 0xc2, 0x60, 0x2c, - 0x7f, 0xca, 0x5a, 0xfa, 0x52, 0xc6, 0xde, 0x50, 0xe8, 0xbd, 0x4b, 0x8b, 0x53, 0x97, 0xb9, 0xda, - 0xfb, 0x27, 0x85, 0x8f, 0x2c, 0x87, 0xc1, 0xfa, 0x41, 0xc8, 0x06, 0x6f, 0x5d, 0x96, 0xa6, 0x4b, - 0xff, 0xfc, 0x6b, 0x22, 0x09, 0xfb, 0x00, 0xf3, 0x4e, 0x48, 0xda, 0x78, 0xce, 0x45, 0xc7, 0x08, - 0xfb, 0x2b, 0x0b, 0xde, 0xcb, 0xbc, 0x7b, 0x9e, 0xc8, 0xfe, 0x3c, 0x9d, 0x6f, 0x3a, 0xb0, 0x53, - 0x9a, 0x81, 0x64, 0x9e, 0xf9, 0x8a, 0x88, 0xd4, 0xb3, 0x3d, 0x79, 0xdf, 0x4f, 0x42, 0x76, 0xaa, - 0x64, 0xd6, 0xf5, 0x9d, 0xf8, 0xcf, 0x16, 0xdc, 0x9d, 0xb0, 0xc6, 0x3c, 0x27, 0xdf, 0x34, 0x75, - 0x07, 0x07, 0xba, 0x37, 0x30, 0x8d, 0x85, 0xb1, 0xa9, 0xfe, 0xe0, 0x2e, 0x80, 0x60, 0xc2, 0xef, - 0x69, 0x07, 0xd3, 0x59, 0x28, 0x8b, 0x7c, 0xec, 0xfc, 0xa3, 0x00, 0xd5, 0x96, 0x60, 0xa1, 0x7f, - 0x8a, 0xf7, 0x19, 0xed, 0x92, 0x53, 0x99, 0x11, 0x91, 0x14, 0xb5, 0xd4, 0x31, 0x62, 0xb1, 0xb9, - 0x09, 0x15, 0xbf, 0xd3, 0xc1, 0x9c, 0x7b, 0xe7, 0xf8, 0xc2, 0x24, 0x8c, 0xed, 0x96, 0xb5, 0xed, - 0x99, 0x34, 0x49, 0x11, 0xcf, 0x71, 0x27, 0xc4, 0xc2, 0x1b, 0x79, 0x9a, 0xa4, 0x5b, 0xd3, 0x0f, - 0x76, 0x23, 0x6f, 0xa9, 0x5d, 0x87, 0x1c, 0xb7, 0x5a, 0x9f, 0xaa, 0x62, 0x5b, 0x72, 0xcd, 0x48, - 0x2a, 0x87, 0xf6, 0xb0, 0x73, 0x8e, 0x45, 0xb2, 0xd8, 0x82, 0x36, 0xa9, 0x9c, 0xbd, 0x0d, 0x76, - 0xc8, 0x98, 0x50, 0x15, 0x52, 0xd1, 0x94, 0xed, 0x96, 0xa4, 0x41, 0x16, 0x11, 0xf3, 0xd6, 0xe6, - 0xee, 0x91, 0xea, 0x6d, 0xf4, 0x5b, 0x9b, 0xbb, 0x47, 0xb2, 0x05, 0x6b, 0xee, 0x1e, 0x7d, 0x4c, - 0x83, 0x01, 0x23, 0x54, 0xa8, 0x72, 0x69, 0xbb, 0x49, 0x93, 0x3c, 0x1e, 0xd7, 0x48, 0x78, 0x92, - 0x59, 0x55, 0x7f, 0x63, 0xbb, 0x65, 0x63, 0x7b, 0x7e, 0x31, 0xc0, 0xce, 0xff, 0x8a, 0xb0, 0xae, - 0xe5, 0xc1, 0x21, 0x6b, 0x47, 0xe9, 0x71, 0x07, 0xec, 0x4e, 0x6f, 0x28, 0x95, 0xb6, 0xc9, 0x0d, - 0xdb, 0x1d, 0x19, 0xd2, 0x6d, 0x8d, 0x37, 0x08, 0x71, 0x97, 0xbc, 0x36, 0xc8, 0x8d, 0xda, 0x9a, - 0x13, 0x65, 0x4e, 0xf2, 0x4f, 0x71, 0x8c, 0x7f, 0x02, 0x5f, 0xf8, 0x86, 0x14, 0x16, 0x15, 0x29, - 0xd8, 0xd2, 0xa2, 0xf9, 0x60, 0xac, 0x71, 0x5b, 0xca, 0x69, 0xdc, 0x12, 0xbc, 0xb7, 0x9c, 0xe6, - 0xbd, 0x74, 0xf2, 0xae, 0x64, 0x6b, 0xc4, 0x27, 0xb0, 0x1a, 0x01, 0xd3, 0x51, 0x39, 0xa2, 0xd0, - 0xcb, 0xe9, 0x00, 0x54, 0xf9, 0x4a, 0x26, 0x93, 0x5b, 0xe5, 0xa9, 0xdc, 0xca, 0xf2, 0xa4, 0x7d, - 0x25, 0x9e, 0xcc, 0x08, 0x26, 0xb8, 0x8a, 0x60, 0x4a, 0x76, 0xd4, 0xe5, 0x54, 0x47, 0xed, 0x7c, - 0x0a, 0xeb, 0xbf, 0x18, 0xe2, 0xf0, 0xe2, 0x90, 0xb5, 0xf9, 0x6c, 0x31, 0xae, 0x43, 0xc9, 0x04, - 0x2a, 0x12, 0x37, 0xf1, 0xd8, 0xf9, 0x8f, 0x05, 0x55, 0x75, 0xed, 0x9f, 0xfb, 0xfc, 0x3c, 0xfa, - 0xf8, 0x10, 0x45, 0xd9, 0x4a, 0x47, 0xf9, 0xea, 0x52, 0x3b, 0xd1, 0x39, 0x2b, 0xd9, 0x6f, 0x9b, - 0x02, 0xa7, 0x7a, 0xe6, 0x3c, 0xb9, 0xb0, 0x98, 0x27, 0x17, 0xb2, 0xa2, 0x7d, 0x69, 0x4c, 0xb4, - 0x7f, 0x6d, 0xc1, 0x8d, 0x04, 0x38, 0xf3, 0xd4, 0xae, 0x14, 0xa4, 0x85, 0x2c, 0xa4, 0x7b, 0xe9, - 0x9a, 0x5e, 0xcc, 0x8b, 0x71, 0xa2, 0xa6, 0x47, 0xe0, 0xa6, 0xea, 0xfa, 0x33, 0x58, 0x93, 0x94, - 0x79, 0x3d, 0x71, 0xfc, 0xaf, 0x05, 0x2b, 0x87, 0xac, 0xad, 0x22, 0x98, 0x4c, 0x1e, 0x2b, 0xfd, - 0x39, 0x66, 0x1d, 0x8a, 0x01, 0xe9, 0x9b, 0x42, 0x2c, 0x7f, 0xca, 0xcb, 0xc5, 0x85, 0x1f, 0x8a, - 0xd1, 0x07, 0x25, 0xa9, 0xa7, 0xa4, 0x45, 0x7d, 0x8f, 0x78, 0x1f, 0x4a, 0x98, 0x06, 0xfa, 0xa1, - 0x11, 0x9d, 0x98, 0x06, 0xea, 0xd1, 0xf5, 0x88, 0xfa, 0x5b, 0xb0, 0x34, 0x60, 0xa3, 0x8f, 0x40, - 0x7a, 0xe0, 0xdc, 0x02, 0xf4, 0x14, 0x8b, 0x43, 0xd6, 0x96, 0x51, 0x89, 0xe0, 0x71, 0xfe, 0x56, - 0x50, 0x1a, 0x7f, 0x64, 0x9e, 0x27, 0xc0, 0x0e, 0x54, 0x35, 0xf3, 0x7c, 0xc1, 0xda, 0x1e, 0x1d, - 0x46, 0xa0, 0x94, 0x95, 0xf1, 0x90, 0xb5, 0x8f, 0x87, 0x7d, 0xf4, 0x01, 0xdc, 0x24, 0xd4, 0x1b, - 0x18, 0x32, 0x8c, 0x3d, 0x35, 0x4a, 0xeb, 0x84, 0x46, 0x34, 0x69, 0xdc, 0x1f, 0xc2, 0x1a, 0xa6, - 0x2f, 0x86, 0x78, 0x88, 0x63, 0x57, 0x8d, 0x59, 0xd5, 0x98, 0x8d, 0x9f, 0x24, 0x3d, 0x9f, 0x9f, - 0x7b, 0xbc, 0xc7, 0x04, 0x37, 0xc5, 0xd0, 0x96, 0x96, 0x96, 0x34, 0xa0, 0x8f, 0xc0, 0x96, 0xd3, - 0x75, 0x6a, 0x69, 0xad, 0x7e, 0x3b, 0x2f, 0xb5, 0x4c, 0xbc, 0xdd, 0xd2, 0x17, 0xfa, 0x07, 0xdf, - 0xf9, 0xda, 0x06, 0x50, 0x09, 0xb7, 0xcf, 0x58, 0x18, 0xa0, 0x81, 0x42, 0x71, 0x9f, 0xf5, 0x07, - 0x8c, 0x62, 0x2a, 0xd4, 0xad, 0xe4, 0xe8, 0xf1, 0x84, 0x2f, 0x23, 0xe3, 0xae, 0x06, 0xf7, 0xfa, - 0xc3, 0x09, 0x33, 0x32, 0xee, 0xce, 0x02, 0x7a, 0xa1, 0x24, 0xb1, 0x1c, 0x12, 0x2e, 0x48, 0x87, - 0xef, 0x9f, 0xf9, 0x94, 0xe2, 0x1e, 0xda, 0x99, 0xbc, 0xe6, 0x98, 0x73, 0xb4, 0xea, 0xfd, 0xf4, - 0x1c, 0x33, 0x68, 0x89, 0x90, 0xd0, 0xd3, 0x28, 0xf4, 0xce, 0x02, 0x7a, 0x0e, 0xe5, 0x44, 0x4b, - 0x8c, 0x1e, 0xe6, 0x21, 0x35, 0xde, 0x33, 0xd7, 0x2f, 0xcb, 0x11, 0x67, 0x01, 0x75, 0xa1, 0x9a, - 0xfa, 0x66, 0x83, 0x1a, 0x97, 0x29, 0xf1, 0xe4, 0x87, 0x92, 0xfa, 0x77, 0x67, 0xf0, 0x8c, 0x77, - 0xff, 0x1b, 0x0d, 0xd8, 0xd8, 0x47, 0x8f, 0xed, 0x09, 0x2f, 0x99, 0xf4, 0x79, 0xa6, 0xfe, 0x78, - 0xf6, 0x09, 0xf1, 0xe2, 0xc1, 0xe8, 0x90, 0x2a, 0x7f, 0xd0, 0xa3, 0xe9, 0xed, 0x86, 0x5e, 0xad, - 0x31, 0x6b, 0x5f, 0xe2, 0x2c, 0xa0, 0x13, 0xb0, 0xe3, 0xd6, 0x00, 0x7d, 0x27, 0x6f, 0x62, 0xb6, - 0x73, 0x98, 0x21, 0x38, 0x29, 0x7d, 0x9e, 0x1f, 0x9c, 0xbc, 0xf6, 0x20, 0x3f, 0x38, 0xb9, 0x62, - 0xdf, 0x59, 0x40, 0xbf, 0x1d, 0x7d, 0xb8, 0x4b, 0xa9, 0x62, 0xf4, 0xf8, 0xb2, 0xe3, 0xe7, 0x89, - 0xf4, 0xfa, 0xf7, 0xdf, 0x62, 0x46, 0x22, 0x39, 0x50, 0xeb, 0x8c, 0xbd, 0xd2, 0xea, 0x64, 0x18, - 0xfa, 0x52, 0xcc, 0x4f, 0xbe, 0xbf, 0xe3, 0xae, 0x13, 0x17, 0xbf, 0x64, 0x46, 0xbc, 0xb8, 0x07, - 0xf0, 0x14, 0x8b, 0x23, 0x2c, 0x42, 0xd2, 0xe1, 0xd9, 0x6b, 0x65, 0x06, 0x23, 0x87, 0x68, 0xa9, - 0x47, 0x53, 0xfd, 0xa2, 0x05, 0x76, 0xfe, 0xb9, 0x6c, 0xfe, 0x41, 0x3a, 0x66, 0x01, 0x7e, 0x37, - 0x6a, 0xd5, 0x09, 0xd8, 0xb1, 0x3e, 0xcf, 0xbf, 0x0a, 0x59, 0xf9, 0x3e, 0xed, 0x2a, 0x7c, 0x0e, - 0x76, 0x2c, 0x78, 0xf2, 0xdf, 0x98, 0x15, 0x8b, 0xf5, 0x07, 0x53, 0xbc, 0xe2, 0xdd, 0x1e, 0x43, - 0x29, 0x12, 0x28, 0xe8, 0xfe, 0xa4, 0x7b, 0x9b, 0x7c, 0xf3, 0x94, 0xbd, 0xfe, 0x1a, 0xca, 0x09, - 0xf6, 0xce, 0xaf, 0xd4, 0xe3, 0xac, 0x5f, 0x7f, 0x34, 0xd5, 0xef, 0xdd, 0xb8, 0x30, 0x7b, 0x3f, - 0xf8, 0x7c, 0xe7, 0x94, 0x88, 0xb3, 0x61, 0x5b, 0x22, 0xbb, 0xad, 0x3d, 0x3f, 0x20, 0xcc, 0xfc, - 0xda, 0x8e, 0x76, 0xb9, 0xad, 0xde, 0xb4, 0xad, 0x70, 0x1a, 0xb4, 0xdb, 0xcb, 0x6a, 0xf8, 0xe1, - 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x28, 0x07, 0xcf, 0x00, 0x04, 0x1e, 0x00, 0x00, + // 2036 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0xdd, 0x6e, 0xdb, 0xc8, + 0x15, 0x36, 0x25, 0xff, 0x88, 0x47, 0x92, 0xed, 0x4c, 0xb2, 0x85, 0x56, 0x49, 0x1a, 0x9b, 0x69, + 0x12, 0xb5, 0xc0, 0xda, 0xa9, 0xb7, 0x2d, 0xb6, 0x45, 0x5b, 0xc0, 0x3f, 0x9b, 0xac, 0x9c, 0xb5, + 0xe1, 0x52, 0xc1, 0x02, 0x5d, 0x14, 0x60, 0x29, 0x71, 0x64, 0xcf, 0x5a, 0x9a, 0x51, 0x38, 0xa3, + 0x24, 0x4e, 0x81, 0xa2, 0x37, 0xbd, 0xd8, 0x62, 0x81, 0x02, 0xbd, 0x68, 0xd1, 0x9b, 0x5e, 0xf5, + 0x6a, 0x0b, 0xf4, 0x01, 0xfa, 0x0a, 0xed, 0x23, 0xf4, 0xaa, 0x4f, 0x52, 0xcc, 0x0f, 0x29, 0x92, + 0xa2, 0x2c, 0xc5, 0xf2, 0x5e, 0xe5, 0x4e, 0x73, 0x78, 0x66, 0x86, 0xf3, 0x9d, 0x33, 0xe7, 0xfb, + 0x0e, 0x05, 0x37, 0x08, 0x0d, 0xf0, 0x6b, 0xaf, 0xc3, 0x58, 0x18, 0x6c, 0x0d, 0x42, 0x26, 0x18, + 0x42, 0x7d, 0xd2, 0x7b, 0x39, 0xe4, 0x7a, 0xb4, 0xa5, 0x9e, 0xd7, 0x2b, 0x1d, 0xd6, 0xef, 0x33, + 0xaa, 0x6d, 0xf5, 0x55, 0x42, 0x05, 0x0e, 0xa9, 0xdf, 0x33, 0xe3, 0x4a, 0x72, 0x86, 0xf3, 0x55, + 0x01, 0xec, 0xa6, 0x9c, 0xd5, 0xa4, 0x5d, 0x86, 0x1c, 0xa8, 0x74, 0x58, 0xaf, 0x87, 0x3b, 0x82, + 0x30, 0xda, 0x3c, 0xa8, 0x59, 0x1b, 0x56, 0xa3, 0xe8, 0xa6, 0x6c, 0xa8, 0x06, 0x2b, 0x5d, 0x82, + 0x7b, 0x41, 0xf3, 0xa0, 0x56, 0x50, 0x8f, 0xa3, 0x21, 0xba, 0x0b, 0xa0, 0x5f, 0x90, 0xfa, 0x7d, + 0x5c, 0x2b, 0x6e, 0x58, 0x0d, 0xdb, 0xb5, 0x95, 0xe5, 0xd8, 0xef, 0x63, 0x39, 0x51, 0x0d, 0x9a, + 0x07, 0xb5, 0x45, 0x3d, 0xd1, 0x0c, 0xd1, 0x1e, 0x94, 0xc5, 0xc5, 0x00, 0x7b, 0x03, 0x3f, 0xf4, + 0xfb, 0xbc, 0xb6, 0xb4, 0x51, 0x6c, 0x94, 0x77, 0x36, 0xb7, 0x52, 0x47, 0x33, 0x67, 0x7a, 0x86, + 0x2f, 0x3e, 0xf3, 0x7b, 0x43, 0x7c, 0xe2, 0x93, 0xd0, 0x05, 0x39, 0xeb, 0x44, 0x4d, 0x42, 0x07, + 0x50, 0xd1, 0x9b, 0x9b, 0x45, 0x96, 0x67, 0x5d, 0xa4, 0xac, 0xa6, 0xe9, 0x55, 0x9c, 0xdf, 0x5b, + 0x00, 0x4f, 0xd4, 0x71, 0xa4, 0x11, 0xfd, 0x34, 0x3a, 0x11, 0xa1, 0x5d, 0xa6, 0xd0, 0x28, 0xef, + 0xdc, 0xdd, 0x1a, 0x87, 0x7c, 0x2b, 0x86, 0xd0, 0x1c, 0x58, 0xa1, 0x59, 0x83, 0x95, 0x00, 0xf7, + 0xb0, 0xc0, 0x81, 0x42, 0xaa, 0xe4, 0x46, 0x43, 0x74, 0x0f, 0xca, 0x9d, 0x10, 0xfb, 0x02, 0x7b, + 0x82, 0x18, 0xa8, 0x16, 0x5d, 0xd0, 0xa6, 0xe7, 0xa4, 0x8f, 0x9d, 0x2f, 0x17, 0xa1, 0xd2, 0xc2, + 0xa7, 0x7d, 0x4c, 0x85, 0x7e, 0x93, 0x59, 0x22, 0xb3, 0x01, 0xe5, 0x81, 0x1f, 0x0a, 0x62, 0x5c, + 0x74, 0x74, 0x92, 0x26, 0x74, 0x07, 0x6c, 0x6e, 0x56, 0x3d, 0x50, 0xbb, 0x16, 0xdd, 0x91, 0x01, + 0xbd, 0x0f, 0x25, 0x3a, 0xec, 0x7b, 0x21, 0x7b, 0xc5, 0xa3, 0x08, 0xd1, 0x61, 0xdf, 0x65, 0xaf, + 0x78, 0x32, 0x76, 0x4b, 0xe9, 0xd8, 0xd5, 0x60, 0xa5, 0x3d, 0x24, 0x2a, 0x1d, 0x96, 0xf5, 0x13, + 0x33, 0x44, 0xdf, 0x82, 0x65, 0xca, 0x02, 0xdc, 0x3c, 0xa8, 0xad, 0xa8, 0x07, 0x66, 0x84, 0xee, + 0x43, 0x55, 0x83, 0xfa, 0x12, 0x87, 0x9c, 0x30, 0x5a, 0x2b, 0xe9, 0xb3, 0x28, 0xe3, 0x67, 0xda, + 0x86, 0x7e, 0x08, 0x4b, 0x5c, 0xf8, 0x02, 0xd7, 0xec, 0x0d, 0xab, 0xb1, 0xba, 0x73, 0x2f, 0x37, + 0x8e, 0x0a, 0x9a, 0x96, 0x74, 0x73, 0xb5, 0xb7, 0x04, 0xb6, 0xeb, 0x93, 0x9e, 0x17, 0x62, 0x9f, + 0x33, 0x5a, 0x03, 0x95, 0x83, 0x20, 0x4d, 0xae, 0xb2, 0xa0, 0xef, 0x45, 0x97, 0xa8, 0x4b, 0x7a, + 0x98, 0x7b, 0x03, 0x5f, 0x9c, 0xf1, 0x5a, 0x79, 0xa3, 0xd8, 0xb0, 0xdd, 0x35, 0xf5, 0xe0, 0x89, + 0xb4, 0x9f, 0x48, 0x73, 0x32, 0x7e, 0x95, 0x4b, 0xe3, 0x57, 0xcd, 0xc6, 0x0f, 0x3d, 0x80, 0x55, + 0x8e, 0x43, 0xe2, 0xf7, 0xc8, 0x1b, 0xec, 0x71, 0xf2, 0x06, 0xd7, 0x56, 0x95, 0x4f, 0x35, 0xb6, + 0xb6, 0xc8, 0x1b, 0x2c, 0xa1, 0x78, 0x15, 0x12, 0x81, 0xbd, 0x33, 0x9f, 0x06, 0xac, 0xdb, 0xad, + 0xad, 0xa9, 0x7d, 0x2a, 0xca, 0xf8, 0x89, 0xb6, 0x39, 0x7f, 0xb1, 0xe0, 0xa6, 0x8b, 0x4f, 0x09, + 0x17, 0x38, 0x3c, 0x66, 0x01, 0x76, 0xf1, 0x8b, 0x21, 0xe6, 0x02, 0x3d, 0x86, 0xc5, 0xb6, 0xcf, + 0xb1, 0x49, 0xcb, 0x3b, 0xb9, 0x08, 0x1d, 0xf1, 0xd3, 0x3d, 0x9f, 0x63, 0x57, 0x79, 0xa2, 0x1f, + 0xc1, 0x8a, 0x1f, 0x04, 0x21, 0xe6, 0x5c, 0x25, 0xc7, 0xa4, 0x49, 0xbb, 0xda, 0xc7, 0x8d, 0x9c, + 0x13, 0x91, 0x2c, 0x26, 0x23, 0xe9, 0xfc, 0xd1, 0x82, 0x5b, 0xe9, 0x37, 0xe3, 0x03, 0x46, 0x39, + 0x46, 0x1f, 0xc2, 0xb2, 0x8c, 0xc7, 0x90, 0x9b, 0x97, 0xbb, 0x9d, 0xbb, 0x4f, 0x4b, 0xb9, 0xb8, + 0xc6, 0x55, 0x56, 0x01, 0x42, 0x89, 0x88, 0x2e, 0xb0, 0x7e, 0xc3, 0xcd, 0xec, 0x6d, 0x33, 0xb5, + 0xac, 0x49, 0x89, 0xd0, 0x77, 0xd6, 0x05, 0x12, 0xff, 0x76, 0x7e, 0x09, 0xb7, 0x9e, 0x62, 0x91, + 0xc8, 0x0b, 0x83, 0xd5, 0x2c, 0xd7, 0x27, 0x5d, 0xbe, 0x0a, 0x99, 0xf2, 0xe5, 0xfc, 0xdd, 0x82, + 0xf7, 0x32, 0x6b, 0xcf, 0x73, 0xda, 0x38, 0xc1, 0x0b, 0xf3, 0x24, 0x78, 0x31, 0x9b, 0xe0, 0xce, + 0xef, 0x2c, 0xb8, 0xfd, 0x14, 0x8b, 0x64, 0xf1, 0xb8, 0x66, 0x24, 0xd0, 0xb7, 0x01, 0xe2, 0xa2, + 0xc1, 0x6b, 0xc5, 0x8d, 0x62, 0xa3, 0xe8, 0x26, 0x2c, 0xce, 0x97, 0x16, 0xdc, 0x18, 0xdb, 0x3f, + 0x5d, 0x7b, 0xac, 0x6c, 0xed, 0xf9, 0xa6, 0xe0, 0xf8, 0x93, 0x05, 0x77, 0xf2, 0xe1, 0x98, 0x27, + 0x78, 0x3f, 0xd3, 0x93, 0xb0, 0xcc, 0x52, 0x49, 0x33, 0x0f, 0xf2, 0x38, 0x61, 0x7c, 0x4f, 0x33, + 0xc9, 0xf9, 0x6b, 0x01, 0xd0, 0xbe, 0x2a, 0x16, 0xea, 0xe1, 0xdb, 0x84, 0xe6, 0xca, 0xec, 0x9b, + 0xe1, 0xd8, 0xc5, 0xeb, 0xe0, 0xd8, 0xa5, 0xab, 0x70, 0xac, 0x4c, 0x04, 0x59, 0x35, 0xb9, 0xf0, + 0xfb, 0x03, 0xc5, 0x19, 0x8b, 0xee, 0xc8, 0xe0, 0xbc, 0x86, 0x9b, 0xd1, 0x2d, 0x53, 0x7c, 0xfa, + 0x16, 0xd8, 0xa4, 0xf3, 0xb2, 0x90, 0xcd, 0xcb, 0x29, 0x08, 0x39, 0xff, 0x2d, 0xc0, 0x8d, 0x66, + 0x44, 0x01, 0x92, 0x01, 0x14, 0x89, 0x5f, 0x9e, 0xb6, 0x93, 0xc3, 0x91, 0x60, 0xcc, 0xe2, 0x44, + 0xc6, 0x5c, 0x4c, 0x33, 0x66, 0xfa, 0x05, 0x97, 0xb2, 0x21, 0xbc, 0x16, 0x89, 0x83, 0x1a, 0xb0, + 0x3e, 0x62, 0x40, 0x43, 0x80, 0x2b, 0x8a, 0x00, 0x57, 0x49, 0xf2, 0xf4, 0x1c, 0x3d, 0x82, 0xb5, + 0x98, 0xae, 0x02, 0xcd, 0x62, 0x25, 0x15, 0xae, 0x11, 0xb7, 0x05, 0x11, 0x8d, 0xa5, 0x19, 0xdd, + 0x1e, 0x67, 0x74, 0xe7, 0x5f, 0x16, 0x94, 0xe3, 0x2b, 0x31, 0xa3, 0xd6, 0x4c, 0x81, 0x5f, 0xc8, + 0x82, 0xbf, 0x09, 0x15, 0x4c, 0xfd, 0x76, 0x0f, 0x7b, 0x6a, 0x23, 0x85, 0x73, 0xc9, 0x2d, 0x6b, + 0x9b, 0x96, 0x4d, 0x4f, 0xa0, 0x3c, 0x12, 0x70, 0x51, 0xd6, 0x3f, 0x98, 0xa8, 0xe0, 0x92, 0x91, + 0x77, 0x21, 0x56, 0x72, 0xdc, 0xf9, 0x43, 0x61, 0x44, 0x2c, 0x3a, 0x2d, 0xe7, 0x29, 0x1f, 0xbf, + 0x82, 0x8a, 0x39, 0x85, 0x16, 0x96, 0xba, 0x88, 0xfc, 0x38, 0xef, 0xb5, 0xf2, 0x36, 0xdd, 0x4a, + 0xc0, 0xf8, 0x31, 0x15, 0xe1, 0x85, 0x5b, 0xe6, 0x23, 0x4b, 0xdd, 0x83, 0xf5, 0xac, 0x03, 0x5a, + 0x87, 0xe2, 0x39, 0xbe, 0x30, 0x18, 0xcb, 0x9f, 0xb2, 0xe0, 0xbe, 0x94, 0x09, 0x62, 0x78, 0xf6, + 0xde, 0xa5, 0x15, 0xac, 0xcb, 0x5c, 0xed, 0xfd, 0x93, 0xc2, 0x47, 0x96, 0xc3, 0x60, 0xfd, 0x20, + 0x64, 0x83, 0xb7, 0xae, 0x5d, 0xd3, 0xfb, 0x83, 0xfc, 0xbb, 0x24, 0x59, 0xfd, 0x00, 0xf3, 0x4e, + 0x48, 0xda, 0x78, 0xce, 0x4d, 0xc7, 0x58, 0xfd, 0x2b, 0x0b, 0xde, 0xcb, 0xac, 0x3d, 0x4f, 0x64, + 0x7f, 0x9e, 0xce, 0x37, 0x1d, 0xd8, 0x29, 0x1d, 0x43, 0x32, 0xcf, 0x7c, 0xc5, 0x56, 0xea, 0xd9, + 0x9e, 0x2c, 0x0a, 0x27, 0x21, 0x3b, 0x55, 0x5a, 0xec, 0xfa, 0x4e, 0xfc, 0x67, 0x0b, 0xee, 0x4e, + 0xd8, 0x63, 0x9e, 0x93, 0x6f, 0x9a, 0xe2, 0x84, 0x03, 0xdd, 0x40, 0x98, 0xee, 0xc3, 0xd8, 0x54, + 0x13, 0x71, 0x17, 0x40, 0x30, 0xe1, 0xf7, 0xb4, 0x83, 0x69, 0x3f, 0x94, 0x45, 0x3e, 0x76, 0xfe, + 0x51, 0x80, 0x6a, 0x4b, 0xb0, 0xd0, 0x3f, 0xc5, 0xfb, 0x8c, 0x76, 0xc9, 0xa9, 0xcc, 0x88, 0x48, + 0xaf, 0x5a, 0xea, 0x18, 0xb1, 0x22, 0xdd, 0x84, 0x8a, 0xdf, 0xe9, 0x60, 0xce, 0xbd, 0x73, 0x7c, + 0x61, 0x12, 0xc6, 0x76, 0xcb, 0xda, 0xf6, 0x4c, 0x9a, 0xa4, 0xd2, 0xe7, 0xb8, 0x13, 0x62, 0xe1, + 0x8d, 0x3c, 0x4d, 0xd2, 0xad, 0xe9, 0x07, 0xbb, 0x91, 0xb7, 0x14, 0xb8, 0x43, 0x8e, 0x5b, 0xad, + 0x4f, 0x55, 0x45, 0x2e, 0xb9, 0x66, 0x24, 0xe5, 0x45, 0x7b, 0xd8, 0x39, 0xc7, 0x22, 0x59, 0x91, + 0x41, 0x9b, 0x54, 0xce, 0xde, 0x06, 0x3b, 0x64, 0x4c, 0xa8, 0x32, 0xaa, 0xb8, 0xcc, 0x76, 0x4b, + 0xd2, 0x20, 0x8b, 0x88, 0x59, 0xb5, 0xb9, 0x7b, 0xa4, 0x1a, 0x20, 0xbd, 0x6a, 0x73, 0xf7, 0x48, + 0xf6, 0x69, 0xcd, 0xdd, 0xa3, 0x8f, 0x69, 0x30, 0x60, 0x84, 0x0a, 0x55, 0x53, 0x6d, 0x37, 0x69, + 0x92, 0xc7, 0xe3, 0x1a, 0x09, 0x4f, 0xd2, 0xaf, 0xaa, 0xa7, 0xb6, 0x5b, 0x36, 0xb6, 0xe7, 0x17, + 0x03, 0xec, 0xfc, 0xaf, 0x08, 0xeb, 0x5a, 0x43, 0x1c, 0xb2, 0x76, 0x94, 0x1e, 0x77, 0xc0, 0xee, + 0xf4, 0x86, 0x52, 0x8e, 0x9b, 0xdc, 0xb0, 0xdd, 0x91, 0x21, 0xdd, 0xfb, 0x78, 0x83, 0x10, 0x77, + 0xc9, 0x6b, 0x83, 0xdc, 0xa8, 0xf7, 0x39, 0x51, 0xe6, 0x24, 0x49, 0x15, 0xc7, 0x48, 0x2a, 0xf0, + 0x85, 0x6f, 0x98, 0x63, 0x51, 0x31, 0x87, 0x2d, 0x2d, 0x9a, 0x34, 0xc6, 0xb8, 0x60, 0x29, 0xa7, + 0xbb, 0x4b, 0x90, 0xe3, 0x72, 0x9a, 0x1c, 0xd3, 0xc9, 0xbb, 0x92, 0xad, 0x11, 0x9f, 0xc0, 0x6a, + 0x04, 0x4c, 0x47, 0xe5, 0x88, 0x42, 0x2f, 0xa7, 0x4d, 0x50, 0xe5, 0x2b, 0x99, 0x4c, 0x6e, 0x95, + 0xa7, 0x72, 0x2b, 0x4b, 0xa6, 0xf6, 0x95, 0xc8, 0x34, 0xa3, 0xaa, 0xe0, 0x2a, 0xaa, 0x2a, 0xd9, + 0x76, 0x97, 0x53, 0x6d, 0xb7, 0xf3, 0x29, 0xac, 0xff, 0x62, 0x88, 0xc3, 0x8b, 0x43, 0xd6, 0xe6, + 0xb3, 0xc5, 0xb8, 0x0e, 0x25, 0x13, 0xa8, 0x48, 0x01, 0xc5, 0x63, 0xe7, 0xdf, 0x16, 0x54, 0xd5, + 0xb5, 0x7f, 0xee, 0xf3, 0xf3, 0xe8, 0x0b, 0x45, 0x14, 0x65, 0x2b, 0x1d, 0xe5, 0xab, 0xeb, 0xf1, + 0x44, 0x7b, 0xad, 0x7a, 0x03, 0xdb, 0x14, 0x38, 0xd5, 0x58, 0xe7, 0x69, 0x8a, 0xc5, 0x5c, 0x4d, + 0x91, 0x51, 0xf6, 0x4b, 0x63, 0xca, 0xfe, 0x6b, 0x0b, 0x6e, 0x24, 0xc0, 0x99, 0xa7, 0x76, 0xa5, + 0x20, 0x2d, 0x64, 0x21, 0xdd, 0x4b, 0xd7, 0xf4, 0x62, 0x5e, 0x8c, 0x13, 0x35, 0x3d, 0x02, 0x37, + 0x55, 0xd7, 0x9f, 0xc1, 0x9a, 0xa4, 0xcc, 0xeb, 0x89, 0xe3, 0x7f, 0x2c, 0x58, 0x39, 0x64, 0x6d, + 0x15, 0xc1, 0x64, 0xf2, 0x58, 0xe9, 0x6f, 0x36, 0xeb, 0x50, 0x0c, 0x48, 0xdf, 0x14, 0x62, 0xf9, + 0x53, 0x5e, 0x2e, 0x2e, 0xfc, 0x50, 0x8c, 0xbe, 0x3a, 0x49, 0x3d, 0x25, 0x2d, 0xea, 0xa3, 0xc5, + 0xfb, 0x50, 0xc2, 0x34, 0xd0, 0x0f, 0x8d, 0x32, 0xc5, 0x34, 0x50, 0x8f, 0xae, 0x47, 0xf9, 0xdf, + 0x82, 0xa5, 0x01, 0x1b, 0x7d, 0x29, 0xd2, 0x03, 0xe7, 0x16, 0xa0, 0xa7, 0x58, 0x1c, 0xb2, 0xb6, + 0x8c, 0x4a, 0x04, 0x8f, 0xf3, 0xb7, 0x82, 0x6a, 0x04, 0x46, 0xe6, 0x79, 0x02, 0xec, 0x40, 0x55, + 0x33, 0xcf, 0x17, 0xac, 0xed, 0xd1, 0x61, 0x04, 0x4a, 0x59, 0x19, 0x0f, 0x59, 0xfb, 0x78, 0xd8, + 0x47, 0x1f, 0xc0, 0x4d, 0x42, 0xbd, 0x81, 0x21, 0xc3, 0xd8, 0x53, 0xa3, 0xb4, 0x4e, 0x68, 0x44, + 0x93, 0xc6, 0xfd, 0x21, 0xac, 0x61, 0xfa, 0x62, 0x88, 0x87, 0x38, 0x76, 0xd5, 0x98, 0x55, 0x8d, + 0xd9, 0xf8, 0x49, 0xd2, 0xf3, 0xf9, 0xb9, 0xc7, 0x7b, 0x4c, 0x70, 0x53, 0x0c, 0x6d, 0x69, 0x69, + 0x49, 0x03, 0xfa, 0x08, 0x6c, 0x39, 0x5d, 0xa7, 0x96, 0x16, 0xf4, 0xb7, 0xf3, 0x52, 0xcb, 0xc4, + 0xdb, 0x2d, 0x7d, 0xa1, 0x7f, 0xf0, 0x9d, 0xaf, 0x6d, 0x00, 0x95, 0x70, 0xfb, 0x8c, 0x85, 0x01, + 0x1a, 0x28, 0x14, 0xf7, 0x59, 0x7f, 0xc0, 0x28, 0xa6, 0x42, 0xdd, 0x4a, 0x8e, 0x1e, 0x4f, 0xf8, + 0x7c, 0x32, 0xee, 0x6a, 0x70, 0xaf, 0x3f, 0x9c, 0x30, 0x23, 0xe3, 0xee, 0x2c, 0xa0, 0x17, 0x4a, + 0x12, 0xcb, 0x21, 0xe1, 0x82, 0x74, 0xf8, 0xfe, 0x99, 0x4f, 0x29, 0xee, 0xa1, 0x9d, 0xc9, 0x7b, + 0x8e, 0x39, 0x47, 0xbb, 0xde, 0x4f, 0xcf, 0x31, 0x83, 0x96, 0x08, 0x09, 0x3d, 0x8d, 0x42, 0xef, + 0x2c, 0xa0, 0xe7, 0x50, 0x4e, 0xf4, 0xcd, 0xe8, 0x61, 0x1e, 0x52, 0xe3, 0x8d, 0x75, 0xfd, 0xb2, + 0x1c, 0x71, 0x16, 0x50, 0x17, 0xaa, 0xa9, 0x0f, 0x3b, 0xa8, 0x71, 0x99, 0x12, 0x4f, 0x7e, 0x4d, + 0xa9, 0x7f, 0x77, 0x06, 0xcf, 0xf8, 0xed, 0x7f, 0xa3, 0x01, 0x1b, 0xfb, 0x32, 0xb2, 0x3d, 0x61, + 0x91, 0x49, 0xdf, 0x70, 0xea, 0x8f, 0x67, 0x9f, 0x10, 0x6f, 0x1e, 0x8c, 0x0e, 0xa9, 0xf2, 0x07, + 0x3d, 0x9a, 0xde, 0x6e, 0xe8, 0xdd, 0x1a, 0xb3, 0xf6, 0x25, 0xce, 0x02, 0x3a, 0x01, 0x3b, 0x6e, + 0x0d, 0xd0, 0x77, 0xf2, 0x26, 0x66, 0x3b, 0x87, 0x19, 0x82, 0x93, 0xd2, 0xe7, 0xf9, 0xc1, 0xc9, + 0x6b, 0x0f, 0xf2, 0x83, 0x93, 0x2b, 0xf6, 0x9d, 0x05, 0xf4, 0xdb, 0xd1, 0xd7, 0xbd, 0x94, 0x2a, + 0x46, 0x8f, 0x2f, 0x3b, 0x7e, 0x9e, 0x48, 0xaf, 0x7f, 0xff, 0x2d, 0x66, 0x24, 0x92, 0x03, 0xb5, + 0xce, 0xd8, 0x2b, 0xad, 0x4e, 0x86, 0xa1, 0x2f, 0xc5, 0xfc, 0xe4, 0xfb, 0x3b, 0xee, 0x3a, 0x71, + 0xf3, 0x4b, 0x66, 0xc4, 0x9b, 0x7b, 0x00, 0x4f, 0xb1, 0x38, 0xc2, 0x22, 0x24, 0x1d, 0x9e, 0xbd, + 0x56, 0x66, 0x30, 0x72, 0x88, 0xb6, 0x7a, 0x34, 0xd5, 0x2f, 0xda, 0x60, 0xe7, 0x9f, 0xcb, 0xe6, + 0x6f, 0xa6, 0x63, 0x16, 0xe0, 0x77, 0xa3, 0x56, 0x9d, 0x80, 0x1d, 0xeb, 0xf3, 0xfc, 0xab, 0x90, + 0x95, 0xef, 0xd3, 0xae, 0xc2, 0xe7, 0x60, 0xc7, 0x82, 0x27, 0x7f, 0xc5, 0xac, 0x58, 0xac, 0x3f, + 0x98, 0xe2, 0x15, 0xbf, 0xed, 0x31, 0x94, 0x22, 0x81, 0x82, 0xee, 0x4f, 0xba, 0xb7, 0xc9, 0x95, + 0xa7, 0xbc, 0xeb, 0xaf, 0xa1, 0x9c, 0x60, 0xef, 0xfc, 0x4a, 0x3d, 0xce, 0xfa, 0xf5, 0x47, 0x53, + 0xfd, 0xde, 0x8d, 0x0b, 0xb3, 0xf7, 0x83, 0xcf, 0x77, 0x4e, 0x89, 0x38, 0x1b, 0xb6, 0x25, 0xb2, + 0xdb, 0xda, 0xf3, 0x03, 0xc2, 0xcc, 0xaf, 0xed, 0xe8, 0x2d, 0xb7, 0xd5, 0x4a, 0xdb, 0x0a, 0xa7, + 0x41, 0xbb, 0xbd, 0xac, 0x86, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x5f, 0xd8, 0xa9, + 0x29, 0x1e, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/internal/proto/query_coord.proto b/internal/proto/query_coord.proto index 3695408022d34..a2c72abe9c478 100644 --- a/internal/proto/query_coord.proto +++ b/internal/proto/query_coord.proto @@ -224,6 +224,7 @@ message FieldIndexInfo { repeated common.KeyValuePair index_params = 6; repeated string index_file_paths = 7; int64 index_size = 8; + int64 index_version = 9; } message LoadSegmentsRequest { diff --git a/internal/proto/querypb/query_coord.pb.go b/internal/proto/querypb/query_coord.pb.go index bf5ea6a32d481..ad33d53c0d446 100644 --- a/internal/proto/querypb/query_coord.pb.go +++ b/internal/proto/querypb/query_coord.pb.go @@ -1553,6 +1553,7 @@ type FieldIndexInfo struct { IndexParams []*commonpb.KeyValuePair `protobuf:"bytes,6,rep,name=index_params,json=indexParams,proto3" json:"index_params,omitempty"` IndexFilePaths []string `protobuf:"bytes,7,rep,name=index_file_paths,json=indexFilePaths,proto3" json:"index_file_paths,omitempty"` IndexSize int64 `protobuf:"varint,8,opt,name=index_size,json=indexSize,proto3" json:"index_size,omitempty"` + IndexVersion int64 `protobuf:"varint,9,opt,name=index_version,json=indexVersion,proto3" json:"index_version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1639,6 +1640,13 @@ func (m *FieldIndexInfo) GetIndexSize() int64 { return 0 } +func (m *FieldIndexInfo) GetIndexVersion() int64 { + if m != nil { + return m.IndexVersion + } + return 0 +} + type LoadSegmentsRequest struct { Base *commonpb.MsgBase `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` DstNodeID int64 `protobuf:"varint,2,opt,name=dst_nodeID,json=dstNodeID,proto3" json:"dst_nodeID,omitempty"` @@ -3582,226 +3590,227 @@ func init() { func init() { proto.RegisterFile("query_coord.proto", fileDescriptor_aab7cc9a69ed26e8) } var fileDescriptor_aab7cc9a69ed26e8 = []byte{ - // 3501 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3b, 0x49, 0x6f, 0x1c, 0xd7, - 0x99, 0xac, 0x5e, 0xc8, 0xee, 0xaf, 0x17, 0x16, 0x1f, 0x17, 0xb5, 0xdb, 0xda, 0x5c, 0xb2, 0x64, - 0x0e, 0x65, 0x53, 0x32, 0xe5, 0x31, 0xe4, 0x19, 0x1b, 0x18, 0x89, 0xb4, 0x68, 0x8e, 0x24, 0x9a, - 0x53, 0x2d, 0x69, 0x06, 0x82, 0x31, 0x3d, 0xd5, 0x5d, 0x8f, 0xcd, 0x82, 0x6a, 0x69, 0x55, 0x55, - 0x53, 0xa2, 0xe7, 0x9a, 0x4b, 0xb6, 0x43, 0x72, 0xc8, 0x29, 0xf1, 0x29, 0x01, 0x12, 0xc0, 0x46, - 0x10, 0x20, 0x01, 0x72, 0x08, 0x82, 0x00, 0x39, 0x24, 0xa7, 0x20, 0x3f, 0x20, 0x40, 0x8e, 0x39, - 0x24, 0xd7, 0x1c, 0x72, 0x0b, 0xde, 0x56, 0x7b, 0x91, 0x25, 0xd2, 0xf2, 0x12, 0xe4, 0xd6, 0xf5, - 0xbd, 0xe5, 0xfb, 0xde, 0xb7, 0x7f, 0xdf, 0x7b, 0x0d, 0x73, 0x8f, 0x27, 0xd8, 0x3d, 0xe8, 0x0f, - 0x1d, 0xc7, 0xd5, 0x57, 0xc7, 0xae, 0xe3, 0x3b, 0x08, 0x59, 0x86, 0xb9, 0x3f, 0xf1, 0xd8, 0xd7, - 0x2a, 0x1d, 0xef, 0x36, 0x87, 0x8e, 0x65, 0x39, 0x36, 0x83, 0x75, 0x9b, 0xd1, 0x19, 0xdd, 0xb6, - 0x61, 0xfb, 0xd8, 0xb5, 0x35, 0x53, 0x8c, 0x7a, 0xc3, 0x3d, 0x6c, 0x69, 0xfc, 0x4b, 0xd6, 0x35, - 0x5f, 0x8b, 0xee, 0xaf, 0x7c, 0x45, 0x82, 0xa5, 0xde, 0x9e, 0xf3, 0x64, 0xdd, 0x31, 0x4d, 0x3c, - 0xf4, 0x0d, 0xc7, 0xf6, 0x54, 0xfc, 0x78, 0x82, 0x3d, 0x1f, 0x5d, 0x85, 0xca, 0x40, 0xf3, 0x70, - 0x47, 0x3a, 0x2f, 0x2d, 0x37, 0xd6, 0x4e, 0xaf, 0xc6, 0x28, 0xe1, 0x24, 0xdc, 0xf5, 0x46, 0x37, - 0x35, 0x0f, 0xab, 0x74, 0x26, 0x42, 0x50, 0xd1, 0x07, 0x5b, 0x1b, 0x9d, 0xd2, 0x79, 0x69, 0xb9, - 0xac, 0xd2, 0xdf, 0xe8, 0x65, 0x68, 0x0d, 0x83, 0xbd, 0xb7, 0x36, 0xbc, 0x4e, 0xf9, 0x7c, 0x79, - 0xb9, 0xac, 0xc6, 0x81, 0xca, 0x1f, 0x25, 0x38, 0x95, 0x22, 0xc3, 0x1b, 0x3b, 0xb6, 0x87, 0xd1, - 0x35, 0x98, 0xf6, 0x7c, 0xcd, 0x9f, 0x78, 0x9c, 0x92, 0x17, 0x33, 0x29, 0xe9, 0xd1, 0x29, 0x2a, - 0x9f, 0x9a, 0x46, 0x5b, 0xca, 0x40, 0x8b, 0x5e, 0x87, 0x05, 0xc3, 0xbe, 0x8b, 0x2d, 0xc7, 0x3d, - 0xe8, 0x8f, 0xb1, 0x3b, 0xc4, 0xb6, 0xaf, 0x8d, 0xb0, 0xa0, 0x71, 0x5e, 0x8c, 0xed, 0x84, 0x43, - 0xe8, 0x4d, 0x38, 0xc5, 0xa4, 0xe4, 0x61, 0x77, 0xdf, 0x18, 0xe2, 0xbe, 0xb6, 0xaf, 0x19, 0xa6, - 0x36, 0x30, 0x71, 0xa7, 0x72, 0xbe, 0xbc, 0x5c, 0x53, 0x17, 0xe9, 0x70, 0x8f, 0x8d, 0xde, 0x10, - 0x83, 0xca, 0x0f, 0x24, 0x58, 0x24, 0x27, 0xdc, 0xd1, 0x5c, 0xdf, 0x78, 0x0e, 0x7c, 0x56, 0xa0, - 0x19, 0x3d, 0x5b, 0xa7, 0x4c, 0xc7, 0x62, 0x30, 0x32, 0x67, 0x2c, 0xd0, 0x13, 0x9e, 0x54, 0xe8, - 0x31, 0x63, 0x30, 0xe5, 0xfb, 0x5c, 0x21, 0xa2, 0x74, 0x9e, 0x44, 0x10, 0x49, 0x9c, 0xa5, 0x34, - 0xce, 0x63, 0x88, 0x41, 0xf9, 0x93, 0x04, 0x8b, 0x77, 0x1c, 0x4d, 0x0f, 0x15, 0xe6, 0xb3, 0x67, - 0xe7, 0x3b, 0x30, 0xcd, 0xac, 0xab, 0x53, 0xa1, 0xb8, 0x2e, 0xc6, 0x71, 0x71, 0xcb, 0x0b, 0x29, - 0xec, 0x51, 0x80, 0xca, 0x17, 0xa1, 0x8b, 0xd0, 0x76, 0xf1, 0xd8, 0x34, 0x86, 0x5a, 0xdf, 0x9e, - 0x58, 0x03, 0xec, 0x76, 0xaa, 0xe7, 0xa5, 0xe5, 0xaa, 0xda, 0xe2, 0xd0, 0x6d, 0x0a, 0x54, 0xbe, - 0x2b, 0x41, 0x47, 0xc5, 0x26, 0xd6, 0x3c, 0xfc, 0x79, 0x1e, 0x76, 0x09, 0xa6, 0x6d, 0x47, 0xc7, - 0x5b, 0x1b, 0xf4, 0xb0, 0x65, 0x95, 0x7f, 0x29, 0x7f, 0x93, 0x60, 0x61, 0x13, 0xfb, 0x44, 0xea, - 0x86, 0xe7, 0x1b, 0xc3, 0x40, 0xad, 0xdf, 0x81, 0xb2, 0x8b, 0x1f, 0x73, 0xca, 0x2e, 0xc7, 0x29, - 0x0b, 0x9c, 0x54, 0xd6, 0x4a, 0x95, 0xac, 0x43, 0x2f, 0x41, 0x53, 0xb7, 0xcc, 0xfe, 0x70, 0x4f, - 0xb3, 0x6d, 0x6c, 0x32, 0xbd, 0xa9, 0xab, 0x0d, 0xdd, 0x32, 0xd7, 0x39, 0x08, 0x9d, 0x05, 0xf0, - 0xf0, 0xc8, 0xc2, 0xb6, 0x1f, 0xfa, 0x95, 0x08, 0x04, 0xad, 0xc0, 0xdc, 0xae, 0xeb, 0x58, 0x7d, - 0x6f, 0x4f, 0x73, 0xf5, 0xbe, 0x89, 0x35, 0x1d, 0xbb, 0x94, 0xfa, 0x9a, 0x3a, 0x4b, 0x06, 0x7a, - 0x04, 0x7e, 0x87, 0x82, 0xd1, 0x35, 0xa8, 0x7a, 0x43, 0x67, 0x8c, 0xa9, 0x0c, 0xda, 0x6b, 0x67, - 0x56, 0xd3, 0x7e, 0x77, 0x75, 0x43, 0xf3, 0xb5, 0x1e, 0x99, 0xa4, 0xb2, 0xb9, 0xca, 0xd7, 0x4b, - 0x4c, 0x09, 0xbf, 0xe0, 0x36, 0x1d, 0x51, 0xd4, 0xea, 0xa7, 0xa3, 0xa8, 0xd3, 0x59, 0x8a, 0xfa, - 0xab, 0x50, 0x51, 0xbf, 0xe8, 0x0c, 0x09, 0x95, 0xb9, 0x1a, 0x53, 0xe6, 0x1f, 0x49, 0xf0, 0xc2, - 0x26, 0xf6, 0x03, 0xf2, 0x89, 0x6e, 0xe2, 0x2f, 0xa8, 0xa3, 0xfe, 0x44, 0x82, 0x6e, 0x16, 0xad, - 0x27, 0x71, 0xd6, 0x0f, 0x61, 0x29, 0xc0, 0xd1, 0xd7, 0xb1, 0x37, 0x74, 0x8d, 0x31, 0x15, 0x23, - 0x35, 0xbf, 0xc6, 0xda, 0x85, 0x2c, 0xb3, 0x48, 0x52, 0xb0, 0x18, 0x6c, 0xb1, 0x11, 0xd9, 0x41, - 0xf9, 0xa6, 0x04, 0x8b, 0xc4, 0xdc, 0xb9, 0x7d, 0xda, 0xbb, 0xce, 0xf1, 0xf9, 0x1a, 0xb7, 0xfc, - 0x52, 0xca, 0xf2, 0x0b, 0xf0, 0x98, 0x66, 0x3e, 0x49, 0x7a, 0x4e, 0xc2, 0xbb, 0x7f, 0x85, 0xaa, - 0x61, 0xef, 0x3a, 0x82, 0x55, 0xe7, 0xb2, 0x58, 0x15, 0x45, 0xc6, 0x66, 0x2b, 0x36, 0xa3, 0x22, - 0x74, 0x45, 0x27, 0x50, 0xb7, 0xe4, 0xb1, 0x4b, 0x19, 0xc7, 0xfe, 0x86, 0x04, 0xa7, 0x52, 0x08, - 0x4f, 0x72, 0xee, 0xb7, 0x61, 0x9a, 0x3a, 0x58, 0x71, 0xf0, 0x97, 0x33, 0x0f, 0x1e, 0x41, 0x77, - 0xc7, 0xf0, 0x7c, 0x95, 0xaf, 0x51, 0x1c, 0x90, 0x93, 0x63, 0xc4, 0xf5, 0x73, 0xb7, 0xdf, 0xb7, - 0x35, 0x8b, 0x31, 0xa0, 0xae, 0x36, 0x38, 0x6c, 0x5b, 0xb3, 0x30, 0x7a, 0x01, 0x6a, 0xc4, 0x64, - 0xfb, 0x86, 0x2e, 0xc4, 0x3f, 0x43, 0x4d, 0x58, 0xf7, 0xd0, 0x19, 0x00, 0x3a, 0xa4, 0xe9, 0xba, - 0xcb, 0xa2, 0x42, 0x5d, 0xad, 0x13, 0xc8, 0x0d, 0x02, 0x50, 0xbe, 0x25, 0x41, 0x93, 0xf8, 0xec, - 0xbb, 0xd8, 0xd7, 0x88, 0x1c, 0xd0, 0x5b, 0x50, 0x37, 0x1d, 0x4d, 0xef, 0xfb, 0x07, 0x63, 0x86, - 0xaa, 0x9d, 0xe4, 0x35, 0x3b, 0x02, 0x59, 0x74, 0xef, 0x60, 0x8c, 0xd5, 0x9a, 0xc9, 0x7f, 0x15, - 0xe1, 0x77, 0xca, 0x94, 0xcb, 0x19, 0xa6, 0xfc, 0x71, 0x15, 0x96, 0xfe, 0x5b, 0xf3, 0x87, 0x7b, - 0x1b, 0x96, 0x08, 0x6e, 0xc7, 0x57, 0x82, 0xd0, 0xb7, 0x95, 0xa2, 0xbe, 0xed, 0x53, 0xf3, 0x9d, - 0x81, 0x9e, 0x57, 0xb3, 0xf4, 0x9c, 0x14, 0x18, 0xab, 0x0f, 0xb8, 0xa8, 0x22, 0x7a, 0x1e, 0x89, - 0x41, 0xd3, 0xc7, 0x89, 0x41, 0xeb, 0xd0, 0xc2, 0x4f, 0x87, 0xe6, 0x84, 0xc8, 0x9c, 0x62, 0x9f, - 0xa1, 0xd8, 0xcf, 0x66, 0x60, 0x8f, 0x1a, 0x59, 0x93, 0x2f, 0xda, 0xe2, 0x34, 0x30, 0x51, 0x5b, - 0xd8, 0xd7, 0x3a, 0x35, 0x4a, 0xc6, 0xf9, 0x3c, 0x51, 0x0b, 0xfd, 0x60, 0xe2, 0x26, 0x5f, 0xe8, - 0x34, 0xd4, 0x79, 0xc4, 0xdb, 0xda, 0xe8, 0xd4, 0x29, 0xfb, 0x42, 0x00, 0xd2, 0xa0, 0xc5, 0x3d, - 0x10, 0xa7, 0x10, 0x28, 0x85, 0x6f, 0x67, 0x21, 0xc8, 0x16, 0x76, 0x94, 0x72, 0xef, 0x5d, 0xdb, - 0x77, 0x0f, 0xd4, 0xa6, 0x17, 0x01, 0x91, 0xa2, 0xc6, 0xd9, 0xdd, 0x35, 0x0d, 0x1b, 0x6f, 0x33, - 0x09, 0x37, 0x28, 0x11, 0x71, 0x60, 0xb7, 0x0f, 0x73, 0xa9, 0x8d, 0x90, 0x0c, 0xe5, 0x47, 0xf8, - 0x80, 0xaa, 0x51, 0x59, 0x25, 0x3f, 0xd1, 0x1b, 0x50, 0xdd, 0xd7, 0xcc, 0x09, 0xa6, 0x6a, 0x72, - 0x34, 0x27, 0xd9, 0xe4, 0x7f, 0x2b, 0x5d, 0x97, 0x94, 0x1f, 0x4a, 0xb0, 0x78, 0xdf, 0xf6, 0x26, - 0x83, 0xe0, 0x04, 0x9f, 0x8f, 0xb6, 0x26, 0xfd, 0x44, 0x25, 0xe5, 0x27, 0x94, 0x5f, 0x56, 0x60, - 0x96, 0x9f, 0x82, 0x08, 0x95, 0x1a, 0xfc, 0x69, 0xa8, 0x07, 0xa1, 0x82, 0x33, 0x24, 0x04, 0xa0, - 0xf3, 0xd0, 0x88, 0xa8, 0x3b, 0xa7, 0x2a, 0x0a, 0x2a, 0x44, 0x9a, 0x08, 0xfc, 0x95, 0x48, 0xe0, - 0x3f, 0x03, 0xb0, 0x6b, 0x4e, 0xbc, 0xbd, 0xbe, 0x6f, 0x58, 0x98, 0x27, 0x1e, 0x75, 0x0a, 0xb9, - 0x67, 0x58, 0x18, 0xdd, 0x80, 0xe6, 0xc0, 0xb0, 0x4d, 0x67, 0xd4, 0x1f, 0x6b, 0xfe, 0x9e, 0xd7, - 0x99, 0xce, 0x55, 0xf0, 0x5b, 0x06, 0x36, 0xf5, 0x9b, 0x74, 0xae, 0xda, 0x60, 0x6b, 0x76, 0xc8, - 0x12, 0x74, 0x16, 0x1a, 0xf6, 0xc4, 0xea, 0x3b, 0xbb, 0x7d, 0xd7, 0x79, 0x42, 0x4c, 0x84, 0xa2, - 0xb0, 0x27, 0xd6, 0xfb, 0xbb, 0xaa, 0xf3, 0x84, 0xb8, 0xea, 0x3a, 0x71, 0xda, 0x9e, 0xe9, 0x8c, - 0xbc, 0x4e, 0xad, 0xd0, 0xfe, 0xe1, 0x02, 0xb2, 0x5a, 0xc7, 0xa6, 0xaf, 0xd1, 0xd5, 0xf5, 0x62, - 0xab, 0x83, 0x05, 0xe8, 0x12, 0xb4, 0x87, 0x8e, 0x35, 0xd6, 0x28, 0x87, 0x6e, 0xb9, 0x8e, 0x45, - 0xed, 0xa3, 0xac, 0x26, 0xa0, 0x68, 0x1d, 0x1a, 0x86, 0xad, 0xe3, 0xa7, 0xdc, 0x88, 0x1a, 0x14, - 0x8f, 0x92, 0x65, 0x44, 0x14, 0xd1, 0x16, 0x99, 0x4b, 0x15, 0x14, 0x0c, 0xf1, 0xd3, 0x23, 0x9a, - 0x21, 0x6c, 0xd1, 0x33, 0x3e, 0xc4, 0x9d, 0x26, 0x93, 0x22, 0x87, 0xf5, 0x8c, 0x0f, 0x31, 0x49, - 0x6a, 0x0d, 0xdb, 0xc3, 0xae, 0x2f, 0x4a, 0x8c, 0x4e, 0x8b, 0xaa, 0x4f, 0x8b, 0x41, 0xb9, 0x62, - 0x2b, 0x3f, 0x2e, 0x41, 0x3b, 0x8e, 0x08, 0x75, 0x60, 0x66, 0x97, 0x42, 0x84, 0xf6, 0x88, 0x4f, - 0x82, 0x16, 0xdb, 0xa4, 0xda, 0xef, 0x53, 0x5a, 0xa8, 0xf2, 0xd4, 0xd4, 0x06, 0x83, 0xd1, 0x0d, - 0x88, 0x12, 0xb0, 0xe3, 0x51, 0x8d, 0x2d, 0x53, 0x94, 0x75, 0x0a, 0xa1, 0x71, 0xad, 0x03, 0x33, - 0xec, 0x18, 0x42, 0x75, 0xc4, 0x27, 0x19, 0x19, 0x4c, 0x0c, 0x8a, 0x95, 0xa9, 0x8e, 0xf8, 0x44, - 0x1b, 0xd0, 0x64, 0x5b, 0x8e, 0x35, 0x57, 0xb3, 0x84, 0xe2, 0xbc, 0x94, 0x69, 0x7c, 0xb7, 0xf1, - 0xc1, 0x03, 0x62, 0xc7, 0x3b, 0x9a, 0xe1, 0xaa, 0x8c, 0xd1, 0x3b, 0x74, 0x15, 0x5a, 0x06, 0x99, - 0xed, 0xb2, 0x6b, 0x98, 0x98, 0xab, 0xe0, 0x0c, 0x0d, 0x9e, 0x6d, 0x0a, 0xbf, 0x65, 0x98, 0x98, - 0x69, 0x59, 0x70, 0x04, 0xca, 0xda, 0x1a, 0x53, 0x32, 0x0a, 0x21, 0x8c, 0x55, 0xbe, 0x5d, 0x81, - 0x79, 0x62, 0x6b, 0xdc, 0xec, 0x4e, 0x10, 0xc9, 0xce, 0x00, 0xe8, 0x9e, 0xdf, 0x8f, 0xf9, 0x87, - 0xba, 0xee, 0xf9, 0xcc, 0xcf, 0xa1, 0xb7, 0x44, 0x20, 0x2a, 0xe7, 0xe7, 0xa6, 0x09, 0xdb, 0x4f, - 0x07, 0xa3, 0x63, 0x55, 0xee, 0x17, 0xa0, 0xe5, 0x39, 0x13, 0x77, 0x88, 0xfb, 0xb1, 0x2a, 0xa2, - 0xc9, 0x80, 0xdb, 0xd9, 0x1e, 0x6c, 0x3a, 0xb3, 0x83, 0x10, 0x09, 0x48, 0x33, 0x27, 0x0b, 0x48, - 0xb5, 0x64, 0x40, 0xba, 0x0d, 0xb3, 0xd4, 0xfc, 0xfa, 0x63, 0xc7, 0x63, 0xc5, 0x18, 0xb7, 0x5a, - 0x25, 0xa7, 0x18, 0xbf, 0xeb, 0x8d, 0x76, 0xf8, 0x54, 0xb5, 0x4d, 0x97, 0x8a, 0x4f, 0x8f, 0xa8, - 0xdf, 0x3e, 0x76, 0x3d, 0xc3, 0xb1, 0x3b, 0xc0, 0xd4, 0x8f, 0x7f, 0x12, 0x66, 0xd8, 0x18, 0xeb, - 0x7d, 0xdf, 0xd5, 0x6c, 0x6f, 0x17, 0xbb, 0x34, 0x28, 0xd5, 0xd4, 0x26, 0x01, 0xde, 0xe3, 0x30, - 0xe5, 0x77, 0x25, 0x58, 0xe2, 0xb5, 0xe1, 0xc9, 0xf5, 0x22, 0x2f, 0x66, 0x08, 0xa7, 0x5b, 0x3e, - 0xa4, 0xda, 0xaa, 0x14, 0xc8, 0x7a, 0xaa, 0x19, 0x59, 0x4f, 0xbc, 0xe2, 0x98, 0x4e, 0x55, 0x1c, - 0x41, 0xff, 0x60, 0xa6, 0x78, 0xff, 0x00, 0x2d, 0x40, 0x95, 0xa6, 0xc1, 0x54, 0x76, 0x75, 0x95, - 0x7d, 0x14, 0x63, 0xe8, 0x9f, 0x25, 0x68, 0xf5, 0xb0, 0xe6, 0x0e, 0xf7, 0x04, 0x1f, 0xdf, 0x8c, - 0xf6, 0x5b, 0x5e, 0xce, 0x11, 0x71, 0x6c, 0xc9, 0x97, 0xa7, 0xd1, 0xf2, 0x17, 0x09, 0x9a, 0xff, - 0x45, 0x86, 0xc4, 0x61, 0xaf, 0x47, 0x0f, 0x7b, 0x29, 0xe7, 0xb0, 0x2a, 0xf6, 0x5d, 0x03, 0xef, - 0xe3, 0x2f, 0xdd, 0x71, 0x7f, 0x23, 0x41, 0xb7, 0x77, 0x60, 0x0f, 0x55, 0x66, 0xcb, 0x27, 0xb7, - 0x98, 0x0b, 0xd0, 0xda, 0x8f, 0xa5, 0x4a, 0x25, 0xaa, 0x70, 0xcd, 0xfd, 0x68, 0x4d, 0xa5, 0x82, - 0x2c, 0xda, 0x3c, 0xfc, 0xb0, 0xc2, 0xb5, 0xbe, 0x92, 0x45, 0x75, 0x82, 0x38, 0xea, 0x9a, 0x66, - 0xdd, 0x38, 0x50, 0x71, 0x61, 0x3e, 0x63, 0x1e, 0x3a, 0x05, 0x33, 0xbc, 0x7c, 0xe3, 0x21, 0x94, - 0x99, 0xb0, 0x4e, 0xa4, 0x13, 0x36, 0x20, 0x0c, 0x3d, 0x9d, 0x7e, 0xe9, 0xe8, 0x1c, 0x34, 0x82, - 0x3c, 0x5b, 0x4f, 0x89, 0x47, 0xf7, 0x94, 0x5f, 0x48, 0xb0, 0xf4, 0x9e, 0x66, 0xeb, 0xce, 0xee, - 0xee, 0xc9, 0x39, 0xb7, 0x0e, 0xb1, 0x14, 0xbc, 0x68, 0x71, 0x1f, 0xcf, 0xdb, 0x2f, 0xc3, 0x9c, - 0xcb, 0x9c, 0x9f, 0x1e, 0x67, 0x6d, 0x59, 0x95, 0xc5, 0x40, 0xc0, 0xb2, 0x8f, 0x4b, 0x80, 0x88, - 0xbf, 0xbf, 0xa9, 0x99, 0x9a, 0x3d, 0xc4, 0xc7, 0x27, 0xfd, 0x22, 0xb4, 0x63, 0x51, 0x2a, 0xb8, - 0x03, 0x89, 0x86, 0x29, 0x0f, 0xdd, 0x86, 0xf6, 0x80, 0xa1, 0xea, 0xbb, 0x58, 0xf3, 0x1c, 0x9b, - 0xfa, 0xcf, 0x76, 0x76, 0x1d, 0x7f, 0xcf, 0x35, 0x46, 0x23, 0xec, 0xae, 0x3b, 0xb6, 0xce, 0xe2, - 0x44, 0x6b, 0x20, 0xc8, 0x24, 0x4b, 0x89, 0x70, 0xc2, 0x90, 0x2d, 0xea, 0x47, 0x08, 0x62, 0x36, - 0x65, 0x85, 0x87, 0x35, 0x33, 0x64, 0x44, 0xe8, 0x70, 0x65, 0x36, 0xd0, 0xcb, 0x6f, 0xe3, 0x64, - 0x84, 0x50, 0xe5, 0xa7, 0x12, 0xa0, 0xa0, 0x0e, 0xa1, 0x75, 0x15, 0xd5, 0xb0, 0xe4, 0x52, 0x29, - 0xc3, 0xef, 0x9f, 0x86, 0xba, 0x2e, 0x56, 0x72, 0x8b, 0x08, 0x01, 0xd4, 0x0d, 0x53, 0xa2, 0xfb, - 0x24, 0xde, 0x62, 0x5d, 0xe4, 0xf9, 0x0c, 0x78, 0x87, 0xc2, 0xe2, 0x11, 0xb8, 0x92, 0x8c, 0xc0, - 0xd1, 0x2e, 0x45, 0x35, 0xd6, 0xa5, 0x50, 0x3e, 0x29, 0x81, 0x4c, 0x3d, 0xda, 0x7a, 0x58, 0x2a, - 0x17, 0x22, 0xfa, 0x02, 0xb4, 0xf8, 0x2d, 0x61, 0x8c, 0xf0, 0xe6, 0xe3, 0xc8, 0x66, 0xe8, 0x2a, - 0x2c, 0xb0, 0x49, 0x2e, 0xf6, 0x26, 0x66, 0x98, 0xe2, 0xb2, 0x7c, 0x13, 0x3d, 0x66, 0xae, 0x94, - 0x0c, 0x89, 0x15, 0xf7, 0x61, 0x69, 0x64, 0x3a, 0x03, 0xcd, 0xec, 0xc7, 0xc5, 0xc3, 0x64, 0x58, - 0x40, 0xe3, 0x17, 0xd8, 0xf2, 0x5e, 0x54, 0x86, 0x1e, 0xda, 0x24, 0x45, 0x31, 0x7e, 0x14, 0xa4, - 0x20, 0xbc, 0x01, 0x5d, 0x24, 0x03, 0x69, 0x92, 0x85, 0xe2, 0x4b, 0xf9, 0x48, 0x82, 0xd9, 0x44, - 0xa3, 0x31, 0x59, 0xaa, 0x49, 0xe9, 0x52, 0xed, 0x3a, 0x54, 0x49, 0xfd, 0xc2, 0xfc, 0x5d, 0x3b, - 0xbb, 0x8c, 0x88, 0xef, 0xaa, 0xb2, 0x05, 0xe8, 0x0a, 0xcc, 0x67, 0x5c, 0x49, 0x71, 0x1d, 0x40, - 0xe9, 0x1b, 0x29, 0xe5, 0x0f, 0x15, 0x68, 0x44, 0xf8, 0x71, 0x44, 0x95, 0x59, 0xa4, 0x73, 0x94, - 0x38, 0x5e, 0x39, 0x7d, 0xbc, 0x9c, 0x3b, 0x19, 0xa2, 0x77, 0x16, 0xb6, 0x58, 0x7e, 0xce, 0x8b, - 0x05, 0x0b, 0x5b, 0xb4, 0xec, 0x21, 0x2a, 0x39, 0xb1, 0x58, 0x7d, 0xc8, 0xcc, 0x69, 0xc6, 0x9e, - 0x58, 0xb4, 0x3a, 0x8c, 0x97, 0x26, 0x33, 0x87, 0x94, 0x26, 0xb5, 0x78, 0x69, 0x12, 0xb3, 0xa3, - 0x7a, 0xd2, 0x8e, 0x8a, 0x16, 0x7e, 0x57, 0x61, 0x7e, 0xe8, 0x62, 0xcd, 0xc7, 0xfa, 0xcd, 0x83, - 0xf5, 0x60, 0x88, 0x27, 0x3f, 0x59, 0x43, 0xe8, 0x56, 0xd8, 0x71, 0x61, 0x52, 0x6e, 0x52, 0x29, - 0x67, 0x57, 0x3e, 0x5c, 0x36, 0x4c, 0xc8, 0xc2, 0x3d, 0xd3, 0xaf, 0x64, 0xc9, 0xd9, 0x3a, 0x56, - 0xc9, 0x79, 0x0e, 0x1a, 0x22, 0x7a, 0x12, 0x73, 0x6f, 0x33, 0xcf, 0x27, 0x7c, 0x81, 0xee, 0xc5, - 0x9c, 0xc1, 0x6c, 0xbc, 0x65, 0x99, 0xac, 0x1b, 0xe5, 0x54, 0xdd, 0xa8, 0xfc, 0xbe, 0x0c, 0xed, - 0xb0, 0x1e, 0x29, 0xec, 0x2d, 0x8a, 0xdc, 0xbe, 0x6e, 0x83, 0x1c, 0xc6, 0x5c, 0xca, 0xc8, 0x43, - 0x4b, 0xaa, 0x64, 0xbb, 0x7f, 0x76, 0x9c, 0x30, 0xcb, 0x58, 0x43, 0xb5, 0xf2, 0x4c, 0x0d, 0xd5, - 0x13, 0x5e, 0x54, 0x5d, 0x83, 0xc5, 0x20, 0xce, 0xc6, 0x8e, 0xcd, 0xf2, 0xf5, 0x05, 0x31, 0xb8, - 0x13, 0x3d, 0x7e, 0x8e, 0xa5, 0xcf, 0xe4, 0x59, 0x7a, 0x52, 0xd2, 0xb5, 0x94, 0xa4, 0xd3, 0xf7, - 0x65, 0xf5, 0xac, 0xfb, 0xb2, 0xfb, 0x30, 0x4f, 0xbb, 0x68, 0xde, 0xd0, 0x35, 0x06, 0x38, 0xc8, - 0x3e, 0x8b, 0x88, 0xb5, 0x0b, 0xb5, 0x44, 0x02, 0x1b, 0x7c, 0x2b, 0x5f, 0x93, 0x60, 0x29, 0xbd, - 0x2f, 0xd5, 0x98, 0xd0, 0x5f, 0x48, 0x31, 0x7f, 0xf1, 0x3f, 0x30, 0x1f, 0x6e, 0x1f, 0x4f, 0x8d, - 0x73, 0x92, 0xbf, 0x0c, 0xc2, 0x55, 0x14, 0xee, 0x21, 0x60, 0xca, 0x5f, 0xa5, 0xa0, 0x19, 0x49, - 0x60, 0x23, 0xda, 0x88, 0x25, 0x31, 0xcc, 0xb1, 0x4d, 0xc3, 0x0e, 0xea, 0x67, 0x7e, 0x46, 0x06, - 0xe4, 0xf5, 0xf3, 0x7b, 0x30, 0xcb, 0x27, 0x05, 0xa1, 0xa8, 0x60, 0xf2, 0xd5, 0x66, 0xeb, 0x82, - 0x20, 0x74, 0x11, 0xda, 0xbc, 0x43, 0x2a, 0xf0, 0x95, 0x33, 0xfa, 0xa6, 0xe8, 0x3f, 0x41, 0x16, - 0xd3, 0x9e, 0x35, 0xf8, 0xcd, 0xf2, 0x85, 0x41, 0x12, 0xf7, 0x55, 0x09, 0x3a, 0xf1, 0x50, 0x18, - 0x39, 0xfe, 0xb3, 0xa7, 0x72, 0xff, 0x1e, 0xbf, 0x5b, 0xba, 0x78, 0x08, 0x3d, 0x21, 0x1e, 0x71, - 0xc3, 0xb4, 0x4d, 0xef, 0x09, 0x49, 0x91, 0xb1, 0x61, 0x78, 0xbe, 0x6b, 0x0c, 0x26, 0x27, 0x7a, - 0x41, 0xa0, 0xfc, 0xac, 0x04, 0x2f, 0x66, 0x6e, 0x78, 0x92, 0x5b, 0xa4, 0xbc, 0x9a, 0xfe, 0x26, - 0xd4, 0x12, 0xc5, 0xc8, 0xa5, 0x43, 0x0e, 0xff, 0x80, 0xf5, 0x24, 0x58, 0x9b, 0x44, 0xac, 0x23, - 0x7b, 0x04, 0x3a, 0x5d, 0xc9, 0xdf, 0x83, 0x2b, 0x6d, 0x6c, 0x0f, 0xb1, 0x0e, 0xdd, 0x80, 0x26, - 0x2b, 0xf4, 0xfa, 0xfb, 0x06, 0x7e, 0x22, 0x2e, 0x3f, 0xce, 0x66, 0xfa, 0x35, 0x3a, 0xef, 0x81, - 0x81, 0x9f, 0xa8, 0x0d, 0x33, 0xf8, 0xed, 0x29, 0x1f, 0x95, 0x00, 0xc2, 0x31, 0x52, 0x65, 0x86, - 0x06, 0xc3, 0x2d, 0x20, 0x02, 0x21, 0xf1, 0x36, 0x9e, 0xe2, 0x89, 0x4f, 0x34, 0x00, 0x24, 0xe2, - 0x1e, 0x8d, 0x28, 0x63, 0xcd, 0x70, 0x05, 0x77, 0xde, 0x38, 0x9c, 0x22, 0xc1, 0x28, 0xa2, 0xf2, - 0x3b, 0x64, 0x19, 0xbb, 0x66, 0x90, 0xbd, 0x04, 0x18, 0xbd, 0x06, 0x68, 0xe4, 0x3a, 0x4f, 0x0c, - 0x7b, 0x14, 0x4d, 0xd4, 0x59, 0x3e, 0x3f, 0xc7, 0x47, 0xc2, 0x4c, 0xbd, 0xbb, 0x0e, 0x8b, 0x99, - 0x3b, 0x67, 0xdc, 0x3b, 0x2c, 0x44, 0xef, 0x1d, 0xca, 0xd1, 0x7b, 0x85, 0xef, 0x48, 0x80, 0xd2, - 0x82, 0x44, 0x6d, 0x28, 0x05, 0x2e, 0xa2, 0xb4, 0xb5, 0x91, 0x60, 0x5c, 0x29, 0xc5, 0xb8, 0xd3, - 0x50, 0x0f, 0x9c, 0x3f, 0xb7, 0xf4, 0x10, 0x10, 0x65, 0x6b, 0x25, 0xce, 0xd6, 0x48, 0x8b, 0xab, - 0x1a, 0x6b, 0x71, 0x29, 0x7b, 0x80, 0xd2, 0xca, 0x11, 0xdd, 0x49, 0x8a, 0xef, 0x74, 0x14, 0x85, - 0x11, 0x4c, 0xe5, 0x38, 0xa6, 0xdf, 0x4a, 0x80, 0xc2, 0xf0, 0x16, 0x5c, 0x59, 0x14, 0x89, 0x09, - 0x57, 0x60, 0x3e, 0x1d, 0xfc, 0x44, 0xc4, 0x47, 0xa9, 0xd0, 0x97, 0x15, 0xa6, 0xca, 0x19, 0x61, - 0x0a, 0xbd, 0x19, 0x98, 0x33, 0x8b, 0xe5, 0x67, 0xf3, 0x62, 0x79, 0xdc, 0xa2, 0x95, 0x9f, 0x4b, - 0x30, 0x17, 0x60, 0x7b, 0xa6, 0x93, 0x1c, 0x7d, 0x05, 0xf3, 0x9c, 0x49, 0xef, 0xc1, 0x0c, 0xef, - 0x5a, 0xa4, 0x94, 0xaf, 0x48, 0xe2, 0xbe, 0x00, 0x55, 0x62, 0x97, 0xa2, 0xc4, 0x67, 0x1f, 0x44, - 0xbb, 0xa1, 0x77, 0x60, 0x0f, 0x6f, 0x30, 0x1d, 0xb8, 0x0a, 0x95, 0xa3, 0x6e, 0x9c, 0xc9, 0x6c, - 0x9a, 0x20, 0xd1, 0x99, 0x05, 0xd8, 0x12, 0xab, 0x39, 0xca, 0xc9, 0x9a, 0x23, 0xef, 0x05, 0xd7, - 0xaf, 0x25, 0x38, 0x45, 0x50, 0x7d, 0x2a, 0xd1, 0xa1, 0x10, 0x83, 0x22, 0x96, 0x53, 0x8e, 0x5b, - 0xce, 0x75, 0x98, 0x61, 0xc9, 0xbd, 0xf0, 0xd4, 0x67, 0xf3, 0x18, 0xc3, 0xd8, 0xa8, 0x8a, 0xe9, - 0x2b, 0xff, 0x01, 0xf5, 0xa0, 0x8f, 0x86, 0x1a, 0x30, 0x73, 0xdf, 0xbe, 0x6d, 0x3b, 0x4f, 0x6c, - 0x79, 0x0a, 0xcd, 0x40, 0xf9, 0x86, 0x69, 0xca, 0x12, 0x6a, 0x41, 0xbd, 0xe7, 0xbb, 0x58, 0xb3, - 0x0c, 0x7b, 0x24, 0x97, 0x50, 0x1b, 0xe0, 0x3d, 0xc3, 0xf3, 0x1d, 0xd7, 0x18, 0x6a, 0xa6, 0x5c, - 0x5e, 0xf9, 0x10, 0xda, 0xf1, 0xdc, 0x16, 0x35, 0xa1, 0xb6, 0xed, 0xf8, 0xef, 0x3e, 0x35, 0x3c, - 0x5f, 0x9e, 0x22, 0xf3, 0xb7, 0x1d, 0x7f, 0xc7, 0xc5, 0x1e, 0xb6, 0x7d, 0x59, 0x42, 0x00, 0xd3, - 0xef, 0xdb, 0x1b, 0x86, 0xf7, 0x48, 0x2e, 0xa1, 0x79, 0x5e, 0x9d, 0x6a, 0xe6, 0x16, 0x4f, 0x18, - 0xe5, 0x32, 0x59, 0x1e, 0x7c, 0x55, 0x90, 0x0c, 0xcd, 0x60, 0xca, 0xe6, 0xce, 0x7d, 0xb9, 0x8a, - 0xea, 0x50, 0x65, 0x3f, 0xa7, 0x57, 0x74, 0x90, 0x93, 0xad, 0x15, 0xb2, 0x27, 0x3b, 0x44, 0x00, - 0x92, 0xa7, 0xc8, 0xc9, 0x78, 0x6f, 0x4b, 0x96, 0xd0, 0x2c, 0x34, 0x22, 0x9d, 0x22, 0xb9, 0x44, - 0x00, 0x9b, 0xee, 0x78, 0xc8, 0xa5, 0xc7, 0x48, 0x20, 0x0e, 0x79, 0x83, 0x70, 0xa2, 0xb2, 0x72, - 0x13, 0x6a, 0x22, 0xe9, 0x26, 0x53, 0x39, 0x8b, 0xc8, 0xa7, 0x3c, 0x85, 0xe6, 0xa0, 0x15, 0x7b, - 0xcb, 0x26, 0x4b, 0x08, 0x41, 0x3b, 0xfe, 0xc6, 0x52, 0x2e, 0xad, 0xac, 0x01, 0x84, 0x16, 0x43, - 0xc8, 0xd9, 0xb2, 0xf7, 0x35, 0xd3, 0xd0, 0x19, 0x6d, 0x64, 0x88, 0x70, 0x97, 0x72, 0x87, 0xf5, - 0x48, 0xe4, 0xd2, 0xca, 0x39, 0xa8, 0x09, 0x5d, 0x26, 0x70, 0x15, 0x5b, 0xce, 0x3e, 0x66, 0x92, - 0xe9, 0x61, 0x5f, 0x96, 0xd6, 0xbe, 0xd7, 0x02, 0x60, 0xdd, 0x10, 0xc7, 0x71, 0x75, 0x34, 0x06, - 0xb4, 0x89, 0x7d, 0x52, 0xe9, 0x39, 0xb6, 0xa8, 0xd2, 0x3c, 0x74, 0x35, 0xff, 0x0d, 0x61, 0x62, - 0x2a, 0x3f, 0x7f, 0x37, 0xaf, 0x31, 0x9c, 0x98, 0xae, 0x4c, 0x21, 0x8b, 0x62, 0xbc, 0x67, 0x58, - 0xf8, 0x9e, 0x31, 0x7c, 0x14, 0xb4, 0x51, 0xf2, 0x31, 0x26, 0xa6, 0x0a, 0x8c, 0x89, 0x8a, 0x89, - 0x7f, 0xf4, 0x7c, 0xd7, 0xb0, 0x47, 0x22, 0x41, 0x52, 0xa6, 0xd0, 0xe3, 0xc4, 0x9b, 0x49, 0x81, - 0x70, 0xad, 0xc8, 0x33, 0xc9, 0xe3, 0xa1, 0x34, 0x61, 0x36, 0xf1, 0xc0, 0x1a, 0xad, 0x64, 0xbf, - 0xd4, 0xc9, 0x7a, 0x0c, 0xde, 0xbd, 0x5c, 0x68, 0x6e, 0x80, 0xcd, 0x80, 0x76, 0xfc, 0x11, 0x31, - 0xfa, 0x97, 0xbc, 0x0d, 0x52, 0x6f, 0x05, 0xbb, 0x2b, 0x45, 0xa6, 0x06, 0xa8, 0x1e, 0x32, 0x25, - 0x3d, 0x0a, 0x55, 0xe6, 0x3b, 0xcd, 0xee, 0x61, 0xb9, 0xa9, 0x32, 0x85, 0xfe, 0x0f, 0xe6, 0x52, - 0x2f, 0x1a, 0xd1, 0xab, 0xd9, 0xdd, 0xf0, 0xec, 0x87, 0x8f, 0x47, 0x61, 0x78, 0x98, 0x34, 0xb1, - 0x7c, 0xea, 0x53, 0xaf, 0x7f, 0x8b, 0x53, 0x1f, 0xd9, 0xfe, 0x30, 0xea, 0x9f, 0x19, 0xc3, 0x84, - 0x9a, 0x4d, 0xb2, 0x2f, 0xf7, 0x5a, 0x16, 0x8a, 0xdc, 0x67, 0x95, 0xdd, 0xd5, 0xa2, 0xd3, 0xa3, - 0xda, 0x15, 0x7f, 0xb9, 0x97, 0xcd, 0xb4, 0xcc, 0xd7, 0x86, 0xd9, 0xda, 0x95, 0xfd, 0x10, 0x50, - 0x99, 0x42, 0xf7, 0x62, 0x2e, 0x16, 0x5d, 0xca, 0x13, 0x4e, 0xbc, 0x5b, 0x7f, 0x14, 0xdf, 0xfe, - 0x1f, 0x10, 0xb3, 0x1d, 0x7b, 0xd7, 0x18, 0x4d, 0x5c, 0x8d, 0x29, 0x56, 0x9e, 0xbb, 0x49, 0x4f, - 0x15, 0x68, 0x5e, 0x7f, 0x86, 0x15, 0xc1, 0x91, 0xfa, 0x00, 0x9b, 0xd8, 0xbf, 0x8b, 0x7d, 0xd7, - 0x18, 0x7a, 0xc9, 0x13, 0xf1, 0x8f, 0x70, 0x82, 0x40, 0xf5, 0xca, 0x91, 0xf3, 0x02, 0x04, 0x03, - 0x68, 0x6c, 0x62, 0x9f, 0x67, 0x50, 0x1e, 0xca, 0x5d, 0x29, 0x66, 0x08, 0x14, 0xcb, 0x47, 0x4f, - 0x8c, 0xba, 0xb3, 0xc4, 0x2b, 0x46, 0x94, 0x2b, 0xd8, 0xf4, 0xdb, 0xca, 0x6c, 0x77, 0x96, 0xf3, - 0x2c, 0x52, 0x99, 0x5a, 0xfb, 0x49, 0x1b, 0xea, 0x34, 0x3e, 0x91, 0x60, 0xfa, 0xcf, 0xf0, 0xf4, - 0x1c, 0xc2, 0xd3, 0x07, 0x30, 0x9b, 0x78, 0x14, 0x97, 0x2d, 0xcf, 0xec, 0x97, 0x73, 0x05, 0xbc, - 0x6c, 0xfc, 0xc1, 0x5a, 0xb6, 0xc3, 0xc8, 0x7c, 0xd4, 0x76, 0xd4, 0xde, 0x0f, 0xd8, 0x7b, 0xd2, - 0xa0, 0xdb, 0xf4, 0x4a, 0x6e, 0x91, 0x11, 0xbf, 0x8c, 0xfc, 0xfc, 0xbd, 0xf7, 0xf3, 0x8f, 0x6e, - 0x1f, 0xc0, 0x6c, 0xe2, 0xd5, 0x47, 0xb6, 0x54, 0xb3, 0x9f, 0x86, 0x1c, 0xb5, 0xfb, 0x67, 0x18, - 0x06, 0x74, 0x98, 0xcf, 0xb8, 0x90, 0x47, 0xab, 0x79, 0xd5, 0x49, 0xf6, 0xcd, 0xfd, 0xd1, 0x07, - 0x6a, 0xc5, 0x4c, 0x09, 0x2d, 0xe7, 0x11, 0x99, 0xfc, 0xcf, 0x4c, 0xf7, 0xd5, 0x62, 0x7f, 0xb0, - 0x09, 0x0e, 0xd4, 0x83, 0x69, 0xf6, 0x16, 0x04, 0xbd, 0x94, 0xdd, 0x4f, 0x8b, 0xbc, 0x13, 0xe9, - 0x1e, 0xf5, 0x9a, 0xc4, 0x9b, 0x98, 0xbe, 0x47, 0x37, 0xad, 0x52, 0x2f, 0x89, 0x32, 0x1f, 0x31, - 0x45, 0x1f, 0x70, 0x74, 0x8f, 0x7e, 0xb3, 0x21, 0x36, 0xfd, 0xc7, 0x8e, 0x95, 0x4f, 0x61, 0x3e, - 0xa3, 0x97, 0x8a, 0xf2, 0x72, 0xa2, 0x9c, 0x2e, 0x6e, 0xf7, 0x4a, 0xe1, 0xf9, 0x01, 0xe6, 0xff, - 0x05, 0x39, 0x59, 0xf5, 0xa3, 0xcb, 0x79, 0xfa, 0x9c, 0x85, 0xf3, 0x70, 0x65, 0xbe, 0xf9, 0xc6, - 0xc3, 0xb5, 0x91, 0xe1, 0xef, 0x4d, 0x06, 0x64, 0xe4, 0x0a, 0x9b, 0xfa, 0x9a, 0xe1, 0xf0, 0x5f, - 0x57, 0x04, 0xff, 0xaf, 0xd0, 0xd5, 0x57, 0x28, 0xaa, 0xf1, 0x60, 0x30, 0x4d, 0x3f, 0xaf, 0xfd, - 0x3d, 0x00, 0x00, 0xff, 0xff, 0x5c, 0x5a, 0x28, 0x07, 0x0b, 0x3b, 0x00, 0x00, + // 3512 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3b, 0x49, 0x6c, 0x1c, 0xd7, + 0x95, 0xac, 0x5e, 0xc8, 0xee, 0xd7, 0x0b, 0x8b, 0x9f, 0x8b, 0xda, 0x6d, 0x6d, 0x2e, 0x59, 0x32, + 0x87, 0xb2, 0x29, 0x99, 0xf2, 0x18, 0xf2, 0x8c, 0x0d, 0x8c, 0x44, 0x5a, 0x34, 0x47, 0x12, 0xcd, + 0xa9, 0x96, 0x34, 0x03, 0xc1, 0x98, 0x9e, 0xea, 0xae, 0xcf, 0x66, 0x41, 0xb5, 0xb4, 0xaa, 0xaa, + 0x29, 0xd1, 0x73, 0xcd, 0x25, 0xdb, 0x21, 0x39, 0xe4, 0x94, 0xf8, 0x94, 0x00, 0x09, 0x60, 0x1f, + 0x02, 0x24, 0x40, 0x0e, 0x41, 0x10, 0x20, 0x87, 0xe4, 0x14, 0xe4, 0x90, 0x63, 0x80, 0x1c, 0x73, + 0x48, 0xae, 0x39, 0xe4, 0x16, 0xfc, 0xad, 0xf6, 0x22, 0x4b, 0xa4, 0xe5, 0x25, 0xc8, 0xad, 0xeb, + 0xfd, 0xe5, 0xbd, 0xff, 0xf6, 0xf7, 0xfe, 0x6f, 0x98, 0x7b, 0x3c, 0xc1, 0xee, 0x41, 0x7f, 0xe8, + 0x38, 0xae, 0xbe, 0x3a, 0x76, 0x1d, 0xdf, 0x41, 0xc8, 0x32, 0xcc, 0xfd, 0x89, 0xc7, 0xbe, 0x56, + 0xe9, 0x78, 0xb7, 0x39, 0x74, 0x2c, 0xcb, 0xb1, 0x19, 0xac, 0xdb, 0x8c, 0xce, 0xe8, 0xb6, 0x0d, + 0xdb, 0xc7, 0xae, 0xad, 0x99, 0x62, 0xd4, 0x1b, 0xee, 0x61, 0x4b, 0xe3, 0x5f, 0xb2, 0xae, 0xf9, + 0x5a, 0x74, 0x7f, 0xe5, 0x2b, 0x12, 0x2c, 0xf5, 0xf6, 0x9c, 0x27, 0xeb, 0x8e, 0x69, 0xe2, 0xa1, + 0x6f, 0x38, 0xb6, 0xa7, 0xe2, 0xc7, 0x13, 0xec, 0xf9, 0xe8, 0x2a, 0x54, 0x06, 0x9a, 0x87, 0x3b, + 0xd2, 0x79, 0x69, 0xb9, 0xb1, 0x76, 0x7a, 0x35, 0x46, 0x09, 0x27, 0xe1, 0xae, 0x37, 0xba, 0xa9, + 0x79, 0x58, 0xa5, 0x33, 0x11, 0x82, 0x8a, 0x3e, 0xd8, 0xda, 0xe8, 0x94, 0xce, 0x4b, 0xcb, 0x65, + 0x95, 0xfe, 0x46, 0x2f, 0x43, 0x6b, 0x18, 0xec, 0xbd, 0xb5, 0xe1, 0x75, 0xca, 0xe7, 0xcb, 0xcb, + 0x65, 0x35, 0x0e, 0x54, 0xfe, 0x28, 0xc1, 0xa9, 0x14, 0x19, 0xde, 0xd8, 0xb1, 0x3d, 0x8c, 0xae, + 0xc1, 0xb4, 0xe7, 0x6b, 0xfe, 0xc4, 0xe3, 0x94, 0xbc, 0x98, 0x49, 0x49, 0x8f, 0x4e, 0x51, 0xf9, + 0xd4, 0x34, 0xda, 0x52, 0x06, 0x5a, 0xf4, 0x3a, 0x2c, 0x18, 0xf6, 0x5d, 0x6c, 0x39, 0xee, 0x41, + 0x7f, 0x8c, 0xdd, 0x21, 0xb6, 0x7d, 0x6d, 0x84, 0x05, 0x8d, 0xf3, 0x62, 0x6c, 0x27, 0x1c, 0x42, + 0x6f, 0xc2, 0x29, 0x26, 0x25, 0x0f, 0xbb, 0xfb, 0xc6, 0x10, 0xf7, 0xb5, 0x7d, 0xcd, 0x30, 0xb5, + 0x81, 0x89, 0x3b, 0x95, 0xf3, 0xe5, 0xe5, 0x9a, 0xba, 0x48, 0x87, 0x7b, 0x6c, 0xf4, 0x86, 0x18, + 0x54, 0x7e, 0x20, 0xc1, 0x22, 0x39, 0xe1, 0x8e, 0xe6, 0xfa, 0xc6, 0x73, 0xe0, 0xb3, 0x02, 0xcd, + 0xe8, 0xd9, 0x3a, 0x65, 0x3a, 0x16, 0x83, 0x91, 0x39, 0x63, 0x81, 0x9e, 0xf0, 0xa4, 0x42, 0x8f, + 0x19, 0x83, 0x29, 0xdf, 0xe7, 0x0a, 0x11, 0xa5, 0xf3, 0x24, 0x82, 0x48, 0xe2, 0x2c, 0xa5, 0x71, + 0x1e, 0x43, 0x0c, 0xca, 0x9f, 0x24, 0x58, 0xbc, 0xe3, 0x68, 0x7a, 0xa8, 0x30, 0x9f, 0x3d, 0x3b, + 0xdf, 0x81, 0x69, 0x66, 0x5d, 0x9d, 0x0a, 0xc5, 0x75, 0x31, 0x8e, 0x8b, 0x5b, 0x5e, 0x48, 0x61, + 0x8f, 0x02, 0x54, 0xbe, 0x08, 0x5d, 0x84, 0xb6, 0x8b, 0xc7, 0xa6, 0x31, 0xd4, 0xfa, 0xf6, 0xc4, + 0x1a, 0x60, 0xb7, 0x53, 0x3d, 0x2f, 0x2d, 0x57, 0xd5, 0x16, 0x87, 0x6e, 0x53, 0xa0, 0xf2, 0x5d, + 0x09, 0x3a, 0x2a, 0x36, 0xb1, 0xe6, 0xe1, 0xcf, 0xf3, 0xb0, 0x4b, 0x30, 0x6d, 0x3b, 0x3a, 0xde, + 0xda, 0xa0, 0x87, 0x2d, 0xab, 0xfc, 0x4b, 0xf9, 0x9b, 0x04, 0x0b, 0x9b, 0xd8, 0x27, 0x52, 0x37, + 0x3c, 0xdf, 0x18, 0x06, 0x6a, 0xfd, 0x0e, 0x94, 0x5d, 0xfc, 0x98, 0x53, 0x76, 0x39, 0x4e, 0x59, + 0xe0, 0xa4, 0xb2, 0x56, 0xaa, 0x64, 0x1d, 0x7a, 0x09, 0x9a, 0xba, 0x65, 0xf6, 0x87, 0x7b, 0x9a, + 0x6d, 0x63, 0x93, 0xe9, 0x4d, 0x5d, 0x6d, 0xe8, 0x96, 0xb9, 0xce, 0x41, 0xe8, 0x2c, 0x80, 0x87, + 0x47, 0x16, 0xb6, 0xfd, 0xd0, 0xaf, 0x44, 0x20, 0x68, 0x05, 0xe6, 0x76, 0x5d, 0xc7, 0xea, 0x7b, + 0x7b, 0x9a, 0xab, 0xf7, 0x4d, 0xac, 0xe9, 0xd8, 0xa5, 0xd4, 0xd7, 0xd4, 0x59, 0x32, 0xd0, 0x23, + 0xf0, 0x3b, 0x14, 0x8c, 0xae, 0x41, 0xd5, 0x1b, 0x3a, 0x63, 0x4c, 0x65, 0xd0, 0x5e, 0x3b, 0xb3, + 0x9a, 0xf6, 0xbb, 0xab, 0x1b, 0x9a, 0xaf, 0xf5, 0xc8, 0x24, 0x95, 0xcd, 0x55, 0xbe, 0x5e, 0x62, + 0x4a, 0xf8, 0x05, 0xb7, 0xe9, 0x88, 0xa2, 0x56, 0x3f, 0x1d, 0x45, 0x9d, 0xce, 0x52, 0xd4, 0x5f, + 0x86, 0x8a, 0xfa, 0x45, 0x67, 0x48, 0xa8, 0xcc, 0xd5, 0x98, 0x32, 0xff, 0x48, 0x82, 0x17, 0x36, + 0xb1, 0x1f, 0x90, 0x4f, 0x74, 0x13, 0x7f, 0x41, 0x1d, 0xf5, 0x27, 0x12, 0x74, 0xb3, 0x68, 0x3d, + 0x89, 0xb3, 0x7e, 0x08, 0x4b, 0x01, 0x8e, 0xbe, 0x8e, 0xbd, 0xa1, 0x6b, 0x8c, 0xa9, 0x18, 0xa9, + 0xf9, 0x35, 0xd6, 0x2e, 0x64, 0x99, 0x45, 0x92, 0x82, 0xc5, 0x60, 0x8b, 0x8d, 0xc8, 0x0e, 0xca, + 0x37, 0x25, 0x58, 0x24, 0xe6, 0xce, 0xed, 0xd3, 0xde, 0x75, 0x8e, 0xcf, 0xd7, 0xb8, 0xe5, 0x97, + 0x52, 0x96, 0x5f, 0x80, 0xc7, 0x34, 0xf3, 0x49, 0xd2, 0x73, 0x12, 0xde, 0xfd, 0x2b, 0x54, 0x0d, + 0x7b, 0xd7, 0x11, 0xac, 0x3a, 0x97, 0xc5, 0xaa, 0x28, 0x32, 0x36, 0x5b, 0xb1, 0x19, 0x15, 0xa1, + 0x2b, 0x3a, 0x81, 0xba, 0x25, 0x8f, 0x5d, 0xca, 0x38, 0xf6, 0x37, 0x24, 0x38, 0x95, 0x42, 0x78, + 0x92, 0x73, 0xbf, 0x0d, 0xd3, 0xd4, 0xc1, 0x8a, 0x83, 0xbf, 0x9c, 0x79, 0xf0, 0x08, 0xba, 0x3b, + 0x86, 0xe7, 0xab, 0x7c, 0x8d, 0xe2, 0x80, 0x9c, 0x1c, 0x23, 0xae, 0x9f, 0xbb, 0xfd, 0xbe, 0xad, + 0x59, 0x8c, 0x01, 0x75, 0xb5, 0xc1, 0x61, 0xdb, 0x9a, 0x85, 0xd1, 0x0b, 0x50, 0x23, 0x26, 0xdb, + 0x37, 0x74, 0x21, 0xfe, 0x19, 0x6a, 0xc2, 0xba, 0x87, 0xce, 0x00, 0xd0, 0x21, 0x4d, 0xd7, 0x5d, + 0x16, 0x15, 0xea, 0x6a, 0x9d, 0x40, 0x6e, 0x10, 0x80, 0xf2, 0x2d, 0x09, 0x9a, 0xc4, 0x67, 0xdf, + 0xc5, 0xbe, 0x46, 0xe4, 0x80, 0xde, 0x82, 0xba, 0xe9, 0x68, 0x7a, 0xdf, 0x3f, 0x18, 0x33, 0x54, + 0xed, 0x24, 0xaf, 0xd9, 0x11, 0xc8, 0xa2, 0x7b, 0x07, 0x63, 0xac, 0xd6, 0x4c, 0xfe, 0xab, 0x08, + 0xbf, 0x53, 0xa6, 0x5c, 0xce, 0x30, 0xe5, 0x8f, 0xab, 0xb0, 0xf4, 0xdf, 0x9a, 0x3f, 0xdc, 0xdb, + 0xb0, 0x44, 0x70, 0x3b, 0xbe, 0x12, 0x84, 0xbe, 0xad, 0x14, 0xf5, 0x6d, 0x9f, 0x9a, 0xef, 0x0c, + 0xf4, 0xbc, 0x9a, 0xa5, 0xe7, 0xa4, 0xc0, 0x58, 0x7d, 0xc0, 0x45, 0x15, 0xd1, 0xf3, 0x48, 0x0c, + 0x9a, 0x3e, 0x4e, 0x0c, 0x5a, 0x87, 0x16, 0x7e, 0x3a, 0x34, 0x27, 0x44, 0xe6, 0x14, 0xfb, 0x0c, + 0xc5, 0x7e, 0x36, 0x03, 0x7b, 0xd4, 0xc8, 0x9a, 0x7c, 0xd1, 0x16, 0xa7, 0x81, 0x89, 0xda, 0xc2, + 0xbe, 0xd6, 0xa9, 0x51, 0x32, 0xce, 0xe7, 0x89, 0x5a, 0xe8, 0x07, 0x13, 0x37, 0xf9, 0x42, 0xa7, + 0xa1, 0xce, 0x23, 0xde, 0xd6, 0x46, 0xa7, 0x4e, 0xd9, 0x17, 0x02, 0x90, 0x06, 0x2d, 0xee, 0x81, + 0x38, 0x85, 0x40, 0x29, 0x7c, 0x3b, 0x0b, 0x41, 0xb6, 0xb0, 0xa3, 0x94, 0x7b, 0xef, 0xda, 0xbe, + 0x7b, 0xa0, 0x36, 0xbd, 0x08, 0x88, 0x14, 0x35, 0xce, 0xee, 0xae, 0x69, 0xd8, 0x78, 0x9b, 0x49, + 0xb8, 0x41, 0x89, 0x88, 0x03, 0xbb, 0x7d, 0x98, 0x4b, 0x6d, 0x84, 0x64, 0x28, 0x3f, 0xc2, 0x07, + 0x54, 0x8d, 0xca, 0x2a, 0xf9, 0x89, 0xde, 0x80, 0xea, 0xbe, 0x66, 0x4e, 0x30, 0x55, 0x93, 0xa3, + 0x39, 0xc9, 0x26, 0xff, 0x5b, 0xe9, 0xba, 0xa4, 0xfc, 0x50, 0x82, 0xc5, 0xfb, 0xb6, 0x37, 0x19, + 0x04, 0x27, 0xf8, 0x7c, 0xb4, 0x35, 0xe9, 0x27, 0x2a, 0x29, 0x3f, 0xa1, 0xfc, 0xa2, 0x02, 0xb3, + 0xfc, 0x14, 0x44, 0xa8, 0xd4, 0xe0, 0x4f, 0x43, 0x3d, 0x08, 0x15, 0x9c, 0x21, 0x21, 0x00, 0x9d, + 0x87, 0x46, 0x44, 0xdd, 0x39, 0x55, 0x51, 0x50, 0x21, 0xd2, 0x44, 0xe0, 0xaf, 0x44, 0x02, 0xff, + 0x19, 0x80, 0x5d, 0x73, 0xe2, 0xed, 0xf5, 0x7d, 0xc3, 0xc2, 0x3c, 0xf1, 0xa8, 0x53, 0xc8, 0x3d, + 0xc3, 0xc2, 0xe8, 0x06, 0x34, 0x07, 0x86, 0x6d, 0x3a, 0xa3, 0xfe, 0x58, 0xf3, 0xf7, 0xbc, 0xce, + 0x74, 0xae, 0x82, 0xdf, 0x32, 0xb0, 0xa9, 0xdf, 0xa4, 0x73, 0xd5, 0x06, 0x5b, 0xb3, 0x43, 0x96, + 0xa0, 0xb3, 0xd0, 0xb0, 0x27, 0x56, 0xdf, 0xd9, 0xed, 0xbb, 0xce, 0x13, 0x62, 0x22, 0x14, 0x85, + 0x3d, 0xb1, 0xde, 0xdf, 0x55, 0x9d, 0x27, 0xc4, 0x55, 0xd7, 0x89, 0xd3, 0xf6, 0x4c, 0x67, 0xe4, + 0x75, 0x6a, 0x85, 0xf6, 0x0f, 0x17, 0x90, 0xd5, 0x3a, 0x36, 0x7d, 0x8d, 0xae, 0xae, 0x17, 0x5b, + 0x1d, 0x2c, 0x40, 0x97, 0xa0, 0x3d, 0x74, 0xac, 0xb1, 0x46, 0x39, 0x74, 0xcb, 0x75, 0x2c, 0x6a, + 0x1f, 0x65, 0x35, 0x01, 0x45, 0xeb, 0xd0, 0x30, 0x6c, 0x1d, 0x3f, 0xe5, 0x46, 0xd4, 0xa0, 0x78, + 0x94, 0x2c, 0x23, 0xa2, 0x88, 0xb6, 0xc8, 0x5c, 0xaa, 0xa0, 0x60, 0x88, 0x9f, 0x1e, 0xd1, 0x0c, + 0x61, 0x8b, 0x9e, 0xf1, 0x21, 0xee, 0x34, 0x99, 0x14, 0x39, 0xac, 0x67, 0x7c, 0x88, 0x49, 0x52, + 0x6b, 0xd8, 0x1e, 0x76, 0x7d, 0x51, 0x62, 0x74, 0x5a, 0x54, 0x7d, 0x5a, 0x0c, 0xca, 0x15, 0x5b, + 0xf9, 0x7d, 0x09, 0xda, 0x71, 0x44, 0xa8, 0x03, 0x33, 0xbb, 0x14, 0x22, 0xb4, 0x47, 0x7c, 0x12, + 0xb4, 0xd8, 0x26, 0xd5, 0x7e, 0x9f, 0xd2, 0x42, 0x95, 0xa7, 0xa6, 0x36, 0x18, 0x8c, 0x6e, 0x40, + 0x94, 0x80, 0x1d, 0x8f, 0x6a, 0x6c, 0x99, 0xa2, 0xac, 0x53, 0x08, 0x8d, 0x6b, 0x1d, 0x98, 0x61, + 0xc7, 0x10, 0xaa, 0x23, 0x3e, 0xc9, 0xc8, 0x60, 0x62, 0x50, 0xac, 0x4c, 0x75, 0xc4, 0x27, 0xda, + 0x80, 0x26, 0xdb, 0x72, 0xac, 0xb9, 0x9a, 0x25, 0x14, 0xe7, 0xa5, 0x4c, 0xe3, 0xbb, 0x8d, 0x0f, + 0x1e, 0x10, 0x3b, 0xde, 0xd1, 0x0c, 0x57, 0x65, 0x8c, 0xde, 0xa1, 0xab, 0xd0, 0x32, 0xc8, 0x6c, + 0x97, 0x5d, 0xc3, 0xc4, 0x5c, 0x05, 0x67, 0x68, 0xf0, 0x6c, 0x53, 0xf8, 0x2d, 0xc3, 0xc4, 0x4c, + 0xcb, 0x82, 0x23, 0x50, 0xd6, 0xd6, 0x98, 0x92, 0x51, 0x08, 0x65, 0xec, 0x05, 0x68, 0xb1, 0xe1, + 0x7d, 0xec, 0x7a, 0x86, 0x63, 0x73, 0x4f, 0xc9, 0x68, 0x7c, 0xc0, 0x60, 0xca, 0xb7, 0x2b, 0x30, + 0x4f, 0x0c, 0x92, 0xdb, 0xe6, 0x09, 0xc2, 0xdd, 0x19, 0x00, 0xdd, 0xf3, 0xfb, 0x31, 0x27, 0x52, + 0xd7, 0x3d, 0x9f, 0x39, 0x43, 0xf4, 0x96, 0x88, 0x56, 0xe5, 0xfc, 0x04, 0x36, 0xe1, 0x20, 0xd2, + 0x11, 0xeb, 0x58, 0xe5, 0xfd, 0x05, 0x68, 0x79, 0xce, 0xc4, 0x1d, 0xe2, 0x7e, 0xac, 0xd4, 0x68, + 0x32, 0xe0, 0x76, 0xb6, 0x9b, 0x9b, 0xce, 0x6c, 0x33, 0x44, 0xa2, 0xd6, 0xcc, 0xc9, 0xa2, 0x56, + 0x2d, 0x19, 0xb5, 0x6e, 0xc3, 0x2c, 0xb5, 0xd1, 0xfe, 0xd8, 0xf1, 0x58, 0xc5, 0xc6, 0x4d, 0x5b, + 0xc9, 0xa9, 0xd8, 0xef, 0x7a, 0xa3, 0x1d, 0x3e, 0x55, 0x6d, 0xd3, 0xa5, 0xe2, 0xd3, 0x23, 0x3a, + 0x2a, 0x84, 0x0e, 0x4c, 0x47, 0xf9, 0x27, 0x61, 0x86, 0x8d, 0xb1, 0xde, 0xf7, 0x5d, 0xcd, 0xf6, + 0x76, 0xb1, 0x4b, 0x23, 0x57, 0x4d, 0x6d, 0x12, 0xe0, 0x3d, 0x0e, 0x53, 0x7e, 0x5b, 0x82, 0x25, + 0x5e, 0x40, 0x9e, 0x5c, 0x2f, 0xf2, 0x02, 0x8b, 0xf0, 0xcc, 0xe5, 0x43, 0x4a, 0xb2, 0x4a, 0x81, + 0xd4, 0xa8, 0x9a, 0x91, 0x1a, 0xc5, 0xcb, 0x92, 0xe9, 0x54, 0x59, 0x12, 0x34, 0x19, 0x66, 0x8a, + 0x37, 0x19, 0xd0, 0x02, 0x54, 0x69, 0xae, 0x4c, 0x65, 0x57, 0x57, 0xd9, 0x47, 0x31, 0x86, 0xfe, + 0x59, 0x82, 0x56, 0x0f, 0x6b, 0xee, 0x70, 0x4f, 0xf0, 0xf1, 0xcd, 0x68, 0x53, 0xe6, 0xe5, 0x1c, + 0x11, 0xc7, 0x96, 0x7c, 0x79, 0xba, 0x31, 0x7f, 0x91, 0xa0, 0xf9, 0x5f, 0x64, 0x48, 0x1c, 0xf6, + 0x7a, 0xf4, 0xb0, 0x97, 0x72, 0x0e, 0xab, 0x62, 0xdf, 0x35, 0xf0, 0x3e, 0xfe, 0xd2, 0x1d, 0xf7, + 0xd7, 0x12, 0x74, 0x7b, 0x07, 0xf6, 0x50, 0x65, 0xb6, 0x7c, 0x72, 0x8b, 0xb9, 0x00, 0xad, 0xfd, + 0x58, 0x3e, 0x55, 0xa2, 0x0a, 0xd7, 0xdc, 0x8f, 0x16, 0x5e, 0x2a, 0xc8, 0xa2, 0x17, 0xc4, 0x0f, + 0x2b, 0x5c, 0xeb, 0x2b, 0x59, 0x54, 0x27, 0x88, 0xa3, 0xae, 0x69, 0xd6, 0x8d, 0x03, 0x15, 0x17, + 0xe6, 0x33, 0xe6, 0xa1, 0x53, 0x30, 0xc3, 0x6b, 0x3c, 0x1e, 0x67, 0x99, 0x09, 0xeb, 0x44, 0x3a, + 0x61, 0x97, 0xc2, 0xd0, 0xd3, 0x39, 0x9a, 0x8e, 0xce, 0x41, 0x23, 0x48, 0xc6, 0xf5, 0x94, 0x78, + 0x74, 0x4f, 0xf9, 0xb9, 0x04, 0x4b, 0xef, 0x69, 0xb6, 0xee, 0xec, 0xee, 0x9e, 0x9c, 0x73, 0xeb, + 0x10, 0xcb, 0xd3, 0x8b, 0x76, 0x00, 0xe2, 0xc9, 0xfd, 0x65, 0x98, 0x73, 0x99, 0xf3, 0xd3, 0xe3, + 0xac, 0x2d, 0xab, 0xb2, 0x18, 0x08, 0x58, 0xf6, 0x71, 0x09, 0x10, 0xf1, 0xf7, 0x37, 0x35, 0x53, + 0xb3, 0x87, 0xf8, 0xf8, 0xa4, 0x5f, 0x84, 0x76, 0x2c, 0x4a, 0x05, 0x17, 0x25, 0xd1, 0x30, 0xe5, + 0xa1, 0xdb, 0xd0, 0x1e, 0x30, 0x54, 0x7d, 0x17, 0x6b, 0x9e, 0x63, 0x53, 0xff, 0xd9, 0xce, 0x2e, + 0xf6, 0xef, 0xb9, 0xc6, 0x68, 0x84, 0xdd, 0x75, 0xc7, 0xd6, 0x59, 0x9c, 0x68, 0x0d, 0x04, 0x99, + 0x64, 0x29, 0x11, 0x4e, 0x18, 0xb2, 0x45, 0x91, 0x09, 0x41, 0xcc, 0xa6, 0xac, 0xf0, 0xb0, 0x66, + 0x86, 0x8c, 0x08, 0x1d, 0xae, 0xcc, 0x06, 0x7a, 0xf9, 0xbd, 0x9e, 0x8c, 0x10, 0xaa, 0xfc, 0x44, + 0x02, 0x14, 0x14, 0x2b, 0xb4, 0xf8, 0xa2, 0x1a, 0x96, 0x5c, 0x2a, 0x65, 0xf8, 0xfd, 0xd3, 0x50, + 0xd7, 0xc5, 0x4a, 0x6e, 0x11, 0x21, 0x80, 0xba, 0x61, 0x4a, 0x74, 0x9f, 0xc4, 0x5b, 0xac, 0x8b, + 0x62, 0x80, 0x01, 0xef, 0x50, 0x58, 0x3c, 0x02, 0x57, 0x92, 0x11, 0x38, 0xda, 0xca, 0xa8, 0xc6, + 0x5a, 0x19, 0xca, 0x27, 0x25, 0x90, 0xa9, 0x47, 0x5b, 0x0f, 0xeb, 0xe9, 0x42, 0x44, 0x5f, 0x80, + 0x16, 0xbf, 0x4a, 0x8c, 0x11, 0xde, 0x7c, 0x1c, 0xd9, 0x0c, 0x5d, 0x85, 0x05, 0x36, 0xc9, 0xc5, + 0xde, 0xc4, 0x0c, 0xf3, 0x60, 0x96, 0x94, 0xa2, 0xc7, 0xcc, 0x95, 0x92, 0x21, 0xb1, 0xe2, 0x3e, + 0x2c, 0x8d, 0x4c, 0x67, 0xa0, 0x99, 0xfd, 0xb8, 0x78, 0x98, 0x0c, 0x0b, 0x68, 0xfc, 0x02, 0x5b, + 0xde, 0x8b, 0xca, 0xd0, 0x43, 0x9b, 0xa4, 0x72, 0xc6, 0x8f, 0x82, 0x14, 0x84, 0x77, 0xa9, 0x8b, + 0x64, 0x20, 0x4d, 0xb2, 0x50, 0x7c, 0x29, 0x1f, 0x49, 0x30, 0x9b, 0xe8, 0x46, 0x26, 0xeb, 0x39, + 0x29, 0x5d, 0xcf, 0x5d, 0x87, 0x2a, 0x29, 0x72, 0x98, 0xbf, 0x6b, 0x67, 0xd7, 0x1a, 0xf1, 0x5d, + 0x55, 0xb6, 0x00, 0x5d, 0x81, 0xf9, 0x8c, 0x7b, 0x2b, 0xae, 0x03, 0x28, 0x7d, 0x6d, 0xa5, 0xfc, + 0xa1, 0x02, 0x8d, 0x08, 0x3f, 0x8e, 0x28, 0x45, 0x8b, 0xb4, 0x97, 0x12, 0xc7, 0x2b, 0xa7, 0x8f, + 0x97, 0x73, 0x71, 0x43, 0xf4, 0xce, 0xc2, 0x16, 0x4b, 0xe2, 0x79, 0x45, 0x61, 0x61, 0x8b, 0xa6, + 0xf0, 0x44, 0x25, 0x27, 0x16, 0x2b, 0x22, 0x99, 0x39, 0xcd, 0xd8, 0x13, 0x8b, 0x96, 0x90, 0xf1, + 0xfa, 0x65, 0xe6, 0x90, 0xfa, 0xa5, 0x16, 0xaf, 0x5f, 0x62, 0x76, 0x54, 0x4f, 0xda, 0x51, 0xd1, + 0xea, 0xf0, 0x2a, 0xcc, 0x0f, 0x5d, 0xac, 0xf9, 0x58, 0xbf, 0x79, 0xb0, 0x1e, 0x0c, 0xf1, 0xe4, + 0x27, 0x6b, 0x08, 0xdd, 0x0a, 0xdb, 0x32, 0x4c, 0xca, 0x4d, 0x2a, 0xe5, 0xec, 0xf2, 0x88, 0xcb, + 0x86, 0x09, 0x59, 0xb8, 0x67, 0xfa, 0x95, 0xac, 0x4b, 0x5b, 0xc7, 0xaa, 0x4b, 0xcf, 0x41, 0x43, + 0x44, 0x4f, 0x62, 0xee, 0x6d, 0xe6, 0xf9, 0x84, 0x2f, 0xd0, 0xbd, 0x98, 0x33, 0x98, 0x8d, 0xf7, + 0x35, 0x93, 0xc5, 0xa5, 0x9c, 0x2a, 0x2e, 0x95, 0xdf, 0x95, 0xa1, 0x1d, 0xd6, 0x23, 0x85, 0xbd, + 0x45, 0x91, 0x2b, 0xda, 0x6d, 0x90, 0xc3, 0x98, 0x4b, 0x19, 0x79, 0x68, 0x49, 0x95, 0xbc, 0x13, + 0x98, 0x1d, 0x27, 0xcc, 0x32, 0xd6, 0x75, 0xad, 0x3c, 0x53, 0xd7, 0xf5, 0x84, 0xb7, 0x59, 0xd7, + 0x60, 0x31, 0x88, 0xb3, 0xb1, 0x63, 0xb3, 0x7c, 0x7d, 0x41, 0x0c, 0xee, 0x44, 0x8f, 0x9f, 0x63, + 0xe9, 0x33, 0x79, 0x96, 0x9e, 0x94, 0x74, 0x2d, 0x25, 0xe9, 0xf4, 0xa5, 0x5a, 0x3d, 0xeb, 0x52, + 0xed, 0x3e, 0xcc, 0xd3, 0x56, 0x9b, 0x37, 0x74, 0x8d, 0x01, 0x0e, 0xb2, 0xcf, 0x22, 0x62, 0xed, + 0x42, 0x2d, 0x91, 0xc0, 0x06, 0xdf, 0xca, 0xd7, 0x24, 0x58, 0x4a, 0xef, 0x4b, 0x35, 0x26, 0xf4, + 0x17, 0x52, 0xcc, 0x5f, 0xfc, 0x0f, 0xcc, 0x87, 0xdb, 0xc7, 0x53, 0xe3, 0x9c, 0xe4, 0x2f, 0x83, + 0x70, 0x15, 0x85, 0x7b, 0x08, 0x98, 0xf2, 0x57, 0x29, 0xe8, 0x58, 0x12, 0xd8, 0x88, 0x76, 0x6b, + 0x49, 0x0c, 0x73, 0x6c, 0xd3, 0xb0, 0x83, 0xfa, 0x99, 0x9f, 0x91, 0x01, 0x79, 0xfd, 0xfc, 0x1e, + 0xcc, 0xf2, 0x49, 0x41, 0x28, 0x2a, 0x98, 0x7c, 0xb5, 0xd9, 0xba, 0x20, 0x08, 0x5d, 0x84, 0x36, + 0x6f, 0xa3, 0x0a, 0x7c, 0xe5, 0x8c, 0xe6, 0x2a, 0xfa, 0x4f, 0x90, 0xc5, 0xb4, 0x67, 0x0d, 0x7e, + 0xb3, 0x7c, 0x61, 0x90, 0xc4, 0x7d, 0x55, 0x82, 0x4e, 0x3c, 0x14, 0x46, 0x8e, 0xff, 0xec, 0xa9, + 0xdc, 0xbf, 0xc7, 0x2f, 0xa0, 0x2e, 0x1e, 0x42, 0x4f, 0x88, 0x47, 0x5c, 0x43, 0x6d, 0xd3, 0xcb, + 0x44, 0x52, 0x64, 0x6c, 0x18, 0x9e, 0xef, 0x1a, 0x83, 0xc9, 0x89, 0x9e, 0x19, 0x28, 0x3f, 0x2d, + 0xc1, 0x8b, 0x99, 0x1b, 0x9e, 0xe4, 0xaa, 0x29, 0xaf, 0xa6, 0xbf, 0x09, 0xb5, 0x44, 0x31, 0x72, + 0xe9, 0x90, 0xc3, 0xf3, 0x1e, 0x14, 0x6b, 0x93, 0x88, 0x75, 0x64, 0x8f, 0x40, 0xa7, 0x2b, 0xf9, + 0x7b, 0x70, 0xa5, 0x8d, 0xed, 0x21, 0xd6, 0xa1, 0x1b, 0xd0, 0x64, 0x85, 0x5e, 0x7f, 0xdf, 0xc0, + 0x4f, 0xc4, 0x0d, 0xc9, 0xd9, 0x4c, 0xbf, 0x46, 0xe7, 0x3d, 0x30, 0xf0, 0x13, 0xb5, 0x61, 0x06, + 0xbf, 0x3d, 0xe5, 0xa3, 0x12, 0x40, 0x38, 0x46, 0xaa, 0xcc, 0xd0, 0x60, 0xb8, 0x05, 0x44, 0x20, + 0x24, 0xde, 0xc6, 0x53, 0x3c, 0xf1, 0x89, 0x06, 0x80, 0x44, 0xdc, 0xa3, 0x11, 0x65, 0xac, 0x19, + 0xae, 0xe0, 0xce, 0x1b, 0x87, 0x53, 0x24, 0x18, 0x45, 0x54, 0x7e, 0x87, 0x2c, 0x63, 0x77, 0x11, + 0xb2, 0x97, 0x00, 0xa3, 0xd7, 0x00, 0x8d, 0x5c, 0xe7, 0x89, 0x61, 0x8f, 0xa2, 0x89, 0x3a, 0xcb, + 0xe7, 0xe7, 0xf8, 0x48, 0x98, 0xa9, 0x77, 0xd7, 0x61, 0x31, 0x73, 0xe7, 0x8c, 0xcb, 0x89, 0x85, + 0xe8, 0xe5, 0x44, 0x39, 0x7a, 0xf9, 0xf0, 0x1d, 0x09, 0x50, 0x5a, 0x90, 0xa8, 0x0d, 0xa5, 0xc0, + 0x45, 0x94, 0xb6, 0x36, 0x12, 0x8c, 0x2b, 0xa5, 0x18, 0x77, 0x1a, 0xea, 0x81, 0xf3, 0xe7, 0x96, + 0x1e, 0x02, 0xa2, 0x6c, 0xad, 0xc4, 0xd9, 0x1a, 0x69, 0x71, 0x55, 0x63, 0x2d, 0x2e, 0x65, 0x0f, + 0x50, 0x5a, 0x39, 0xa2, 0x3b, 0x49, 0xf1, 0x9d, 0x8e, 0xa2, 0x30, 0x82, 0xa9, 0x1c, 0xc7, 0xf4, + 0x1b, 0x09, 0x50, 0x18, 0xde, 0x82, 0x7b, 0x8d, 0x22, 0x31, 0xe1, 0x0a, 0xcc, 0xa7, 0x83, 0x9f, + 0x88, 0xf8, 0x28, 0x15, 0xfa, 0xb2, 0xc2, 0x54, 0x39, 0x23, 0x4c, 0xa1, 0x37, 0x03, 0x73, 0x66, + 0xb1, 0xfc, 0x6c, 0x5e, 0x2c, 0x8f, 0x5b, 0xb4, 0xf2, 0x33, 0x09, 0xe6, 0x02, 0x6c, 0xcf, 0x74, + 0x92, 0xa3, 0xef, 0x69, 0x9e, 0x33, 0xe9, 0x3d, 0x98, 0xe1, 0x5d, 0x8b, 0x94, 0xf2, 0x15, 0x49, + 0xdc, 0x17, 0xa0, 0x4a, 0xec, 0x52, 0x94, 0xf8, 0xec, 0x83, 0x68, 0x37, 0xf4, 0x0e, 0xec, 0xe1, + 0x0d, 0xa6, 0x03, 0x57, 0xa1, 0x72, 0xd4, 0xb5, 0x34, 0x99, 0x4d, 0x13, 0x24, 0x3a, 0xb3, 0x00, + 0x5b, 0x62, 0x35, 0x47, 0x39, 0x59, 0x73, 0xe4, 0x3d, 0xf3, 0xfa, 0x95, 0x04, 0xa7, 0x08, 0xaa, + 0x4f, 0x25, 0x3a, 0x14, 0x62, 0x50, 0xc4, 0x72, 0xca, 0x71, 0xcb, 0xb9, 0x0e, 0x33, 0x2c, 0xb9, + 0x17, 0x9e, 0xfa, 0x6c, 0x1e, 0x63, 0x18, 0x1b, 0x55, 0x31, 0x7d, 0xe5, 0x3f, 0xa0, 0x1e, 0xf4, + 0xd1, 0x50, 0x03, 0x66, 0xee, 0xdb, 0xb7, 0x6d, 0xe7, 0x89, 0x2d, 0x4f, 0xa1, 0x19, 0x28, 0xdf, + 0x30, 0x4d, 0x59, 0x42, 0x2d, 0xa8, 0xf7, 0x7c, 0x17, 0x6b, 0x96, 0x61, 0x8f, 0xe4, 0x12, 0x6a, + 0x03, 0xbc, 0x67, 0x78, 0xbe, 0xe3, 0x1a, 0x43, 0xcd, 0x94, 0xcb, 0x2b, 0x1f, 0x42, 0x3b, 0x9e, + 0xdb, 0xa2, 0x26, 0xd4, 0xb6, 0x1d, 0xff, 0xdd, 0xa7, 0x86, 0xe7, 0xcb, 0x53, 0x64, 0xfe, 0xb6, + 0xe3, 0xef, 0xb8, 0xd8, 0xc3, 0xb6, 0x2f, 0x4b, 0x08, 0x60, 0xfa, 0x7d, 0x7b, 0xc3, 0xf0, 0x1e, + 0xc9, 0x25, 0x34, 0xcf, 0xab, 0x53, 0xcd, 0xdc, 0xe2, 0x09, 0xa3, 0x5c, 0x26, 0xcb, 0x83, 0xaf, + 0x0a, 0x92, 0xa1, 0x19, 0x4c, 0xd9, 0xdc, 0xb9, 0x2f, 0x57, 0x51, 0x1d, 0xaa, 0xec, 0xe7, 0xf4, + 0x8a, 0x0e, 0x72, 0xb2, 0xb5, 0x42, 0xf6, 0x64, 0x87, 0x08, 0x40, 0xf2, 0x14, 0x39, 0x19, 0xef, + 0x6d, 0xc9, 0x12, 0x9a, 0x85, 0x46, 0xa4, 0x53, 0x24, 0x97, 0x08, 0x60, 0xd3, 0x1d, 0x0f, 0xb9, + 0xf4, 0x18, 0x09, 0xc4, 0x21, 0x6f, 0x10, 0x4e, 0x54, 0x56, 0x6e, 0x42, 0x4d, 0x24, 0xdd, 0x64, + 0x2a, 0x67, 0x11, 0xf9, 0x94, 0xa7, 0xd0, 0x1c, 0xb4, 0x62, 0x0f, 0xde, 0x64, 0x09, 0x21, 0x68, + 0xc7, 0x1f, 0x62, 0xca, 0xa5, 0x95, 0x35, 0x80, 0xd0, 0x62, 0x08, 0x39, 0x5b, 0xf6, 0xbe, 0x66, + 0x1a, 0x3a, 0xa3, 0x8d, 0x0c, 0x11, 0xee, 0x52, 0xee, 0xb0, 0x1e, 0x89, 0x5c, 0x5a, 0x39, 0x07, + 0x35, 0xa1, 0xcb, 0x04, 0xae, 0x62, 0xcb, 0xd9, 0xc7, 0x4c, 0x32, 0x3d, 0xec, 0xcb, 0xd2, 0xda, + 0xf7, 0x5a, 0x00, 0xac, 0x1b, 0xe2, 0x38, 0xae, 0x8e, 0xc6, 0x80, 0x36, 0xb1, 0x4f, 0x2a, 0x3d, + 0xc7, 0x16, 0x55, 0x9a, 0x87, 0xae, 0xe6, 0x3f, 0x34, 0x4c, 0x4c, 0xe5, 0xe7, 0xef, 0xe6, 0x35, + 0x86, 0x13, 0xd3, 0x95, 0x29, 0x64, 0x51, 0x8c, 0xf7, 0x0c, 0x0b, 0xdf, 0x33, 0x86, 0x8f, 0x82, + 0x36, 0x4a, 0x3e, 0xc6, 0xc4, 0x54, 0x81, 0x31, 0x51, 0x31, 0xf1, 0x8f, 0x9e, 0xef, 0x1a, 0xf6, + 0x48, 0x24, 0x48, 0xca, 0x14, 0x7a, 0x9c, 0x78, 0x58, 0x29, 0x10, 0xae, 0x15, 0x79, 0x4b, 0x79, + 0x3c, 0x94, 0x26, 0xcc, 0x26, 0x5e, 0x61, 0xa3, 0x95, 0xec, 0xe7, 0x3c, 0x59, 0x2f, 0xc6, 0xbb, + 0x97, 0x0b, 0xcd, 0x0d, 0xb0, 0x19, 0xd0, 0x8e, 0xbf, 0x34, 0x46, 0xff, 0x92, 0xb7, 0x41, 0xea, + 0x41, 0x61, 0x77, 0xa5, 0xc8, 0xd4, 0x00, 0xd5, 0x43, 0xa6, 0xa4, 0x47, 0xa1, 0xca, 0x7c, 0xcc, + 0xd9, 0x3d, 0x2c, 0x37, 0x55, 0xa6, 0xd0, 0xff, 0xc1, 0x5c, 0xea, 0xd9, 0x23, 0x7a, 0x35, 0xbb, + 0x1b, 0x9e, 0xfd, 0x3a, 0xf2, 0x28, 0x0c, 0x0f, 0x93, 0x26, 0x96, 0x4f, 0x7d, 0xea, 0x89, 0x70, + 0x71, 0xea, 0x23, 0xdb, 0x1f, 0x46, 0xfd, 0x33, 0x63, 0x98, 0x50, 0xb3, 0x49, 0xf6, 0xe5, 0x5e, + 0xcb, 0x42, 0x91, 0xfb, 0xf6, 0xb2, 0xbb, 0x5a, 0x74, 0x7a, 0x54, 0xbb, 0xe2, 0xcf, 0xfb, 0xb2, + 0x99, 0x96, 0xf9, 0x24, 0x31, 0x5b, 0xbb, 0xb2, 0x5f, 0x0b, 0x2a, 0x53, 0xe8, 0x5e, 0xcc, 0xc5, + 0xa2, 0x4b, 0x79, 0xc2, 0x89, 0x77, 0xeb, 0x8f, 0xe2, 0xdb, 0xff, 0x03, 0x62, 0xb6, 0x63, 0xef, + 0x1a, 0xa3, 0x89, 0xab, 0x31, 0xc5, 0xca, 0x73, 0x37, 0xe9, 0xa9, 0x02, 0xcd, 0xeb, 0xcf, 0xb0, + 0x22, 0x38, 0x52, 0x1f, 0x60, 0x13, 0xfb, 0x77, 0xb1, 0xef, 0x1a, 0x43, 0x2f, 0x79, 0x22, 0xfe, + 0x11, 0x4e, 0x10, 0xa8, 0x5e, 0x39, 0x72, 0x5e, 0x80, 0x60, 0x00, 0x8d, 0x4d, 0xec, 0xf3, 0x0c, + 0xca, 0x43, 0xb9, 0x2b, 0xc5, 0x0c, 0x81, 0x62, 0xf9, 0xe8, 0x89, 0x51, 0x77, 0x96, 0x78, 0xea, + 0x88, 0x72, 0x05, 0x9b, 0x7e, 0x80, 0x99, 0xed, 0xce, 0x72, 0xde, 0x4e, 0x2a, 0x53, 0x6b, 0x3f, + 0x6e, 0x43, 0x9d, 0xc6, 0x27, 0x12, 0x4c, 0xff, 0x19, 0x9e, 0x9e, 0x43, 0x78, 0xfa, 0x00, 0x66, + 0x13, 0x2f, 0xe7, 0xb2, 0xe5, 0x99, 0xfd, 0xbc, 0xae, 0x80, 0x97, 0x8d, 0xbf, 0x6a, 0xcb, 0x76, + 0x18, 0x99, 0x2f, 0xdf, 0x8e, 0xda, 0xfb, 0x01, 0x7b, 0x74, 0x1a, 0x74, 0x9b, 0x5e, 0xc9, 0x2d, + 0x32, 0xe2, 0x97, 0x91, 0x9f, 0xbf, 0xf7, 0x7e, 0xfe, 0xd1, 0xed, 0x03, 0x98, 0x4d, 0xbc, 0xfa, + 0xc8, 0x96, 0x6a, 0xf6, 0xd3, 0x90, 0xa3, 0x76, 0xff, 0x0c, 0xc3, 0x80, 0x0e, 0xf3, 0x19, 0x17, + 0xf2, 0x68, 0x35, 0xaf, 0x3a, 0xc9, 0xbe, 0xb9, 0x3f, 0xfa, 0x40, 0xad, 0x98, 0x29, 0xa1, 0xe5, + 0x3c, 0x22, 0x93, 0x7f, 0xac, 0xe9, 0xbe, 0x5a, 0xec, 0x5f, 0x38, 0xc1, 0x81, 0x7a, 0x30, 0xcd, + 0xde, 0x82, 0xa0, 0x97, 0xb2, 0xfb, 0x69, 0x91, 0x77, 0x22, 0xdd, 0xa3, 0x5e, 0x93, 0x78, 0x13, + 0xd3, 0xf7, 0xe8, 0xa6, 0x55, 0xea, 0x25, 0x51, 0xe6, 0x23, 0xa6, 0xe8, 0x03, 0x8e, 0xee, 0xd1, + 0x6f, 0x36, 0xc4, 0xa6, 0xff, 0xd8, 0xb1, 0xf2, 0x29, 0xcc, 0x67, 0xf4, 0x52, 0x51, 0x5e, 0x4e, + 0x94, 0xd3, 0xc5, 0xed, 0x5e, 0x29, 0x3c, 0x3f, 0xc0, 0xfc, 0xbf, 0x20, 0x27, 0xab, 0x7e, 0x74, + 0x39, 0x4f, 0x9f, 0xb3, 0x70, 0x1e, 0xae, 0xcc, 0x37, 0xdf, 0x78, 0xb8, 0x36, 0x32, 0xfc, 0xbd, + 0xc9, 0x80, 0x8c, 0x5c, 0x61, 0x53, 0x5f, 0x33, 0x1c, 0xfe, 0xeb, 0x8a, 0xe0, 0xff, 0x15, 0xba, + 0xfa, 0x0a, 0x45, 0x35, 0x1e, 0x0c, 0xa6, 0xe9, 0xe7, 0xb5, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, + 0x9f, 0x9d, 0x73, 0xb2, 0x30, 0x3b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/internal/proxy/task.go b/internal/proxy/task.go index 83f15aef68a4d..3863c6d4d7d20 100644 --- a/internal/proxy/task.go +++ b/internal/proxy/task.go @@ -1271,7 +1271,13 @@ func checkTrain(field *schemapb.FieldSchema, indexParams map[string]string) erro return err } - ok := adapter.CheckTrain(indexParams) + ok := adapter.CheckValidDataType(field.GetDataType()) + if !ok { + log.Warn("Field data type don't support the index build type", zap.String("fieldDataType", field.GetDataType().String()), zap.String("indexType", indexType)) + return fmt.Errorf("field data type %s don't support the index build type %s", field.GetDataType().String(), indexType) + } + + ok = adapter.CheckTrain(indexParams) if !ok { log.Warn("Create index with invalid params", zap.Any("index_params", indexParams)) return fmt.Errorf("invalid index params: %v", indexParams) diff --git a/internal/querycoord/global_meta_broker.go b/internal/querycoord/global_meta_broker.go index 9f33fbbdd2333..2c58ecbfd6e8c 100644 --- a/internal/querycoord/global_meta_broker.go +++ b/internal/querycoord/global_meta_broker.go @@ -243,6 +243,7 @@ func (broker *globalMetaBroker) getFullIndexInfos(ctx context.Context, collectio IndexParams: info.IndexParams, IndexFilePaths: info.IndexFilePaths, IndexSize: int64(info.SerializedSize), + IndexVersion: info.IndexVersion, } ret[segmentID] = append(ret[segmentID], indexInfo) diff --git a/internal/querycoord/util.go b/internal/querycoord/util.go index fababf69a40b9..2bc28ee2f6803 100644 --- a/internal/querycoord/util.go +++ b/internal/querycoord/util.go @@ -20,12 +20,13 @@ import ( "context" "sort" + "go.uber.org/zap" + "github.com/milvus-io/milvus/api/milvuspb" "github.com/milvus-io/milvus/internal/log" - "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" + "github.com/milvus-io/milvus/internal/util/funcutil" "github.com/milvus-io/milvus/internal/util/typeutil" - "go.uber.org/zap" ) func getCompareMapFromSlice(sliceData []int64) map[int64]struct{} { @@ -53,33 +54,23 @@ func estimateSegmentSize(segmentLoadInfo *querypb.SegmentLoadInfo) int64 { if FieldIndexInfo, ok := vecFieldID2IndexInfo[fieldID]; ok { segmentSize += FieldIndexInfo.IndexSize } else { - segmentSize += getFieldSizeFromFieldBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } } // get size of state data for _, fieldBinlog := range segmentLoadInfo.Statslogs { - segmentSize += getFieldSizeFromFieldBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } // get size of delete data for _, fieldBinlog := range segmentLoadInfo.Deltalogs { - segmentSize += getFieldSizeFromFieldBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } return segmentSize } -func getFieldSizeFromFieldBinlog(fieldBinlog *datapb.FieldBinlog) int64 { - fieldSize := int64(0) - for _, binlog := range fieldBinlog.Binlogs { - fieldSize += binlog.LogSize - } - - return fieldSize - -} - // syncReplicaSegments syncs the segments distribution of replica to shard leaders // only syncs the segments in shards if not nil func syncReplicaSegments(ctx context.Context, meta Meta, cluster Cluster, replicaID UniqueID, shards ...string) error { diff --git a/internal/querycoordv2/meta/coordinator_broker.go b/internal/querycoordv2/meta/coordinator_broker.go index 835d388a16f0e..cb81743fc5a59 100644 --- a/internal/querycoordv2/meta/coordinator_broker.go +++ b/internal/querycoordv2/meta/coordinator_broker.go @@ -178,6 +178,7 @@ func (broker *CoordinatorBroker) GetIndexInfo(ctx context.Context, collectionID IndexParams: info.GetIndexParams(), IndexFilePaths: info.GetIndexFilePaths(), IndexSize: int64(info.GetSerializedSize()), + IndexVersion: info.GetIndexVersion(), } if len(info.GetIndexFilePaths()) == 0 { diff --git a/internal/querycoordv2/task/executor.go b/internal/querycoordv2/task/executor.go index ce60a57a9d63a..47e41db31ef04 100644 --- a/internal/querycoordv2/task/executor.go +++ b/internal/querycoordv2/task/executor.go @@ -15,7 +15,7 @@ import ( ) const ( - actionTimeout = 10 * time.Second + actionTimeout = 120 * time.Second ) type actionIndex struct { diff --git a/internal/querycoordv2/utils/types.go b/internal/querycoordv2/utils/types.go index bbe32b49820e6..ab3aec8f918e3 100644 --- a/internal/querycoordv2/utils/types.go +++ b/internal/querycoordv2/utils/types.go @@ -8,6 +8,7 @@ import ( "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/internal/querycoordv2/meta" + "github.com/milvus-io/milvus/internal/util/funcutil" ) // WrapStatus wraps status with given error code, message and errors @@ -95,32 +96,23 @@ func calculateSegmentSize(segmentLoadInfo *querypb.SegmentLoadInfo) int64 { if index, ok := fieldIndex[fieldID]; ok { segmentSize += index.IndexSize } else { - segmentSize += getFieldSizeFromBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } } // Get size of state data for _, fieldBinlog := range segmentLoadInfo.Statslogs { - segmentSize += getFieldSizeFromBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } // Get size of delete data for _, fieldBinlog := range segmentLoadInfo.Deltalogs { - segmentSize += getFieldSizeFromBinlog(fieldBinlog) + segmentSize += funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog) } return segmentSize } -func getFieldSizeFromBinlog(fieldBinlog *datapb.FieldBinlog) int64 { - fieldSize := int64(0) - for _, binlog := range fieldBinlog.Binlogs { - fieldSize += binlog.LogSize - } - - return fieldSize -} - func MergeDmChannelInfo(infos []*datapb.VchannelInfo) *meta.DmChannel { var dmChannel *meta.DmChannel diff --git a/internal/querynode/cgo_helper.go b/internal/querynode/cgo_helper.go index 29123eed807a8..a756a542589d1 100644 --- a/internal/querynode/cgo_helper.go +++ b/internal/querynode/cgo_helper.go @@ -17,11 +17,12 @@ package querynode /* -#cgo pkg-config: milvus_segcore +#cgo pkg-config: milvus_segcore milvus_storage #include "segcore/collection_c.h" #include "common/type_c.h" #include "segcore/segment_c.h" +#include "storage/storage_c.h" */ import "C" @@ -80,3 +81,16 @@ func GetCProtoBlob(cProto *C.CProto) []byte { cgoconverter.Extract(lease) return blob } + +func GetLocalUsedSize() (int64, error) { + var availableSize int64 + cSize := C.int64_t(availableSize) + + status := C.GetLocalUsedSize(&cSize) + err := HandleCStatus(&status, "get local used size failed") + if err != nil { + return 0, err + } + + return availableSize, nil +} diff --git a/internal/querynode/load_index_info.go b/internal/querynode/load_index_info.go index 3ba729968bcb9..94e9ad9ae3e62 100644 --- a/internal/querynode/load_index_info.go +++ b/internal/querynode/load_index_info.go @@ -20,7 +20,7 @@ package querynode #cgo pkg-config: milvus_common milvus_segcore #include "segcore/load_index_c.h" -#include "common/vector_index_c.h" +#include "common/binary_set_c.h" */ import "C" @@ -28,9 +28,12 @@ import ( "path/filepath" "unsafe" + "github.com/golang/protobuf/proto" + + "github.com/milvus-io/milvus/api/commonpb" "github.com/milvus-io/milvus/api/schemapb" + "github.com/milvus-io/milvus/internal/proto/indexcgopb" "github.com/milvus-io/milvus/internal/proto/querypb" - "github.com/milvus-io/milvus/internal/util/funcutil" ) // LoadIndexInfo is a wrapper of the underlying C-structure C.CLoadIndexInfo @@ -53,21 +56,20 @@ func deleteLoadIndexInfo(info *LoadIndexInfo) { C.DeleteLoadIndexInfo(info.cLoadIndexInfo) } -func (li *LoadIndexInfo) appendIndexInfo(bytesIndex [][]byte, indexInfo *querypb.FieldIndexInfo, fieldType schemapb.DataType) error { +func (li *LoadIndexInfo) appendLoadIndexInfo(bytesIndex [][]byte, indexInfo *querypb.FieldIndexInfo, collectionID int64, partitionID int64, segmentID int64, fieldType schemapb.DataType) error { fieldID := indexInfo.FieldID - indexParams := funcutil.KeyValuePair2Map(indexInfo.IndexParams) indexPaths := indexInfo.IndexFilePaths - err := li.appendFieldInfo(fieldID, fieldType) + err := li.appendFieldInfo(collectionID, partitionID, segmentID, fieldID, fieldType) if err != nil { return err } - for key, value := range indexParams { - err = li.appendIndexParam(key, value) - if err != nil { - return err - } + + err = li.appendIndexInfo(indexInfo.IndexID, indexInfo.BuildID, indexInfo.IndexVersion, indexInfo.IndexParams) + if err != nil { + return err } + err = li.appendIndexData(bytesIndex, indexPaths) return err } @@ -82,16 +84,56 @@ func (li *LoadIndexInfo) appendIndexParam(indexKey string, indexValue string) er return HandleCStatus(&status, "AppendIndexParam failed") } +func (li *LoadIndexInfo) appendIndexInfo(indexID int64, buildID int64, indexVersion int64, indexParams []*commonpb.KeyValuePair) error { + protoIndexParams := &indexcgopb.IndexParams{ + Params: indexParams, + } + + indexParamsStr := proto.MarshalTextString(protoIndexParams) + indexParamsPointer := C.CString(indexParamsStr) + defer C.free(unsafe.Pointer(indexParamsPointer)) + + cIndexID := C.int64_t(indexID) + cBuildID := C.int64_t(buildID) + cIndexVersion := C.int64_t(indexVersion) + + status := C.AppendIndexInfo(li.cLoadIndexInfo, cIndexID, cBuildID, cIndexVersion, indexParamsPointer) + return HandleCStatus(&status, "AppendIndexInfo failed") +} + +func (li *LoadIndexInfo) cleanLocalData() error { + status := C.CleanLoadedIndex(li.cLoadIndexInfo) + return HandleCStatus(&status, "failed to clean cached data on disk") +} + +func (li *LoadIndexInfo) appendIndexFile(filePath string) error { + cIndexFilePath := C.CString(filePath) + defer C.free(unsafe.Pointer(cIndexFilePath)) + + status := C.AppendIndexFilePath(li.cLoadIndexInfo, cIndexFilePath) + return HandleCStatus(&status, "AppendIndexIFile failed") +} + // appendFieldInfo appends fieldID & fieldType to index -func (li *LoadIndexInfo) appendFieldInfo(fieldID FieldID, fieldType schemapb.DataType) error { +func (li *LoadIndexInfo) appendFieldInfo(collectionID int64, partitionID int64, segmentID int64, fieldID FieldID, fieldType schemapb.DataType) error { + cColID := C.int64_t(collectionID) + cParID := C.int64_t(partitionID) + cSegID := C.int64_t(segmentID) cFieldID := C.int64_t(fieldID) cintDType := uint32(fieldType) - status := C.AppendFieldInfo(li.cLoadIndexInfo, cFieldID, cintDType) + status := C.AppendFieldInfo(li.cLoadIndexInfo, cColID, cParID, cSegID, cFieldID, cintDType) return HandleCStatus(&status, "AppendFieldInfo failed") } // appendIndexData appends binarySet index to cLoadIndexInfo func (li *LoadIndexInfo) appendIndexData(bytesIndex [][]byte, indexKeys []string) error { + for _, indexPath := range indexKeys { + err := li.appendIndexFile(indexPath) + if err != nil { + return err + } + } + var cBinarySet C.CBinarySet status := C.NewBinarySet(&cBinarySet) defer C.DeleteBinarySet(cBinarySet) diff --git a/internal/querynode/load_index_info_test.go b/internal/querynode/load_index_info_test.go index b395dd7fae5f9..5f8ce380cd2f8 100644 --- a/internal/querynode/load_index_info_test.go +++ b/internal/querynode/load_index_info_test.go @@ -19,11 +19,10 @@ package querynode import ( "testing" - "github.com/milvus-io/milvus/api/schemapb" - "github.com/stretchr/testify/assert" "github.com/milvus-io/milvus/api/commonpb" + "github.com/milvus-io/milvus/api/schemapb" "github.com/milvus-io/milvus/internal/proto/querypb" ) @@ -37,6 +36,10 @@ func TestLoadIndexInfo(t *testing.T) { Key: "index_mode", Value: "cpu", }) + indexParams = append(indexParams, &commonpb.KeyValuePair{ + Key: "metric_type", + Value: "L2", + }) indexBytes, err := genIndexBinarySet() assert.NoError(t, err) @@ -53,7 +56,7 @@ func TestLoadIndexInfo(t *testing.T) { } fieldType := schemapb.DataType_FloatVector - err = loadIndexInfo.appendIndexInfo(indexBytes, indexInfo, fieldType) + err = loadIndexInfo.appendLoadIndexInfo(indexBytes, indexInfo, 0, 0, 0, fieldType) assert.NoError(t, err) deleteLoadIndexInfo(loadIndexInfo) diff --git a/internal/querynode/query_node.go b/internal/querynode/query_node.go index 3f81a6bcae855..796dabdeffcf2 100644 --- a/internal/querynode/query_node.go +++ b/internal/querynode/query_node.go @@ -17,11 +17,12 @@ package querynode /* -#cgo pkg-config: milvus_segcore +#cgo pkg-config: milvus_segcore milvus_common #include "segcore/collection_c.h" #include "segcore/segment_c.h" #include "segcore/segcore_init_c.h" +#include "common/init_c.h" */ import "C" @@ -29,7 +30,6 @@ import "C" import ( "context" "fmt" - "github.com/milvus-io/milvus/internal/util/metricsinfo" "os" "path" "path/filepath" @@ -57,6 +57,8 @@ import ( "github.com/milvus-io/milvus/internal/util" "github.com/milvus-io/milvus/internal/util/concurrency" "github.com/milvus-io/milvus/internal/util/dependency" + "github.com/milvus-io/milvus/internal/util/initcore" + "github.com/milvus-io/milvus/internal/util/metricsinfo" "github.com/milvus-io/milvus/internal/util/paramtable" "github.com/milvus-io/milvus/internal/util/sessionutil" "github.com/milvus-io/milvus/internal/util/typeutil" @@ -215,6 +217,9 @@ func (node *QueryNode) InitSegcore() { // override segcore index slice size cIndexSliceSize := C.int64_t(Params.CommonCfg.IndexSliceSize) C.SegcoreSetIndexSliceSize(cIndexSliceSize) + + initcore.InitLocalStorageConfig(&Params) + initcore.InitMinioConfig(&Params) } // Init function init historical and streaming module to manage segments diff --git a/internal/querynode/segment.go b/internal/querynode/segment.go index 2da559e982fe9..10353a4a565dd 100644 --- a/internal/querynode/segment.go +++ b/internal/querynode/segment.go @@ -883,8 +883,13 @@ func (s *Segment) segmentLoadIndexData(bytesIndex [][]byte, indexInfo *querypb.F return err } - err = loadIndexInfo.appendIndexInfo(bytesIndex, indexInfo, fieldType) + err = loadIndexInfo.appendLoadIndexInfo(bytesIndex, indexInfo, s.collectionID, s.partitionID, s.segmentID, fieldType) if err != nil { + if loadIndexInfo.cleanLocalData() != nil { + log.Error("failed to clean cached data on disk after append index failed", + zap.Int64("buildID", indexInfo.BuildID), + zap.Int64("index version", indexInfo.IndexVersion)) + } return err } diff --git a/internal/querynode/segment_loader.go b/internal/querynode/segment_loader.go index af2e43b90f9dc..b1ef77abd53d1 100644 --- a/internal/querynode/segment_loader.go +++ b/internal/querynode/segment_loader.go @@ -42,12 +42,14 @@ import ( "github.com/milvus-io/milvus/internal/types" "github.com/milvus-io/milvus/internal/util/concurrency" "github.com/milvus-io/milvus/internal/util/funcutil" + "github.com/milvus-io/milvus/internal/util/indexparamcheck" "github.com/milvus-io/milvus/internal/util/metricsinfo" "github.com/milvus-io/milvus/internal/util/timerecord" ) const ( requestConcurrencyLevelLimit = 8 + UsedDiskMemoryRatio = 6 ) var ( @@ -251,6 +253,12 @@ func (loader *segmentLoader) loadFiles(segment *Segment, for _, fieldBinlog := range loadInfo.BinlogPaths { fieldID := fieldBinlog.FieldID if indexInfo, ok := fieldID2IndexInfo[fieldID]; ok { + // TODO:: ugly + indexInfo.IndexParams = append(indexInfo.IndexParams, &commonpb.KeyValuePair{ + Key: "count", + Value: strconv.FormatInt(loadInfo.NumOfRows, 10), + }) + fieldInfo := &IndexedFieldInfo{ fieldBinlog: fieldBinlog, indexInfo: indexInfo, @@ -466,35 +474,74 @@ func (loader *segmentLoader) loadFieldIndexData(segment *Segment, indexInfo *que futures := make([]*concurrency.Future, 0, len(indexInfo.IndexFilePaths)) indexCodec := storage.NewIndexFileBinlogCodec() + for _, indexPath := range indexInfo.IndexFilePaths { + // get index params when detecting indexParamPrefix + if path.Base(indexPath) == storage.IndexParamsKey { + indexParamsFuture := loader.ioPool.Submit(func() (interface{}, error) { + log.Debug("load index params file", zap.String("path", indexPath)) + return loader.cm.Read(indexPath) + }) + + indexParamsBlob, err := indexParamsFuture.Await() + if err != nil { + return err + } + + _, indexParams, _, _, err := indexCodec.Deserialize([]*storage.Blob{{Key: storage.IndexParamsKey, Value: indexParamsBlob.([]byte)}}) + if err != nil { + return err + } + + // update index params(dim...) + newIndexParams := funcutil.KeyValuePair2Map(indexInfo.IndexParams) + for key, value := range indexParams { + newIndexParams[key] = value + } + indexInfo.IndexParams = funcutil.Map2KeyValuePair(newIndexParams) + continue + } + + filteredPaths = append(filteredPaths, indexPath) + } + + // 2. use index bytes and index path to update segment + indexInfo.IndexFilePaths = filteredPaths + fieldType, err := loader.getFieldType(segment, indexInfo.FieldID) + if err != nil { + return err + } + + indexParams := funcutil.KeyValuePair2Map(indexInfo.IndexParams) + if indexParams["index_type"] == indexparamcheck.IndexDISKANN { + return segment.segmentLoadIndexData(nil, indexInfo, fieldType) + } + for _, p := range indexInfo.IndexFilePaths { indexPath := p - if path.Base(indexPath) != storage.IndexParamsKey { - indexFuture := loader.cpuPool.Submit(func() (interface{}, error) { - indexBlobFuture := loader.ioPool.Submit(func() (interface{}, error) { - log.Debug("load index file", zap.String("path", indexPath)) - data, err := loader.cm.Read(indexPath) - if err != nil { - log.Warn("failed to load index file", zap.String("path", indexPath), zap.Error(err)) - return nil, err - } - return data, nil - }) - - indexBlob, err := indexBlobFuture.Await() + indexFuture := loader.cpuPool.Submit(func() (interface{}, error) { + indexBlobFuture := loader.ioPool.Submit(func() (interface{}, error) { + log.Debug("load index file", zap.String("path", indexPath)) + data, err := loader.cm.Read(indexPath) if err != nil { + log.Warn("failed to load index file", zap.String("path", indexPath), zap.Error(err)) return nil, err } - - data, _, _, _, err := indexCodec.Deserialize([]*storage.Blob{{Key: path.Base(indexPath), Value: indexBlob.([]byte)}}) - return data, err + return data, nil }) - futures = append(futures, indexFuture) - filteredPaths = append(filteredPaths, indexPath) - } + indexBlob, err := indexBlobFuture.Await() + if err != nil { + return nil, err + } + + data, _, _, _, err := indexCodec.Deserialize([]*storage.Blob{{Key: path.Base(indexPath), Value: indexBlob.([]byte)}}) + return data, err + }) + + futures = append(futures, indexFuture) } - err := concurrency.AwaitAll(futures...) + err = concurrency.AwaitAll(futures...) if err != nil { return err } @@ -504,12 +551,6 @@ func (loader *segmentLoader) loadFieldIndexData(segment *Segment, indexInfo *que indexBuffer = append(indexBuffer, blobs[0].Value) } - // 2. use index bytes and index path to update segment - indexInfo.IndexFilePaths = filteredPaths - fieldType, err := loader.getFieldType(segment, indexInfo.FieldID) - if err != nil { - return err - } return segment.segmentLoadIndexData(indexBuffer, indexInfo, fieldType) } @@ -787,6 +828,20 @@ func JoinIDPath(ids ...UniqueID) string { return path.Join(idStr...) } +func GetStorageSizeByIndexInfo(indexInfo *querypb.FieldIndexInfo) (uint64, uint64, error) { + indexType, err := funcutil.GetAttrByKeyFromRepeatedKV("index_type", indexInfo.IndexParams) + if err != nil { + return 0, 0, fmt.Errorf("index type not exist in index params") + } + if indexType == indexparamcheck.IndexDISKANN { + neededMemSize := indexInfo.IndexSize / UsedDiskMemoryRatio + neededDiskSize := indexInfo.IndexSize - neededMemSize + return uint64(neededMemSize), uint64(neededDiskSize), nil + } + + return uint64(indexInfo.IndexSize), 0, nil +} + func (loader *segmentLoader) checkSegmentSize(collectionID UniqueID, segmentLoadInfos []*querypb.SegmentLoadInfo, concurrency int) error { usedMem := metricsinfo.GetUsedMemoryCount() totalMem := metricsinfo.GetMemoryCount() @@ -800,11 +855,52 @@ func (loader *segmentLoader) checkSegmentSize(collectionID UniqueID, segmentLoad usedMemAfterLoad := usedMem maxSegmentSize := uint64(0) + + localUsedSize, err := GetLocalUsedSize() + if err != nil { + return fmt.Errorf("get local used size failed, collectionID = %d", collectionID) + } + usedLocalSizeAfterLoad := uint64(localUsedSize) + for _, loadInfo := range segmentLoadInfos { - segmentSize := uint64(loadInfo.SegmentSize) - usedMemAfterLoad += segmentSize - if segmentSize > maxSegmentSize { - maxSegmentSize = segmentSize + oldUsedMem := usedMemAfterLoad + vecFieldID2IndexInfo := make(map[int64]*querypb.FieldIndexInfo) + for _, fieldIndexInfo := range loadInfo.IndexInfos { + if fieldIndexInfo.EnableIndex { + fieldID := fieldIndexInfo.FieldID + vecFieldID2IndexInfo[fieldID] = fieldIndexInfo + } + } + + for _, fieldBinlog := range loadInfo.BinlogPaths { + fieldID := fieldBinlog.FieldID + if fieldIndexInfo, ok := vecFieldID2IndexInfo[fieldID]; ok { + neededMemSize, neededDiskSize, err := GetStorageSizeByIndexInfo(fieldIndexInfo) + if err != nil { + log.Error(err.Error(), zap.Int64("collectionID", loadInfo.CollectionID), + zap.Int64("segmentID", loadInfo.SegmentID), + zap.Int64("indexBuildID", fieldIndexInfo.BuildID)) + return err + } + usedMemAfterLoad += neededMemSize + usedLocalSizeAfterLoad += neededDiskSize + } else { + usedMemAfterLoad += uint64(funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog)) + } + } + + // get size of state data + for _, fieldBinlog := range loadInfo.Statslogs { + usedMemAfterLoad += uint64(funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog)) + } + + // get size of delete data + for _, fieldBinlog := range loadInfo.Deltalogs { + usedMemAfterLoad += uint64(funcutil.GetFieldSizeFromFieldBinlog(fieldBinlog)) + } + + if usedMemAfterLoad-oldUsedMem > maxSegmentSize { + maxSegmentSize = usedMemAfterLoad - oldUsedMem } } @@ -813,15 +909,16 @@ func (loader *segmentLoader) checkSegmentSize(collectionID UniqueID, segmentLoad } // when load segment, data will be copied from go memory to c++ memory - loadingUsage := usedMemAfterLoad + uint64( + memLoadingUsage := usedMemAfterLoad + uint64( float64(maxSegmentSize)*float64(concurrency)*Params.QueryNodeCfg.LoadMemoryUsageFactor) - log.Debug("predict memory usage while loading (in MiB)", + log.Debug("predict memory and disk usage while loading (in MiB)", zap.Int64("collectionID", collectionID), zap.Int("concurrency", concurrency), - zap.Uint64("usage", toMB(loadingUsage)), - zap.Uint64("usageAfterLoad", toMB(usedMemAfterLoad))) + zap.Uint64("memUsage", toMB(memLoadingUsage)), + zap.Uint64("memUsageAfterLoad", toMB(usedMemAfterLoad)), + zap.Uint64("diskUsageAfterLoad", toMB(usedLocalSizeAfterLoad))) - if loadingUsage > uint64(float64(totalMem)*Params.QueryNodeCfg.OverloadedMemoryThresholdPercentage) { + if memLoadingUsage > uint64(float64(totalMem)*Params.QueryNodeCfg.OverloadedMemoryThresholdPercentage) { return fmt.Errorf("load segment failed, OOM if load, collectionID = %d, maxSegmentSize = %v MB, concurrency = %d, usedMemAfterLoad = %v MB, totalMem = %v MB, thresholdFactor = %f", collectionID, toMB(maxSegmentSize), @@ -831,6 +928,14 @@ func (loader *segmentLoader) checkSegmentSize(collectionID UniqueID, segmentLoad Params.QueryNodeCfg.OverloadedMemoryThresholdPercentage) } + if usedLocalSizeAfterLoad > uint64(float64(Params.QueryNodeCfg.DiskCapacityLimit)*Params.QueryNodeCfg.MaxDiskUsagePercentage) { + return fmt.Errorf("load segment failed, disk space is not enough, collectionID = %d, usedDiskAfterLoad = %v MB, totalDisk = %v MB, thresholdFactor = %f", + collectionID, + toMB(usedLocalSizeAfterLoad), + toMB(uint64(Params.QueryNodeCfg.DiskCapacityLimit)), + Params.QueryNodeCfg.MaxDiskUsagePercentage) + } + return nil } diff --git a/internal/querynode/task_test.go b/internal/querynode/task_test.go index bedd00f7e7d03..9301a6dd2094c 100644 --- a/internal/querynode/task_test.go +++ b/internal/querynode/task_test.go @@ -21,6 +21,9 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/milvus-io/milvus/api/commonpb" "github.com/milvus-io/milvus/api/schemapb" "github.com/milvus-io/milvus/internal/mq/msgstream" @@ -31,8 +34,6 @@ import ( "github.com/milvus-io/milvus/internal/util/funcutil" "github.com/milvus-io/milvus/internal/util/metricsinfo" "github.com/milvus-io/milvus/internal/util/typeutil" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestTask_watchDmChannelsTask(t *testing.T) { @@ -542,6 +543,11 @@ func TestTask_loadSegmentsTask(t *testing.T) { req: genLoadEmptySegmentsRequest(), node: node, } + binlogs := []*datapb.Binlog{ + { + LogSize: totalRAM, + }, + } task.req.Infos = []*querypb.SegmentLoadInfo{ { SegmentID: defaultSegmentID, @@ -549,6 +555,7 @@ func TestTask_loadSegmentsTask(t *testing.T) { CollectionID: defaultCollectionID, NumOfRows: totalRAM / int64(sizePerRecord), SegmentSize: totalRAM, + BinlogPaths: []*datapb.FieldBinlog{{Binlogs: binlogs}}, }, } // Reach the segment size that would cause OOM diff --git a/internal/util/constant.go b/internal/util/constant.go index 50b33a37820ce..cbd3a80158682 100644 --- a/internal/util/constant.go +++ b/internal/util/constant.go @@ -52,6 +52,11 @@ const ( AnyWord = "*" ) +const ( + // ParamsKeyToParse is the key of the param to build index. + ParamsKeyToParse = "params" +) + var ( DefaultRoles = []string{RoleAdmin, RolePublic} diff --git a/internal/util/funcutil/func.go b/internal/util/funcutil/func.go index 8c4afb0ec8699..6fcf26dd82c28 100644 --- a/internal/util/funcutil/func.go +++ b/internal/util/funcutil/func.go @@ -31,19 +31,18 @@ import ( "strings" "time" - "github.com/milvus-io/milvus/api/milvuspb" - + "github.com/go-basic/ipv4" "go.uber.org/zap" + grpcStatus "google.golang.org/grpc/status" - "github.com/go-basic/ipv4" "github.com/milvus-io/milvus/api/commonpb" + "github.com/milvus-io/milvus/api/milvuspb" "github.com/milvus-io/milvus/api/schemapb" "github.com/milvus-io/milvus/internal/log" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/types" "github.com/milvus-io/milvus/internal/util/retry" - - grpcStatus "google.golang.org/grpc/status" ) // CheckGrpcReady wait for context timeout, or wait 100ms then send nil to targetCh @@ -406,3 +405,12 @@ func DecodeUserRoleCache(cache string) (string, string, error) { role := cache[index+1:] return user, role, nil } + +func GetFieldSizeFromFieldBinlog(fieldBinlog *datapb.FieldBinlog) int64 { + fieldSize := int64(0) + for _, binlog := range fieldBinlog.Binlogs { + fieldSize += binlog.LogSize + } + + return fieldSize +} diff --git a/internal/util/indexcgowrapper/helper.go b/internal/util/indexcgowrapper/helper.go index 4d2ae2a2f89af..a1e251a6199d5 100644 --- a/internal/util/indexcgowrapper/helper.go +++ b/internal/util/indexcgowrapper/helper.go @@ -1,10 +1,11 @@ package indexcgowrapper /* -#cgo pkg-config: milvus_common +#cgo pkg-config: milvus_common milvus_storage #include // free -#include "indexbuilder/index_c.h" +#include "common/binary_set_c.h" +#include "storage/storage_c.h" */ import "C" import ( @@ -50,6 +51,13 @@ func GetBinarySetValue(cBinarySet C.CBinarySet, key string) ([]byte, error) { return value, nil } +func GetBinarySetSize(cBinarySet C.CBinarySet, key string) (int64, error) { + cIndexKey := C.CString(key) + defer C.free(unsafe.Pointer(cIndexKey)) + ret := C.GetBinarySetValueSize(cBinarySet, cIndexKey) + return int64(ret), nil +} + // HandleCStatus deal with the error returned from CGO func HandleCStatus(status *C.CStatus, extraInfo string) error { if status.error_code == 0 { @@ -68,3 +76,16 @@ func HandleCStatus(status *C.CStatus, extraInfo string) error { log.Warn(logMsg) return errors.New(finalMsg) } + +func GetLocalUsedSize() (int64, error) { + var availableSize int64 + cSize := C.int64_t(availableSize) + + status := C.GetLocalUsedSize(&cSize) + err := HandleCStatus(&status, "get local used size failed") + if err != nil { + return 0, err + } + + return availableSize, nil +} diff --git a/internal/util/indexcgowrapper/index.go b/internal/util/indexcgowrapper/index.go index 1ec2d7fd159c7..1a1b693401625 100644 --- a/internal/util/indexcgowrapper/index.go +++ b/internal/util/indexcgowrapper/index.go @@ -28,8 +28,10 @@ type Blob = storage.Blob type CodecIndex interface { Build(*Dataset) error Serialize() ([]*Blob, error) + SerializeDiskIndex() ([]*Blob, error) Load([]*Blob) error Delete() error + CleanLocalData() error } var ( @@ -216,9 +218,47 @@ func (index *CgoIndex) Serialize() ([]*Blob, error) { if err != nil { return nil, err } + size, err := GetBinarySetSize(cBinarySet, key) + if err != nil { + return nil, err + } blob := &Blob{ Key: key, Value: value, + Size: size, + } + ret = append(ret, blob) + } + + return ret, nil +} + +func (index *CgoIndex) SerializeDiskIndex() ([]*Blob, error) { + var cBinarySet C.CBinarySet + + status := C.SerializeIndexToBinarySet(index.indexPtr, &cBinarySet) + defer func() { + if cBinarySet != nil { + C.DeleteBinarySet(cBinarySet) + } + }() + if err := HandleCStatus(&status, "failed to serialize index to binary set"); err != nil { + return nil, err + } + + keys, err := GetBinarySetKeys(cBinarySet) + if err != nil { + return nil, err + } + ret := make([]*Blob, 0) + for _, key := range keys { + size, err := GetBinarySetSize(cBinarySet, key) + if err != nil { + return nil, err + } + blob := &Blob{ + Key: key, + Size: size, } ret = append(ret, blob) } @@ -259,3 +299,8 @@ func (index *CgoIndex) Delete() error { index.close = true return HandleCStatus(&status, "failed to delete index") } + +func (index *CgoIndex) CleanLocalData() error { + status := C.CleanLocalData(index.indexPtr) + return HandleCStatus(&status, "failed to clean cached data on disk") +} diff --git a/internal/util/indexcgowrapper/index_test.go b/internal/util/indexcgowrapper/index_test.go index d0c108d98bbd8..44307d7a934c9 100644 --- a/internal/util/indexcgowrapper/index_test.go +++ b/internal/util/indexcgowrapper/index_test.go @@ -224,7 +224,10 @@ func TestCIndex_Delete(t *testing.T) { } func TestCIndex_Error(t *testing.T) { - indexPtr, err := NewCgoIndex(schemapb.DataType_FloatVector, nil, nil) + indexParams := make(map[string]string) + indexParams["index_type"] = "IVF_FLAT" + indexParams["metric_type"] = "L2" + indexPtr, err := NewCgoIndex(schemapb.DataType_FloatVector, nil, indexParams) assert.Nil(t, err) t.Run("Serialize error", func(t *testing.T) { diff --git a/internal/util/indexparamcheck/conf_adapter.go b/internal/util/indexparamcheck/conf_adapter.go index 2d1f60954b0ac..f0ec88afff2c7 100644 --- a/internal/util/indexparamcheck/conf_adapter.go +++ b/internal/util/indexparamcheck/conf_adapter.go @@ -19,6 +19,7 @@ package indexparamcheck import ( "strconv" + "github.com/milvus-io/milvus/api/schemapb" "github.com/milvus-io/milvus/internal/util/funcutil" ) @@ -58,6 +59,9 @@ const ( // DefaultMaxDim is the largest dimension supported in Milvus DefaultMaxDim = 32768 + DiskAnnMinDim = 1 + DiskAnnMaxDim = 1024 + NgtMinEdgeSize = 1 NgtMaxEdgeSize = 200 @@ -123,6 +127,7 @@ var supportSubQuantizer = []int{96, 64, 56, 48, 40, 32, 28, 24, 20, 16, 12, 8, 4 type ConfAdapter interface { // CheckTrain returns true if the index can be built with the specific index parameters. CheckTrain(map[string]string) bool + CheckValidDataType(dType schemapb.DataType) bool } // BaseConfAdapter checks if a `FLAT` index can be built. @@ -138,6 +143,11 @@ func (adapter *BaseConfAdapter) CheckTrain(params map[string]string) bool { return CheckStrByValues(params, Metric, METRICS) } +// CheckValidDataType check whether the field data type is supported for the index type +func (adapter *BaseConfAdapter) CheckValidDataType(dType schemapb.DataType) bool { + return true +} + func newBaseConfAdapter() *BaseConfAdapter { return &BaseConfAdapter{} } @@ -255,6 +265,7 @@ func newIVFSQConfAdapter() *IVFSQConfAdapter { } type BinIDMAPConfAdapter struct { + BaseConfAdapter } // CheckTrain checks if a binary flat index can be built with the specific parameters. @@ -272,6 +283,7 @@ func newBinIDMAPConfAdapter() *BinIDMAPConfAdapter { // BinIVFConfAdapter checks if a bin IFV index can be built. type BinIVFConfAdapter struct { + BaseConfAdapter } // CheckTrain checks if a binary ivf index can be built with specific parameters. @@ -298,6 +310,7 @@ func newBinIVFConfAdapter() *BinIVFConfAdapter { } type NSGConfAdapter struct { + BaseConfAdapter } // CheckTrain checks if a nsg index can be built with specific parameters. @@ -507,3 +520,26 @@ func (adapter *NGTONNGConfAdapter) CheckTrain(params map[string]string) bool { func newNGTONNGConfAdapter() *NGTONNGConfAdapter { return &NGTONNGConfAdapter{} } + +type DISKANNConfAdapter struct { + BaseConfAdapter +} + +func (adapter *DISKANNConfAdapter) CheckTrain(params map[string]string) bool { + if !CheckIntByRange(params, DIM, DiskAnnMinDim, DiskAnnMaxDim) { + return false + } + return adapter.BaseConfAdapter.CheckTrain(params) +} + +// CheckValidDataType check whether the field data type is supported for the index type +func (adapter *DISKANNConfAdapter) CheckValidDataType(dType schemapb.DataType) bool { + vecDataTypes := []schemapb.DataType{ + schemapb.DataType_FloatVector, + } + return funcutil.SliceContain(vecDataTypes, dType) +} + +func newDISKANNConfAdapter() *DISKANNConfAdapter { + return &DISKANNConfAdapter{} +} diff --git a/internal/util/indexparamcheck/conf_adapter_mgr.go b/internal/util/indexparamcheck/conf_adapter_mgr.go index b8c0d394466ba..51d71f22cabde 100644 --- a/internal/util/indexparamcheck/conf_adapter_mgr.go +++ b/internal/util/indexparamcheck/conf_adapter_mgr.go @@ -60,6 +60,7 @@ func (mgr *ConfAdapterMgrImpl) registerConfAdapter() { mgr.adapters[IndexRHNSWSQ] = newRHNSWSQConfAdapter() mgr.adapters[IndexNGTPANNG] = newNGTPANNGConfAdapter() mgr.adapters[IndexNGTONNG] = newNGTONNGConfAdapter() + mgr.adapters[IndexDISKANN] = newDISKANNConfAdapter() } func newConfAdapterMgrImpl() *ConfAdapterMgrImpl { diff --git a/internal/util/indexparamcheck/index_type.go b/internal/util/indexparamcheck/index_type.go index d32ae4d1bd2d0..99a466d51efc8 100644 --- a/internal/util/indexparamcheck/index_type.go +++ b/internal/util/indexparamcheck/index_type.go @@ -31,4 +31,5 @@ const ( IndexANNOY IndexType = "ANNOY" IndexNGTPANNG IndexType = "NGT_PANNG" IndexNGTONNG IndexType = "NGT_ONNG" + IndexDISKANN IndexType = "DISKANN" ) diff --git a/internal/util/initcore/init_storage_config.go b/internal/util/initcore/init_storage_config.go new file mode 100644 index 0000000000000..65d968e155654 --- /dev/null +++ b/internal/util/initcore/init_storage_config.go @@ -0,0 +1,70 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package initcore + +/* +#cgo pkg-config: milvus_common + +#include +#include +#include "common/init_c.h" +*/ +import "C" +import ( + "os" + "path/filepath" + "strings" + "unsafe" + + "github.com/milvus-io/milvus/internal/util/paramtable" +) + +func InitMinioConfig(params *paramtable.ComponentParam) { + CMinioAddress := C.CString(params.MinioCfg.Address) + C.MinioAddressInit(CMinioAddress) + C.free(unsafe.Pointer(CMinioAddress)) + + CMinioAccessKey := C.CString(params.MinioCfg.AccessKeyID) + C.MinioAccessKeyInit(CMinioAccessKey) + C.free(unsafe.Pointer(CMinioAccessKey)) + + CMinioAccessValue := C.CString(params.MinioCfg.SecretAccessKey) + C.MinioAccessValueInit(CMinioAccessValue) + C.free(unsafe.Pointer(CMinioAccessValue)) + + CUseSSL := C.bool(params.MinioCfg.UseSSL) + C.MinioSSLInit(CUseSSL) + + CUseIam := C.bool(params.MinioCfg.UseIAM) + C.MinioUseIamInit(CUseIam) + + CMinioBucketName := C.CString(strings.TrimLeft(params.MinioCfg.BucketName, "/")) + C.MinioBucketNameInit(CMinioBucketName) + C.free(unsafe.Pointer(CMinioBucketName)) + + CMinioRootPath := C.CString(params.MinioCfg.RootPath) + C.MinioRootPathInit(CMinioRootPath) + C.free(unsafe.Pointer(CMinioRootPath)) +} + +func InitLocalStorageConfig(params *paramtable.ComponentParam) { + b, _ := os.Getwd() + LocalRootPath := filepath.Dir(b) + "/" + filepath.Base(b) + "/" + "data/" + CLocalRootPath := C.CString(LocalRootPath) + C.LocalRootPathInit(CLocalRootPath) + C.free(unsafe.Pointer(CLocalRootPath)) +} diff --git a/internal/util/paramtable/component_param.go b/internal/util/paramtable/component_param.go index f11c0c9d82eb1..66f46fad391aa 100644 --- a/internal/util/paramtable/component_param.go +++ b/internal/util/paramtable/component_param.go @@ -13,6 +13,7 @@ package paramtable import ( "math" + "os" "runtime" "strconv" "strings" @@ -20,8 +21,10 @@ import ( "sync/atomic" "time" - "github.com/milvus-io/milvus/internal/log" + "github.com/shirou/gopsutil/disk" "go.uber.org/zap" + + "github.com/milvus-io/milvus/internal/log" ) const ( @@ -797,6 +800,11 @@ type queryNodeConfig struct { LoadMemoryUsageFactor float64 OverloadedMemoryThresholdPercentage float64 + // enable disk + EnableDisk bool + DiskCapacityLimit int64 + MaxDiskUsagePercentage float64 + // cache limit CacheEnabled bool CacheMemoryLimit int64 @@ -834,6 +842,9 @@ func (p *queryNodeConfig) init(base *BaseTable) { p.initMaxGroupNQ() p.initTopKMergeRatio() p.initCPURatio() + p.initEnableDisk() + p.initDiskCapacity() + p.initMaxDiskUsagePercentage() } // InitAlias initializes an alias for the QueryNode role. @@ -969,6 +980,43 @@ func (p *queryNodeConfig) GetNodeID() UniqueID { return 0 } +func (p *queryNodeConfig) initEnableDisk() { + var err error + enableDisk := p.Base.LoadWithDefault("queryNode.enableDisk", "false") + p.EnableDisk, err = strconv.ParseBool(enableDisk) + if err != nil { + panic(err) + } +} + +func (p *queryNodeConfig) initMaxDiskUsagePercentage() { + maxDiskUsagePercentageStr := p.Base.LoadWithDefault("queryNode.maxDiskUsagePercentage", "95") + maxDiskUsagePercentage, err := strconv.ParseInt(maxDiskUsagePercentageStr, 10, 64) + if err != nil { + panic(err) + } + p.MaxDiskUsagePercentage = float64(maxDiskUsagePercentage) / 100 +} + +func (p *queryNodeConfig) initDiskCapacity() { + diskSizeStr := os.Getenv("LOCAL_STORAGE_SIZE") + if len(diskSizeStr) == 0 { + diskUsage, err := disk.Usage("/") + if err != nil { + panic(err) + } + p.DiskCapacityLimit = int64(diskUsage.Total) + + return + } + + diskSize, err := strconv.ParseInt(diskSizeStr, 10, 64) + if err != nil { + panic(err) + } + p.DiskCapacityLimit = diskSize * 1024 * 1024 * 1024 +} + /////////////////////////////////////////////////////////////////////////////// // --- datacoord --- type dataCoordConfig struct { @@ -1304,12 +1352,20 @@ type indexNodeConfig struct { CreatedTime time.Time UpdatedTime time.Time + + // enable disk + EnableDisk bool + DiskCapacityLimit int64 + MaxDiskUsagePercentage float64 } func (p *indexNodeConfig) init(base *BaseTable) { p.Base = base p.NodeID.Store(UniqueID(0)) p.initBuildParallel() + p.initEnableDisk() + p.initDiskCapacity() + p.initMaxDiskUsagePercentage() } // InitAlias initializes an alias for the IndexNode role. @@ -1332,3 +1388,40 @@ func (p *indexNodeConfig) GetNodeID() UniqueID { } return 0 } + +func (p *indexNodeConfig) initEnableDisk() { + var err error + enableDisk := p.Base.LoadWithDefault("indexNode.enableDisk", "false") + p.EnableDisk, err = strconv.ParseBool(enableDisk) + if err != nil { + panic(err) + } +} + +func (p *indexNodeConfig) initDiskCapacity() { + diskSizeStr := os.Getenv("LOCAL_STORAGE_SIZE") + if len(diskSizeStr) == 0 { + diskUsage, err := disk.Usage("/") + if err != nil { + panic(err) + } + + p.DiskCapacityLimit = int64(diskUsage.Total) + return + } + + diskSize, err := strconv.ParseInt(diskSizeStr, 10, 64) + if err != nil { + panic(err) + } + p.DiskCapacityLimit = diskSize * 1024 * 1024 * 1024 +} + +func (p *indexNodeConfig) initMaxDiskUsagePercentage() { + maxDiskUsagePercentageStr := p.Base.LoadWithDefault("indexNode.maxDiskUsagePercentage", "95") + maxDiskUsagePercentage, err := strconv.ParseInt(maxDiskUsagePercentageStr, 10, 64) + if err != nil { + panic(err) + } + p.MaxDiskUsagePercentage = float64(maxDiskUsagePercentage) / 100 +} diff --git a/scripts/core_build.sh b/scripts/core_build.sh index a4e06028b2dee..2904cdbd09d19 100755 --- a/scripts/core_build.sh +++ b/scripts/core_build.sh @@ -56,6 +56,7 @@ WITH_PROMETHEUS="ON" CUDA_ARCH="DEFAULT" CUSTOM_THIRDPARTY_PATH="" EMBEDDED_MILVUS="OFF" +BUILD_DISK_ANN="OFF" while getopts "p:d:t:s:f:ulrcghzmeb" arg; do case $arg in @@ -101,6 +102,9 @@ while getopts "p:d:t:s:f:ulrcghzmeb" arg; do b) EMBEDDED_MILVUS="ON" ;; + n) + BUILD_DISK_ANN="OFF" + ;; h) # help echo " @@ -156,6 +160,11 @@ if [ "$MSYSTEM" == "MINGW64" ] ; then export OpenBLAS_HOME="$(cygpath -w /mingw64)" fi +# UBUNTU system build diskann index +if [ "$OS_NAME" == "ubuntu20.04" ] ; then + BUILD_DISK_ANN=ON +fi + pushd ${BUILD_OUTPUT_DIR} # Remove make cache since build.sh -l use default variables @@ -198,6 +207,7 @@ ${CMAKE_EXTRA_ARGS} \ -DMILVUS_CUDA_ARCH=${CUDA_ARCH} \ -DCUSTOM_THIRDPARTY_DOWNLOAD_PATH=${CUSTOM_THIRDPARTY_PATH} \ -DEMBEDDED_MILVUS=${EMBEDDED_MILVUS} \ +-DBUILD_DISK_ANN=${BUILD_DISK_ANN} \ ${CPP_SRC_DIR}" echo ${CMAKE_CMD}