diff --git a/ci/jenkinsfile/milvus_build.groovy b/ci/jenkinsfile/milvus_build.groovy index 63c9850d18d85f41e52db5741062f3d9154f00e3..663d2e0f779de6fb67445fa2c8e0460896f2d43a 100644 --- a/ci/jenkinsfile/milvus_build.groovy +++ b/ci/jenkinsfile/milvus_build.groovy @@ -1,5 +1,5 @@ container('milvus-build-env') { - timeout(time: 40, unit: 'MINUTES') { + timeout(time: 120, unit: 'MINUTES') { gitlabCommitStatus(name: 'Build Engine') { dir ("milvus_engine") { try { diff --git a/ci/jenkinsfile/milvus_build_no_ut.groovy b/ci/jenkinsfile/milvus_build_no_ut.groovy index 9947cf2c8482a07d95b2afaffb267c5ca3b0ae2b..cea9c8550bdb6b24f2870e5c5e1937b57ff2a669 100644 --- a/ci/jenkinsfile/milvus_build_no_ut.groovy +++ b/ci/jenkinsfile/milvus_build_no_ut.groovy @@ -1,5 +1,5 @@ container('milvus-build-env') { - timeout(time: 40, unit: 'MINUTES') { + timeout(time: 120, unit: 'MINUTES') { gitlabCommitStatus(name: 'Build Engine') { dir ("milvus_engine") { try { diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 2467013ba94a5a5042efcbee8b6b09e2a98f54b0..bbd58fb28d237d64b49074ff8f8ad9a7426e7981 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -20,6 +20,7 @@ Please mark all change in change log and use the ticket from JIRA. - MS-647 - [monitor] grafana display average cpu-temp - MS-644 - Search crashed with index-type: flat - MS-624 - Search vectors failed if time ranges long enough +- MS-652 - IVFSQH quantization double free ## Improvement - MS-552 - Add and change the easylogging library diff --git a/core/cmake/ThirdPartyPackages.cmake b/core/cmake/ThirdPartyPackages.cmake index 5347aa0acaf5c516ca33c79f0d0f47a2db13a22e..d22556bbf03e9bdf3cc320b41aee292cc63cefd3 100644 --- a/core/cmake/ThirdPartyPackages.cmake +++ b/core/cmake/ThirdPartyPackages.cmake @@ -158,6 +158,10 @@ if(USE_JFROG_CACHE STREQUAL "ON") endif() set(THIRDPARTY_PACKAGE_CACHE "${THIRDPARTY_DIR}/cache") + if(NOT EXISTS ${THIRDPARTY_PACKAGE_CACHE}) + message(STATUS "Will create cached directory: ${THIRDPARTY_PACKAGE_CACHE}") + file(MAKE_DIRECTORY ${THIRDPARTY_PACKAGE_CACHE}) + endif() endif() macro(resolve_dependency DEPENDENCY_NAME) @@ -324,8 +328,8 @@ if(DEFINED ENV{MILVUS_SQLITE_ORM_URL}) set(SQLITE_ORM_SOURCE_URL "$ENV{MILVUS_SQLITE_ORM_URL}") else() set(SQLITE_ORM_SOURCE_URL - "http://192.168.1.105:6060/Test/sqlite_orm/-/archive/master/sqlite_orm-master.zip") -# "https://github.com/fnc12/sqlite_orm/archive/${SQLITE_ORM_VERSION}.zip") +# "http://192.168.1.105:6060/Test/sqlite_orm/-/archive/master/sqlite_orm-master.zip") + "https://github.com/fnc12/sqlite_orm/archive/${SQLITE_ORM_VERSION}.zip") endif() set(SQLITE_ORM_MD5 "ba9a405a8a1421c093aa8ce988ff8598") @@ -370,9 +374,9 @@ if(DEFINED ENV{MILVUS_GRPC_URL}) set(GRPC_SOURCE_URL "$ENV{MILVUS_GRPC_URL}") else() set(GRPC_SOURCE_URL - "http://git.zilliz.tech/kun.yu/grpc/-/archive/master/grpc-master.tar.gz") + "https://github.com/youny626/grpc-milvus/archive/${GRPC_VERSION}.zip") endif() -set(GRPC_MD5 "7ec59ad54c85a12dcbbfede09bf413a9") +set(GRPC_MD5 "0362ba219f59432c530070b5f5c3df73") # ---------------------------------------------------------------------- diff --git a/core/src/index/cmake/ThirdPartyPackagesCore.cmake b/core/src/index/cmake/ThirdPartyPackagesCore.cmake index 12d5c2a71168429d87060e0d1d181f9f74a27018..4c233125bcd0158d22aec158529e91c8b03544f3 100644 --- a/core/src/index/cmake/ThirdPartyPackagesCore.cmake +++ b/core/src/index/cmake/ThirdPartyPackagesCore.cmake @@ -125,6 +125,10 @@ endif() if(USE_JFROG_CACHE STREQUAL "ON") set(JFROG_ARTFACTORY_CACHE_URL "${JFROG_ARTFACTORY_URL}/milvus/thirdparty/cache/${CMAKE_OS_NAME}/${KNOWHERE_BUILD_ARCH}/${BUILD_TYPE}") set(THIRDPARTY_PACKAGE_CACHE "${THIRDPARTY_DIR}/cache") + if(NOT EXISTS ${THIRDPARTY_PACKAGE_CACHE}) + message(STATUS "Will create cached directory: ${THIRDPARTY_PACKAGE_CACHE}") + file(MAKE_DIRECTORY ${THIRDPARTY_PACKAGE_CACHE}) + endif() endif() macro(resolve_dependency DEPENDENCY_NAME) diff --git a/core/src/index/knowhere/knowhere/index/vector_index/IndexIVFSQHybrid.cpp b/core/src/index/knowhere/knowhere/index/vector_index/IndexIVFSQHybrid.cpp index e44d049a1af621ad7afb9efe775b52ae320f6e56..da0ed2283c76a2b309ada3655d4f6fbd465c2093 100644 --- a/core/src/index/knowhere/knowhere/index/vector_index/IndexIVFSQHybrid.cpp +++ b/core/src/index/knowhere/knowhere/index/vector_index/IndexIVFSQHybrid.cpp @@ -27,6 +27,7 @@ namespace knowhere { #ifdef CUSTOMIZATION + IndexModelPtr IVFSQHybrid::Train(const DatasetPtr& dataset, const Config& config) { auto build_cfg = std::dynamic_pointer_cast(config); @@ -79,8 +80,24 @@ IVFSQHybrid::CopyGpuToCpu(const Config& config) { VectorIndexPtr IVFSQHybrid::CopyCpuToGpu(const int64_t& device_id, const Config& config) { - auto p = CopyCpuToGpuWithQuantizer(device_id, config); - return p.first; + if (auto res = FaissGpuResourceMgr::GetInstance().GetRes(device_id)) { + ResScope rs(res, device_id, false); + faiss::gpu::GpuClonerOptions option; + option.allInGpu = true; + + faiss::IndexComposition index_composition; + index_composition.index = index_.get(); + index_composition.quantizer = nullptr; + index_composition.mode = 0; // copy all + + auto gpu_index = faiss::gpu::index_cpu_to_gpu(res->faiss_res.get(), device_id, &index_composition, &option); + + std::shared_ptr device_index = std::shared_ptr(gpu_index); + auto new_idx = std::make_shared(device_index, device_id, res); + return new_idx; + } else { + KNOWHERE_THROW_MSG("CopyCpuToGpu Error, can't get gpu_resource"); + } } void diff --git a/core/src/scheduler/task/SearchTask.cpp b/core/src/scheduler/task/SearchTask.cpp index b5f1599eba269c0ed35b2330a3efc225293a9dc7..b7a1e211d2b1b23dee3f903e0e7e130de1e98efe 100644 --- a/core/src/scheduler/task/SearchTask.cpp +++ b/core/src/scheduler/task/SearchTask.cpp @@ -315,10 +315,10 @@ XSearchTask::MergeTopkArray(std::vector& tar_ids, std::vector& t return; } - std::vector id_buf(nq * topk, -1); - std::vector dist_buf(nq * topk, 0.0); - uint64_t output_k = std::min(topk, tar_input_k + src_input_k); + std::vector id_buf(nq * output_k, -1); + std::vector dist_buf(nq * output_k, 0.0); + uint64_t buf_k, src_k, tar_k; uint64_t src_idx, tar_idx, buf_idx; uint64_t src_input_k_multi_i, tar_input_k_multi_i, buf_k_multi_i; @@ -349,6 +349,7 @@ XSearchTask::MergeTopkArray(std::vector& tar_ids, std::vector& t if (src_k < src_input_k) { while (buf_k < output_k && src_k < src_input_k) { src_idx = src_input_k_multi_i + src_k; + buf_idx = buf_k_multi_i + buf_k; id_buf[buf_idx] = src_ids[src_idx]; dist_buf[buf_idx] = src_distance[src_idx]; src_k++; @@ -356,6 +357,8 @@ XSearchTask::MergeTopkArray(std::vector& tar_ids, std::vector& t } } else { while (buf_k < output_k && tar_k < tar_input_k) { + tar_idx = tar_input_k_multi_i + tar_k; + buf_idx = buf_k_multi_i + buf_k; id_buf[buf_idx] = tar_ids[tar_idx]; dist_buf[buf_idx] = tar_distance[tar_idx]; tar_k++; diff --git a/core/unittest/db/test_search.cpp b/core/unittest/db/test_search.cpp index b0ce9a28b6e407a74af198837d5597584c902ddc..dc393b7a26f1e9f233865c75702eab2b320e8038 100644 --- a/core/unittest/db/test_search.cpp +++ b/core/unittest/db/test_search.cpp @@ -110,87 +110,102 @@ CheckTopkResult(const std::vector& input_ids_1, } // namespace -TEST(DBSearchTest, TOPK_TEST) { - uint64_t NQ = 15; - uint64_t TOP_K = 64; - bool ascending; +void MergeTopkToResultSetTest(uint64_t topk_1, uint64_t topk_2, uint64_t nq, uint64_t topk, bool ascending) { std::vector ids1, ids2; std::vector dist1, dist2; ms::ResultSet result; + BuildResult(ids1, dist1, topk_1, nq, ascending); + BuildResult(ids2, dist2, topk_2, nq, ascending); + ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, topk_1, nq, topk, ascending, result); + ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, topk_2, nq, topk, ascending, result); + CheckTopkResult(ids1, dist1, ids2, dist2, topk, nq, ascending, result); +} + +TEST(DBSearchTest, MERGE_RESULT_SET_TEST) { + uint64_t NQ = 15; + uint64_t TOP_K = 64; /* test1, id1/dist1 valid, id2/dist2 empty */ - ascending = true; - BuildResult(ids1, dist1, TOP_K, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkToResultSetTest(TOP_K, 0, NQ, TOP_K, true); + MergeTopkToResultSetTest(TOP_K, 0, NQ, TOP_K, false); /* test2, id1/dist1 valid, id2/dist2 valid */ - BuildResult(ids2, dist2, TOP_K, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkToResultSetTest(TOP_K, TOP_K, NQ, TOP_K, true); + MergeTopkToResultSetTest(TOP_K, TOP_K, NQ, TOP_K, false); /* test3, id1/dist1 small topk */ - ids1.clear(); - dist1.clear(); - result.clear(); - BuildResult(ids1, dist1, TOP_K/2, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K/2, NQ, TOP_K, ascending, result); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkToResultSetTest(TOP_K/2, TOP_K, NQ, TOP_K, true); + MergeTopkToResultSetTest(TOP_K/2, TOP_K, NQ, TOP_K, false); /* test4, id1/dist1 small topk, id2/dist2 small topk */ - ids2.clear(); - dist2.clear(); - result.clear(); - BuildResult(ids2, dist2, TOP_K/3, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K/2, NQ, TOP_K, ascending, result); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K/3, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); - -///////////////////////////////////////////////////////////////////////////////////////// - ascending = false; - ids1.clear(); - dist1.clear(); - ids2.clear(); - dist2.clear(); - result.clear(); + MergeTopkToResultSetTest(TOP_K/2, TOP_K/3, NQ, TOP_K, true); + MergeTopkToResultSetTest(TOP_K/2, TOP_K/3, NQ, TOP_K, false); +} + +void MergeTopkArrayTest(uint64_t topk_1, uint64_t topk_2, uint64_t nq, uint64_t topk, bool ascending) { + std::vector ids1, ids2; + std::vector dist1, dist2; + ms::ResultSet result; + BuildResult(ids1, dist1, topk_1, nq, ascending); + BuildResult(ids2, dist2, topk_2, nq, ascending); + uint64_t result_topk = std::min(topk, topk_1 + topk_2); + ms::XSearchTask::MergeTopkArray(ids1, dist1, topk_1, ids2, dist2, topk_2, nq, topk, ascending); + if (ids1.size() != result_topk * nq) { + std::cout << ids1.size() << " " << result_topk * nq << std::endl; + } + ASSERT_TRUE(ids1.size() == result_topk * nq); + ASSERT_TRUE(dist1.size() == result_topk * nq); + for (uint64_t i = 0; i < nq; i++) { + for (uint64_t k = 1; k < result_topk; k++) { + if (ascending) { + if (dist1[i * result_topk + k] < dist1[i * result_topk + k - 1]) { + std::cout << dist1[i * result_topk + k - 1] << " " << dist1[i * result_topk + k] << std::endl; + } + ASSERT_TRUE(dist1[i * result_topk + k] >= dist1[i * result_topk + k - 1]); + } else { + if (dist1[i * result_topk + k] > dist1[i * result_topk + k - 1]) { + std::cout << dist1[i * result_topk + k - 1] << " " << dist1[i * result_topk + k] << std::endl; + } + ASSERT_TRUE(dist1[i * result_topk + k] <= dist1[i * result_topk + k - 1]); + } + } + } +} + +TEST(DBSearchTest, MERGE_ARRAY_TEST) { + uint64_t NQ = 15; + uint64_t TOP_K = 64; /* test1, id1/dist1 valid, id2/dist2 empty */ - BuildResult(ids1, dist1, TOP_K, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkArrayTest(TOP_K, 0, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K, 0, NQ, TOP_K, false); + MergeTopkArrayTest(0, TOP_K, NQ, TOP_K, true); + MergeTopkArrayTest(0, TOP_K, NQ, TOP_K, false); /* test2, id1/dist1 valid, id2/dist2 valid */ - BuildResult(ids2, dist2, TOP_K, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkArrayTest(TOP_K, TOP_K, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K, TOP_K, NQ, TOP_K, false); /* test3, id1/dist1 small topk */ - ids1.clear(); - dist1.clear(); - result.clear(); - BuildResult(ids1, dist1, TOP_K/2, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K/2, NQ, TOP_K, ascending, result); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkArrayTest(TOP_K/2, TOP_K, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K/2, TOP_K, NQ, TOP_K, false); + MergeTopkArrayTest(TOP_K, TOP_K/2, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K, TOP_K/2, NQ, TOP_K, false); /* test4, id1/dist1 small topk, id2/dist2 small topk */ - ids2.clear(); - dist2.clear(); - result.clear(); - BuildResult(ids2, dist2, TOP_K/3, NQ, ascending); - ms::XSearchTask::MergeTopkToResultSet(ids1, dist1, TOP_K/2, NQ, TOP_K, ascending, result); - ms::XSearchTask::MergeTopkToResultSet(ids2, dist2, TOP_K/3, NQ, TOP_K, ascending, result); - CheckTopkResult(ids1, dist1, ids2, dist2, TOP_K, NQ, ascending, result); + MergeTopkArrayTest(TOP_K/2, TOP_K/3, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K/2, TOP_K/3, NQ, TOP_K, false); + MergeTopkArrayTest(TOP_K/3, TOP_K/2, NQ, TOP_K, true); + MergeTopkArrayTest(TOP_K/3, TOP_K/2, NQ, TOP_K, false); } TEST(DBSearchTest, REDUCE_PERF_TEST) { int32_t index_file_num = 478; /* sift1B dataset, index files num */ bool ascending = true; - std::vector thread_vec = {4, 8, 11}; - std::vector nq_vec = {1, 10, 100, 1000}; - std::vector topk_vec = {1, 4, 16, 64, 256, 1024}; + std::vector thread_vec = {4, 8}; + std::vector nq_vec = {1, 10, 100}; + std::vector topk_vec = {1, 4, 16, 64}; int32_t NQ = nq_vec[nq_vec.size()-1]; int32_t TOPK = topk_vec[topk_vec.size()-1];