ExecutionEngineImpl.cpp 35.0 KB
Newer Older
1
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
J
jinhai 已提交
2
//
3 4
// 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
J
jinhai 已提交
5
//
6 7 8 9 10
// 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.
J
jinhai 已提交
11

S
starlord 已提交
12
#include "db/engine/ExecutionEngineImpl.h"
T
Tinkerrr 已提交
13

14
#include <faiss/utils/ConcurrentBitset.h>
S
shengjh 已提交
15
#include <fiu-local.h>
16

T
Tinkerrr 已提交
17 18 19 20
#include <stdexcept>
#include <utility>
#include <vector>

S
starlord 已提交
21
#include "cache/CpuCacheMgr.h"
S
starlord 已提交
22
#include "cache/GpuCacheMgr.h"
23
#include "config/Config.h"
24
#include "db/Utils.h"
C
Cai Yudong 已提交
25
#include "index/archive/VecIndex.h"
X
xiaojun.lin 已提交
26
#include "knowhere/common/Config.h"
C
Cai Yudong 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40
#include "knowhere/index/vector_index/ConfAdapter.h"
#include "knowhere/index/vector_index/ConfAdapterMgr.h"
#include "knowhere/index/vector_index/IndexBinaryIDMAP.h"
#include "knowhere/index/vector_index/IndexIDMAP.h"
#include "knowhere/index/vector_index/VecIndex.h"
#include "knowhere/index/vector_index/VecIndexFactory.h"
#include "knowhere/index/vector_index/adapter/VectorAdapter.h"
#ifdef MILVUS_GPU_VERSION
#include "knowhere/index/vector_index/gpu/GPUIndex.h"
#include "knowhere/index/vector_index/gpu/IndexIVFSQHybrid.h"
#include "knowhere/index/vector_index/gpu/Quantizer.h"
#include "knowhere/index/vector_index/helpers/Cloner.h"
#endif
#include "knowhere/index/vector_index/helpers/IndexParameter.h"
S
starlord 已提交
41
#include "metrics/Metrics.h"
X
xiaojun.lin 已提交
42
#include "scheduler/Utils.h"
J
jinhai 已提交
43
#include "utils/CommonUtil.h"
S
starlord 已提交
44
#include "utils/Exception.h"
S
starlord 已提交
45
#include "utils/Log.h"
C
Cai Yudong 已提交
46
#include "utils/Status.h"
47
#include "utils/TimeRecorder.h"
G
groot 已提交
48
#include "utils/ValidationUtil.h"
X
xj.lin 已提交
49

S
starlord 已提交
50 51 52
namespace milvus {
namespace engine {

G
groot 已提交
53 54 55
namespace {

Status
56
MappingMetricType(MetricType metric_type, milvus::json& conf) {
G
groot 已提交
57 58
    switch (metric_type) {
        case MetricType::IP:
59
            conf[knowhere::Metric::TYPE] = knowhere::Metric::IP;
G
groot 已提交
60 61
            break;
        case MetricType::L2:
62
            conf[knowhere::Metric::TYPE] = knowhere::Metric::L2;
G
groot 已提交
63 64
            break;
        case MetricType::HAMMING:
65
            conf[knowhere::Metric::TYPE] = knowhere::Metric::HAMMING;
G
groot 已提交
66 67
            break;
        case MetricType::JACCARD:
68
            conf[knowhere::Metric::TYPE] = knowhere::Metric::JACCARD;
G
groot 已提交
69 70
            break;
        case MetricType::TANIMOTO:
71
            conf[knowhere::Metric::TYPE] = knowhere::Metric::TANIMOTO;
G
groot 已提交
72
            break;
73 74 75 76 77 78
        case MetricType::SUBSTRUCTURE:
            conf[knowhere::Metric::TYPE] = knowhere::Metric::SUBSTRUCTURE;
            break;
        case MetricType::SUPERSTRUCTURE:
            conf[knowhere::Metric::TYPE] = knowhere::Metric::SUPERSTRUCTURE;
            break;
G
groot 已提交
79 80 81 82 83 84 85 86
        default:
            return Status(DB_ERROR, "Unsupported metric type");
    }

    return Status::OK();
}

bool
C
Cai Yudong 已提交
87 88
IsBinaryIndexType(knowhere::IndexType type) {
    return type == knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP || type == knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT;
G
groot 已提交
89 90 91 92
}

}  // namespace

C
Cai Yudong 已提交
93
#ifdef MILVUS_GPU_VERSION
W
wxyu 已提交
94 95
class CachedQuantizer : public cache::DataObj {
 public:
W
wxyu 已提交
96 97
    explicit CachedQuantizer(knowhere::QuantizerPtr data) : data_(std::move(data)) {
    }
W
wxyu 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111

    knowhere::QuantizerPtr
    Data() {
        return data_;
    }

    int64_t
    Size() override {
        return data_->size;
    }

 private:
    knowhere::QuantizerPtr data_;
};
C
Cai Yudong 已提交
112
#endif
W
wxyu 已提交
113

S
starlord 已提交
114
ExecutionEngineImpl::ExecutionEngineImpl(uint16_t dimension, const std::string& location, EngineType index_type,
115 116 117 118 119 120
                                         MetricType metric_type, const milvus::json& index_params)
    : location_(location),
      dim_(dimension),
      index_type_(index_type),
      metric_type_(metric_type),
      index_params_(index_params) {
121 122
    EngineType tmp_index_type =
        utils::IsBinaryMetricType((int32_t)metric_type) ? EngineType::FAISS_BIN_IDMAP : EngineType::FAISS_IDMAP;
G
groot 已提交
123
    index_ = CreatetVecIndex(tmp_index_type);
124
    if (!index_) {
125
        throw Exception(DB_ERROR, "Unsupported index type");
126
    }
X
xj.lin 已提交
127

128 129 130 131 132
    milvus::json conf = index_params;
    conf[knowhere::meta::DEVICEID] = gpu_num_;
    conf[knowhere::meta::DIM] = dimension;
    MappingMetricType(metric_type, conf);
    ENGINE_LOG_DEBUG << "Index params: " << conf.dump();
C
Cai Yudong 已提交
133 134
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckTrain(conf, index_->index_mode())) {
135 136
        throw Exception(DB_ERROR, "Illegal index params");
    }
X
xiaojun.lin 已提交
137

C
Cai Yudong 已提交
138 139 140 141 142
    fiu_do_on("ExecutionEngineImpl.throw_exception", throw Exception(DB_ERROR, ""));
    if (auto bf_index = std::dynamic_pointer_cast<knowhere::IDMAP>(index_)) {
        bf_index->Train(knowhere::DatasetPtr(), conf);
    } else if (auto bf_bin_index = std::dynamic_pointer_cast<knowhere::BinaryIDMAP>(index_)) {
        bf_bin_index->Train(knowhere::DatasetPtr(), conf);
143
    }
S
starlord 已提交
144 145
}

C
Cai Yudong 已提交
146 147 148
ExecutionEngineImpl::ExecutionEngineImpl(knowhere::VecIndexPtr index, const std::string& location,
                                         EngineType index_type, MetricType metric_type,
                                         const milvus::json& index_params)
149 150 151 152 153
    : index_(std::move(index)),
      location_(location),
      index_type_(index_type),
      metric_type_(metric_type),
      index_params_(index_params) {
X
xj.lin 已提交
154
}
S
starlord 已提交
155

C
Cai Yudong 已提交
156
knowhere::VecIndexPtr
S
starlord 已提交
157
ExecutionEngineImpl::CreatetVecIndex(EngineType type) {
C
Cai Yudong 已提交
158 159
    knowhere::VecIndexFactory& vec_index_factory = knowhere::VecIndexFactory::GetInstance();
    knowhere::IndexMode mode = knowhere::IndexMode::MODE_CPU;
Y
yudong.cai 已提交
160
#ifdef MILVUS_GPU_VERSION
161 162 163
    server::Config& config = server::Config::GetInstance();
    bool gpu_resource_enable = true;
    config.GetGpuResourceConfigEnable(gpu_resource_enable);
S
shengjh 已提交
164
    fiu_do_on("ExecutionEngineImpl.CreatetVecIndex.gpu_res_disabled", gpu_resource_enable = false);
C
Cai Yudong 已提交
165 166 167
    if (gpu_resource_enable) {
        mode = knowhere::IndexMode::MODE_GPU;
    }
Y
yudong.cai 已提交
168
#endif
S
shengjh 已提交
169

C
Cai Yudong 已提交
170 171
    fiu_do_on("ExecutionEngineImpl.CreateVecIndex.invalid_type", type = EngineType::INVALID);
    knowhere::VecIndexPtr index = nullptr;
X
xj.lin 已提交
172 173
    switch (type) {
        case EngineType::FAISS_IDMAP: {
C
Cai Yudong 已提交
174
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IDMAP, mode);
S
starlord 已提交
175 176
            break;
        }
J
jinhai 已提交
177
        case EngineType::FAISS_IVFFLAT: {
C
Cai Yudong 已提交
178
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IVFFLAT, mode);
S
starlord 已提交
179 180
            break;
        }
C
Cai Yudong 已提交
181 182
        case EngineType::FAISS_PQ: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IVFPQ, mode);
S
starlord 已提交
183 184
            break;
        }
C
Cai Yudong 已提交
185 186
        case EngineType::FAISS_IVFSQ8: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IVFSQ8, mode);
X
xj.lin 已提交
187 188
            break;
        }
189
#ifdef MILVUS_GPU_VERSION
W
wxyu 已提交
190
        case EngineType::FAISS_IVFSQ8H: {
C
Cai Yudong 已提交
191
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IVFSQ8H, mode);
W
wxyu 已提交
192 193
            break;
        }
Y
Yukikaze-CZR 已提交
194
#endif
C
Cai Yudong 已提交
195 196
        case EngineType::FAISS_BIN_IDMAP: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP, mode);
Z
zirui.chen 已提交
197 198
            break;
        }
C
Cai Yudong 已提交
199 200
        case EngineType::FAISS_BIN_IVFFLAT: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_BIN_IVFFLAT, mode);
201 202
            break;
        }
C
Cai Yudong 已提交
203 204
        case EngineType::NSG_MIX: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_NSG, mode);
205 206
            break;
        }
C
Cai Yudong 已提交
207 208
        case EngineType::SPTAG_KDT: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_SPTAG_KDT_RNT, mode);
T
Tinkerrr 已提交
209 210
            break;
        }
C
Cai Yudong 已提交
211 212
        case EngineType::SPTAG_BKT: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_SPTAG_BKT_RNT, mode);
G
groot 已提交
213 214
            break;
        }
C
Cai Yudong 已提交
215 216
        case EngineType::HNSW: {
            index = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_HNSW, mode);
G
groot 已提交
217 218
            break;
        }
X
xj.lin 已提交
219
        default: {
C
Cai Yudong 已提交
220
            ENGINE_LOG_ERROR << "Unsupported index type " << (int)type;
S
starlord 已提交
221 222 223
            return nullptr;
        }
    }
C
Cai Yudong 已提交
224 225 226 227 228
    if (index == nullptr) {
        std::string err_msg = "Invalid index type " + std::to_string((int)type) + " mod " + std::to_string((int)mode);
        ENGINE_LOG_ERROR << err_msg;
        throw Exception(DB_ERROR, err_msg);
    }
X
xj.lin 已提交
229
    return index;
S
starlord 已提交
230 231
}

232
void
W
wxyu 已提交
233
ExecutionEngineImpl::HybridLoad() const {
C
Cai Yudong 已提交
234 235 236 237
#ifdef MILVUS_GPU_VERSION
    auto hybrid_index = std::dynamic_pointer_cast<knowhere::IVFSQHybrid>(index_);
    if (hybrid_index == nullptr) {
        ENGINE_LOG_WARNING << "HybridLoad only support with IVFSQHybrid";
W
update  
wxyu 已提交
238 239 240
        return;
    }

W
wxyu 已提交
241
    const std::string key = location_ + ".quantizer";
242 243

    server::Config& config = server::Config::GetInstance();
Y
yudong.cai 已提交
244
    std::vector<int64_t> gpus;
245 246 247 248 249
    Status s = config.GetGpuResourceConfigSearchResources(gpus);
    if (!s.ok()) {
        ENGINE_LOG_ERROR << s.message();
        return;
    }
W
wxyu 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

    // cache hit
    {
        const int64_t NOT_FOUND = -1;
        int64_t device_id = NOT_FOUND;
        knowhere::QuantizerPtr quantizer = nullptr;

        for (auto& gpu : gpus) {
            auto cache = cache::GpuCacheMgr::GetInstance(gpu);
            if (auto cached_quantizer = cache->GetIndex(key)) {
                device_id = gpu;
                quantizer = std::static_pointer_cast<CachedQuantizer>(cached_quantizer)->Data();
            }
        }

        if (device_id != NOT_FOUND) {
C
Cai Yudong 已提交
266
            hybrid_index->SetQuantizer(quantizer);
W
wxyu 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
            return;
        }
    }

    // cache miss
    {
        std::vector<int64_t> all_free_mem;
        for (auto& gpu : gpus) {
            auto cache = cache::GpuCacheMgr::GetInstance(gpu);
            auto free_mem = cache->CacheCapacity() - cache->CacheUsage();
            all_free_mem.push_back(free_mem);
        }

        auto max_e = std::max_element(all_free_mem.begin(), all_free_mem.end());
        auto best_index = std::distance(all_free_mem.begin(), max_e);
        auto best_device_id = gpus[best_index];

284
        milvus::json quantizer_conf{{knowhere::meta::DEVICEID, best_device_id}, {"mode", 1}};
C
Cai Yudong 已提交
285
        auto quantizer = hybrid_index->LoadQuantizer(quantizer_conf);
286
        ENGINE_LOG_DEBUG << "Quantizer params: " << quantizer_conf.dump();
W
add log  
wxyu 已提交
287 288 289
        if (quantizer == nullptr) {
            ENGINE_LOG_ERROR << "quantizer is nullptr";
        }
C
Cai Yudong 已提交
290
        hybrid_index->SetQuantizer(quantizer);
W
wxyu 已提交
291 292 293
        auto cache_quantizer = std::make_shared<CachedQuantizer>(quantizer);
        cache::GpuCacheMgr::GetInstance(best_device_id)->InsertItem(key, cache_quantizer);
    }
G
groot 已提交
294
#endif
W
wxyu 已提交
295 296 297 298
}

void
ExecutionEngineImpl::HybridUnset() const {
C
Cai Yudong 已提交
299 300 301
#ifdef MILVUS_GPU_VERSION
    auto hybrid_index = std::dynamic_pointer_cast<knowhere::IVFSQHybrid>(index_);
    if (hybrid_index == nullptr) {
W
update  
wxyu 已提交
302 303
        return;
    }
C
Cai Yudong 已提交
304 305
    hybrid_index->UnsetQuantizer();
#endif
306 307
}

S
starlord 已提交
308
Status
S
starlord 已提交
309
ExecutionEngineImpl::AddWithIds(int64_t n, const float* xdata, const int64_t* xids) {
C
Cai Yudong 已提交
310 311 312
    auto dataset = knowhere::GenDatasetWithIds(n, index_->Dim(), xdata, xids);
    index_->Add(dataset, knowhere::Config());
    return Status::OK();
S
starlord 已提交
313 314
}

G
groot 已提交
315 316
Status
ExecutionEngineImpl::AddWithIds(int64_t n, const uint8_t* xdata, const int64_t* xids) {
C
Cai Yudong 已提交
317 318 319
    auto dataset = knowhere::GenDatasetWithIds(n, index_->Dim(), xdata, xids);
    index_->Add(dataset, knowhere::Config());
    return Status::OK();
G
groot 已提交
320 321
}

S
starlord 已提交
322 323 324
size_t
ExecutionEngineImpl::Count() const {
    if (index_ == nullptr) {
S
starlord 已提交
325
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, return count 0";
S
starlord 已提交
326 327
        return 0;
    }
X
xj.lin 已提交
328
    return index_->Count();
S
starlord 已提交
329 330
}

S
starlord 已提交
331 332 333
size_t
ExecutionEngineImpl::Dimension() const {
    if (index_ == nullptr) {
S
starlord 已提交
334
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, return dimension " << dim_;
S
starlord 已提交
335 336
        return dim_;
    }
C
Cai Yudong 已提交
337
    return index_->Dim();
S
starlord 已提交
338 339
}

S
starlord 已提交
340
size_t
341 342 343 344 345 346
ExecutionEngineImpl::Size() const {
    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, return size 0";
        return 0;
    }
    return index_->Size();
S
starlord 已提交
347 348
}

S
starlord 已提交
349 350
Status
ExecutionEngineImpl::Serialize() {
351
    auto status = write_index(index_, location_);
352 353 354

    // here we reset index size by file size,
    // since some index type(such as SQ8) data size become smaller after serialized
C
Cai Yudong 已提交
355
    index_->SetIndexSize(server::CommonUtil::GetFileSize(location_));
G
add log  
groot 已提交
356
    ENGINE_LOG_DEBUG << "Finish serialize index file: " << location_ << " size: " << index_->Size();
357

G
groot 已提交
358 359 360 361 362
    if (index_->Size() == 0) {
        std::string msg = "Failed to serialize file: " + location_ + " reason: out of disk space or memory";
        status = Status(DB_ERROR, msg);
    }

363
    return status;
S
starlord 已提交
364 365
}

366 367 368 369
Status
ExecutionEngineImpl::Load(bool to_cache) {
    // TODO(zhiru): refactor

C
Cai Yudong 已提交
370
    index_ = std::static_pointer_cast<knowhere::VecIndex>(cache::CpuCacheMgr::GetInstance()->GetIndex(location_));
371 372 373 374 375
    bool already_in_cache = (index_ != nullptr);
    if (!already_in_cache) {
        std::string segment_dir;
        utils::GetParentPath(location_, segment_dir);
        auto segment_reader_ptr = std::make_shared<segment::SegmentReader>(segment_dir);
C
Cai Yudong 已提交
376
        knowhere::VecIndexFactory& vec_index_factory = knowhere::VecIndexFactory::GetInstance();
377

378
        if (utils::IsRawIndexType((int32_t)index_type_)) {
C
Cai Yudong 已提交
379 380 381 382 383
            if (index_type_ == EngineType::FAISS_IDMAP) {
                index_ = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_IDMAP);
            } else {
                index_ = vec_index_factory.CreateVecIndex(knowhere::IndexEnum::INDEX_FAISS_BIN_IDMAP);
            }
384 385
            milvus::json conf{{knowhere::meta::DEVICEID, gpu_num_}, {knowhere::meta::DIM, dim_}};
            MappingMetricType(metric_type_, conf);
C
Cai Yudong 已提交
386
            auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
387
            ENGINE_LOG_DEBUG << "Index params: " << conf.dump();
C
Cai Yudong 已提交
388
            if (!adapter->CheckTrain(conf, index_->index_mode())) {
389 390
                throw Exception(DB_ERROR, "Illegal index params");
            }
391

392
            auto status = segment_reader_ptr->Load();
393 394 395 396 397 398 399 400 401 402 403 404 405
            if (!status.ok()) {
                std::string msg = "Failed to load segment from " + location_;
                ENGINE_LOG_ERROR << msg;
                return Status(DB_ERROR, msg);
            }

            segment::SegmentPtr segment_ptr;
            segment_reader_ptr->GetSegment(segment_ptr);
            auto& vectors = segment_ptr->vectors_ptr_;
            auto& deleted_docs = segment_ptr->deleted_docs_ptr_->GetDeletedDocs();

            auto vectors_uids = vectors->GetUids();
            index_->SetUids(vectors_uids);
406
            ENGINE_LOG_DEBUG << "set uids " << index_->GetUids().size() << " for index " << location_;
407 408 409 410 411 412 413 414 415 416 417

            auto vectors_data = vectors->GetData();

            faiss::ConcurrentBitsetPtr concurrent_bitset_ptr =
                std::make_shared<faiss::ConcurrentBitset>(vectors->GetCount());
            for (auto& offset : deleted_docs) {
                if (!concurrent_bitset_ptr->test(offset)) {
                    concurrent_bitset_ptr->set(offset);
                }
            }

C
Cai Yudong 已提交
418
            auto dataset = knowhere::GenDataset(vectors->GetCount(), this->dim_, vectors_data.data());
419
            if (index_type_ == EngineType::FAISS_IDMAP) {
C
Cai Yudong 已提交
420 421 422 423
                auto bf_index = std::static_pointer_cast<knowhere::IDMAP>(index_);
                bf_index->Train(knowhere::DatasetPtr(), conf);
                bf_index->AddWithoutIds(dataset, conf);
                bf_index->SetBlacklist(concurrent_bitset_ptr);
424
            } else if (index_type_ == EngineType::FAISS_BIN_IDMAP) {
C
Cai Yudong 已提交
425 426 427 428
                auto bin_bf_index = std::static_pointer_cast<knowhere::BinaryIDMAP>(index_);
                bin_bf_index->Train(knowhere::DatasetPtr(), conf);
                bin_bf_index->AddWithoutIds(dataset, conf);
                bin_bf_index->SetBlacklist(concurrent_bitset_ptr);
429
            }
430

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
            ENGINE_LOG_DEBUG << "Finished loading raw data from segment " << segment_dir;
        } else {
            try {
                index_ = read_index(location_);

                if (index_ == nullptr) {
                    std::string msg = "Failed to load index from " + location_;
                    ENGINE_LOG_ERROR << msg;
                    return Status(DB_ERROR, msg);
                } else {
                    segment::DeletedDocsPtr deleted_docs_ptr;
                    auto status = segment_reader_ptr->LoadDeletedDocs(deleted_docs_ptr);
                    if (!status.ok()) {
                        std::string msg = "Failed to load deleted docs from " + location_;
                        ENGINE_LOG_ERROR << msg;
                        return Status(DB_ERROR, msg);
                    }
                    auto& deleted_docs = deleted_docs_ptr->GetDeletedDocs();

                    faiss::ConcurrentBitsetPtr concurrent_bitset_ptr =
                        std::make_shared<faiss::ConcurrentBitset>(index_->Count());
                    for (auto& offset : deleted_docs) {
                        if (!concurrent_bitset_ptr->test(offset)) {
                            concurrent_bitset_ptr->set(offset);
                        }
                    }

                    index_->SetBlacklist(concurrent_bitset_ptr);

                    std::vector<segment::doc_id_t> uids;
                    segment_reader_ptr->LoadUids(uids);
                    index_->SetUids(uids);
463
                    ENGINE_LOG_DEBUG << "set uids " << index_->GetUids().size() << " for index " << location_;
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

                    ENGINE_LOG_DEBUG << "Finished loading index file from segment " << segment_dir;
                }
            } catch (std::exception& e) {
                ENGINE_LOG_ERROR << e.what();
                return Status(DB_ERROR, e.what());
            }
        }
    }

    if (!already_in_cache && to_cache) {
        Cache();
    }
    return Status::OK();
}  // namespace engine
X
xj.lin 已提交
479

S
starlord 已提交
480
Status
W
wxyu 已提交
481
ExecutionEngineImpl::CopyToGpu(uint64_t device_id, bool hybrid) {
X
xiaojun.lin 已提交
482
#if 0
W
wxyu 已提交
483
    if (hybrid) {
X
xiaojun.lin 已提交
484
        const std::string key = location_ + ".quantizer";
W
wxyu 已提交
485
        std::vector<uint64_t> gpus{device_id};
X
xiaojun.lin 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503

        const int64_t NOT_FOUND = -1;
        int64_t device_id = NOT_FOUND;

        // cache hit
        {
            knowhere::QuantizerPtr quantizer = nullptr;

            for (auto& gpu : gpus) {
                auto cache = cache::GpuCacheMgr::GetInstance(gpu);
                if (auto cached_quantizer = cache->GetIndex(key)) {
                    device_id = gpu;
                    quantizer = std::static_pointer_cast<CachedQuantizer>(cached_quantizer)->Data();
                }
            }

            if (device_id != NOT_FOUND) {
                // cache hit
504
                milvus::json quantizer_conf{{knowhere::meta::DEVICEID : device_id}, {"mode" : 2}};
X
xiaojun.lin 已提交
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
                auto new_index = index_->LoadData(quantizer, config);
                index_ = new_index;
            }
        }

        if (device_id == NOT_FOUND) {
            // cache miss
            std::vector<int64_t> all_free_mem;
            for (auto& gpu : gpus) {
                auto cache = cache::GpuCacheMgr::GetInstance(gpu);
                auto free_mem = cache->CacheCapacity() - cache->CacheUsage();
                all_free_mem.push_back(free_mem);
            }

            auto max_e = std::max_element(all_free_mem.begin(), all_free_mem.end());
            auto best_index = std::distance(all_free_mem.begin(), max_e);
            device_id = gpus[best_index];

            auto pair = index_->CopyToGpuWithQuantizer(device_id);
            index_ = pair.first;

            // cache
            auto cached_quantizer = std::make_shared<CachedQuantizer>(pair.second);
            cache::GpuCacheMgr::GetInstance(device_id)->InsertItem(key, cached_quantizer);
        }
W
wxyu 已提交
530 531
        return Status::OK();
    }
X
xiaojun.lin 已提交
532
#endif
Y
youny626 已提交
533

G
groot 已提交
534
#ifdef MILVUS_GPU_VERSION
C
Cai Yudong 已提交
535 536
    auto data_obj_ptr = cache::GpuCacheMgr::GetInstance(device_id)->GetIndex(location_);
    auto index = std::static_pointer_cast<knowhere::VecIndex>(data_obj_ptr);
Y
youny626 已提交
537 538 539 540 541 542 543 544 545 546
    bool already_in_cache = (index != nullptr);
    if (already_in_cache) {
        index_ = index;
    } else {
        if (index_ == nullptr) {
            ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to copy to gpu";
            return Status(DB_ERROR, "index is null");
        }

        try {
C
Cai Yudong 已提交
547
            index_ = knowhere::cloner::CopyCpuToGpu(index_, device_id, knowhere::Config());
Y
youny626 已提交
548
            ENGINE_LOG_DEBUG << "CPU to GPU" << device_id;
C
Cai Yudong 已提交
549
            GpuCache(device_id);
Y
youny626 已提交
550 551 552 553
        } catch (std::exception& e) {
            ENGINE_LOG_ERROR << e.what();
            return Status(DB_ERROR, e.what());
        }
554
    }
G
groot 已提交
555
#endif
Y
youny626 已提交
556

557 558 559
    return Status::OK();
}

Y
Yu Kun 已提交
560 561
Status
ExecutionEngineImpl::CopyToIndexFileToGpu(uint64_t device_id) {
G
groot 已提交
562
#ifdef MILVUS_GPU_VERSION
G
groot 已提交
563
    // the ToIndexData is only a placeholder, cpu-copy-to-gpu action is performed in
564 565
    if (index_) {
        gpu_num_ = device_id;
C
Cai Yudong 已提交
566
        auto to_index_data = std::make_shared<knowhere::ToIndexData>(index_->Size());
567 568 569
        cache::DataObjPtr obj = std::static_pointer_cast<cache::DataObj>(to_index_data);
        milvus::cache::GpuCacheMgr::GetInstance(device_id)->InsertItem(location_ + "_placeholder", obj);
    }
G
groot 已提交
570
#endif
Y
Yu Kun 已提交
571 572 573
    return Status::OK();
}

S
starlord 已提交
574 575
Status
ExecutionEngineImpl::CopyToCpu() {
C
Cai Yudong 已提交
576 577
#ifdef MILVUS_GPU_VERSION
    auto index = std::static_pointer_cast<knowhere::VecIndex>(cache::CpuCacheMgr::GetInstance()->GetIndex(location_));
W
wxyu 已提交
578 579 580 581
    bool already_in_cache = (index != nullptr);
    if (already_in_cache) {
        index_ = index;
    } else {
S
starlord 已提交
582
        if (index_ == nullptr) {
S
starlord 已提交
583
            ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to copy to cpu";
S
starlord 已提交
584
            return Status(DB_ERROR, "index is null");
S
starlord 已提交
585 586
        }

Y
Yu Kun 已提交
587
        try {
C
Cai Yudong 已提交
588
            index_ = knowhere::cloner::CopyGpuToCpu(index_, knowhere::Config());
Y
Yu Kun 已提交
589
            ENGINE_LOG_DEBUG << "GPU to CPU";
S
starlord 已提交
590
        } catch (std::exception& e) {
S
starlord 已提交
591
            ENGINE_LOG_ERROR << e.what();
S
starlord 已提交
592
            return Status(DB_ERROR, e.what());
Y
Yu Kun 已提交
593 594 595
        }
    }

W
wxyu 已提交
596
    if (!already_in_cache) {
Y
Yu Kun 已提交
597
        Cache();
598 599
    }
    return Status::OK();
C
Cai Yudong 已提交
600 601 602 603
#else
    ENGINE_LOG_ERROR << "Calling ExecutionEngineImpl::CopyToCpu when using CPU version";
    return Status(DB_ERROR, "Calling ExecutionEngineImpl::CopyToCpu when using CPU version");
#endif
604 605
}

S
starlord 已提交
606
ExecutionEnginePtr
S
starlord 已提交
607
ExecutionEngineImpl::BuildIndex(const std::string& location, EngineType engine_type) {
X
xj.lin 已提交
608 609
    ENGINE_LOG_DEBUG << "Build index file: " << location << " from: " << location_;

C
Cai Yudong 已提交
610 611
    auto from_index = std::dynamic_pointer_cast<knowhere::IDMAP>(index_);
    auto bin_from_index = std::dynamic_pointer_cast<knowhere::BinaryIDMAP>(index_);
G
groot 已提交
612
    if (from_index == nullptr && bin_from_index == nullptr) {
S
starlord 已提交
613 614 615 616
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: from_index is null, failed to build index";
        return nullptr;
    }

S
starlord 已提交
617
    auto to_index = CreatetVecIndex(engine_type);
X
xj.lin 已提交
618
    if (!to_index) {
619
        throw Exception(DB_ERROR, "Unsupported index type");
X
xj.lin 已提交
620 621
    }

622 623 624 625 626 627
    milvus::json conf = index_params_;
    conf[knowhere::meta::DIM] = Dimension();
    conf[knowhere::meta::ROWS] = Count();
    conf[knowhere::meta::DEVICEID] = gpu_num_;
    MappingMetricType(metric_type_, conf);
    ENGINE_LOG_DEBUG << "Index params: " << conf.dump();
C
Cai Yudong 已提交
628 629
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(to_index->index_type());
    if (!adapter->CheckTrain(conf, to_index->index_mode())) {
630 631 632
        throw Exception(DB_ERROR, "Illegal index params");
    }
    ENGINE_LOG_DEBUG << "Index config: " << conf.dump();
633 634

    std::vector<segment::doc_id_t> uids;
Z
update  
Zhiru Zhu 已提交
635
    faiss::ConcurrentBitsetPtr blacklist;
G
groot 已提交
636
    if (from_index) {
C
Cai Yudong 已提交
637 638 639
        auto dataset =
            knowhere::GenDatasetWithIds(Count(), Dimension(), from_index->GetRawVectors(), from_index->GetRawIds());
        to_index->BuildAll(dataset, conf);
640
        uids = from_index->GetUids();
Z
update  
Zhiru Zhu 已提交
641
        from_index->GetBlacklist(blacklist);
G
groot 已提交
642
    } else if (bin_from_index) {
C
Cai Yudong 已提交
643 644 645
        auto dataset = knowhere::GenDatasetWithIds(Count(), Dimension(), bin_from_index->GetRawVectors(),
                                                   bin_from_index->GetRawIds());
        to_index->BuildAll(dataset, conf);
646
        uids = bin_from_index->GetUids();
Z
update  
Zhiru Zhu 已提交
647
        bin_from_index->GetBlacklist(blacklist);
G
groot 已提交
648
    }
C
Cai Yudong 已提交
649 650 651 652 653 654 655 656 657

#ifdef MILVUS_GPU_VERSION
    /* for GPU index, need copy back to CPU */
    if (to_index->index_mode() == knowhere::IndexMode::MODE_GPU) {
        auto device_index = std::dynamic_pointer_cast<knowhere::GPUIndex>(to_index);
        to_index = device_index->CopyGpuToCpu(conf);
    }
#endif

658
    to_index->SetUids(uids);
Z
update  
Zhiru Zhu 已提交
659 660 661 662 663
    ENGINE_LOG_DEBUG << "Set " << to_index->GetUids().size() << "uids for " << location;
    if (blacklist != nullptr) {
        to_index->SetBlacklist(blacklist);
        ENGINE_LOG_DEBUG << "Set blacklist for index " << location;
    }
664

665
    ENGINE_LOG_DEBUG << "Finish build index: " << location;
666
    return std::make_shared<ExecutionEngineImpl>(to_index, location, engine_type, metric_type_, index_params_);
S
starlord 已提交
667 668
}

669
void
C
Cai Yudong 已提交
670 671 672 673 674 675 676 677 678
MapAndCopyResult(const knowhere::DatasetPtr& dataset, const std::vector<milvus::segment::doc_id_t>& uids, int64_t nq,
                 int64_t k, float* distances, int64_t* labels) {
    int64_t* res_ids = dataset->Get<int64_t*>(knowhere::meta::IDS);
    float* res_dist = dataset->Get<float*>(knowhere::meta::DISTANCE);

    memcpy(distances, res_dist, sizeof(float) * nq * k);

    /* map offsets to ids */
    int64_t num = nq * k;
679
    for (int64_t i = 0; i < num; ++i) {
C
Cai Yudong 已提交
680
        int64_t offset = res_ids[i];
681
        if (offset != -1) {
C
Cai Yudong 已提交
682 683 684
            labels[i] = uids[offset];
        } else {
            labels[i] = -1;
685 686
        }
    }
C
Cai Yudong 已提交
687 688 689

    free(res_ids);
    free(res_dist);
690 691
}

S
starlord 已提交
692
Status
693 694
ExecutionEngineImpl::Search(int64_t n, const float* data, int64_t k, const milvus::json& extra_params, float* distances,
                            int64_t* labels, bool hybrid) {
695
#if 0
J
JinHai-CN 已提交
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
    if (index_type_ == EngineType::FAISS_IVFSQ8H) {
        if (!hybrid) {
            const std::string key = location_ + ".quantizer";
            std::vector<uint64_t> gpus = scheduler::get_gpu_pool();

            const int64_t NOT_FOUND = -1;
            int64_t device_id = NOT_FOUND;

            // cache hit
            {
                knowhere::QuantizerPtr quantizer = nullptr;

                for (auto& gpu : gpus) {
                    auto cache = cache::GpuCacheMgr::GetInstance(gpu);
                    if (auto cached_quantizer = cache->GetIndex(key)) {
                        device_id = gpu;
                        quantizer = std::static_pointer_cast<CachedQuantizer>(cached_quantizer)->Data();
                    }
                }

                if (device_id != NOT_FOUND) {
                    // cache hit
718
                    milvus::json quantizer_conf{{knowhere::meta::DEVICEID : device_id}, {"mode" : 2}};
J
JinHai-CN 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
                    auto new_index = index_->LoadData(quantizer, config);
                    index_ = new_index;
                }
            }

            if (device_id == NOT_FOUND) {
                // cache miss
                std::vector<int64_t> all_free_mem;
                for (auto& gpu : gpus) {
                    auto cache = cache::GpuCacheMgr::GetInstance(gpu);
                    auto free_mem = cache->CacheCapacity() - cache->CacheUsage();
                    all_free_mem.push_back(free_mem);
                }

                auto max_e = std::max_element(all_free_mem.begin(), all_free_mem.end());
                auto best_index = std::distance(all_free_mem.begin(), max_e);
                device_id = gpus[best_index];

                auto pair = index_->CopyToGpuWithQuantizer(device_id);
                index_ = pair.first;

                // cache
                auto cached_quantizer = std::make_shared<CachedQuantizer>(pair.second);
                cache::GpuCacheMgr::GetInstance(device_id)->InsertItem(key, cached_quantizer);
            }
        }
    }
746
#endif
747
    TimeRecorder rc("ExecutionEngineImpl::Search float");
J
JinHai-CN 已提交
748

S
starlord 已提交
749
    if (index_ == nullptr) {
S
starlord 已提交
750
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
S
starlord 已提交
751
        return Status(DB_ERROR, "index is null");
S
starlord 已提交
752 753
    }

754 755
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
756 757
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
758 759
        throw Exception(DB_ERROR, "Illegal search params");
    }
X
xiaojun.lin 已提交
760

W
wxyu 已提交
761 762 763
    if (hybrid) {
        HybridLoad();
    }
W
wxyu 已提交
764

C
Cai Yudong 已提交
765 766 767 768
    rc.RecordSection("query prepare");
    auto dataset = knowhere::GenDataset(n, index_->Dim(), data);
    auto result = index_->Query(dataset, conf);
    rc.RecordSection("query done");
769

770
    ENGINE_LOG_DEBUG << "get uids " << index_->GetUids().size() << " from index " << location_;
C
Cai Yudong 已提交
771
    MapAndCopyResult(result, index_->GetUids(), n, k, distances, labels);
772
    rc.RecordSection("map uids " + std::to_string(n * k));
W
wxyu 已提交
773

W
wxyu 已提交
774 775 776
    if (hybrid) {
        HybridUnset();
    }
W
wxyu 已提交
777

C
Cai Yudong 已提交
778
    return Status::OK();
S
starlord 已提交
779 780
}

G
groot 已提交
781
Status
782 783
ExecutionEngineImpl::Search(int64_t n, const uint8_t* data, int64_t k, const milvus::json& extra_params,
                            float* distances, int64_t* labels, bool hybrid) {
784
    TimeRecorder rc("ExecutionEngineImpl::Search uint8");
785

G
groot 已提交
786 787 788 789 790
    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
        return Status(DB_ERROR, "index is null");
    }

791 792
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
793 794
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
795 796
        throw Exception(DB_ERROR, "Illegal search params");
    }
G
groot 已提交
797 798 799 800 801

    if (hybrid) {
        HybridLoad();
    }

C
Cai Yudong 已提交
802 803 804 805
    rc.RecordSection("query prepare");
    auto dataset = knowhere::GenDataset(n, index_->Dim(), data);
    auto result = index_->Query(dataset, conf);
    rc.RecordSection("query done");
806

807
    ENGINE_LOG_DEBUG << "get uids " << index_->GetUids().size() << " from index " << location_;
C
Cai Yudong 已提交
808
    MapAndCopyResult(result, index_->GetUids(), n, k, distances, labels);
809
    rc.RecordSection("map uids " + std::to_string(n * k));
810 811 812 813 814

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
815
    return Status::OK();
816 817 818
}

Status
819 820
ExecutionEngineImpl::Search(int64_t n, const std::vector<int64_t>& ids, int64_t k, const milvus::json& extra_params,
                            float* distances, int64_t* labels, bool hybrid) {
821
    TimeRecorder rc("ExecutionEngineImpl::Search vector of ids");
822 823 824 825 826 827

    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
        return Status(DB_ERROR, "index is null");
    }

828 829
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
830 831
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
832 833
        throw Exception(DB_ERROR, "Illegal search params");
    }
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880

    if (hybrid) {
        HybridLoad();
    }

    rc.RecordSection("search prepare");

    // std::string segment_dir;
    // utils::GetParentPath(location_, segment_dir);
    // segment::SegmentReader segment_reader(segment_dir);
    //    segment::IdBloomFilterPtr id_bloom_filter_ptr;
    //    segment_reader.LoadBloomFilter(id_bloom_filter_ptr);

    // Check if the id is present. If so, find its offset
    const std::vector<segment::doc_id_t>& uids = index_->GetUids();

    std::vector<int64_t> offsets;
    /*
    std::vector<segment::doc_id_t> uids;
    auto status = segment_reader.LoadUids(uids);
    if (!status.ok()) {
        return status;
    }
     */

    // There is only one id in ids
    for (auto& id : ids) {
        //        if (id_bloom_filter_ptr->Check(id)) {
        //            if (uids.empty()) {
        //                segment_reader.LoadUids(uids);
        //            }
        //            auto found = std::find(uids.begin(), uids.end(), id);
        //            if (found != uids.end()) {
        //                auto offset = std::distance(uids.begin(), found);
        //                offsets.emplace_back(offset);
        //            }
        //        }
        auto found = std::find(uids.begin(), uids.end(), id);
        if (found != uids.end()) {
            auto offset = std::distance(uids.begin(), found);
            offsets.emplace_back(offset);
        }
    }

    rc.RecordSection("get offset");

    if (!offsets.empty()) {
C
Cai Yudong 已提交
881 882 883
        auto dataset = knowhere::GenDatasetWithIds(offsets.size(), index_->Dim(), nullptr, offsets.data());
        auto result = index_->QueryById(dataset, conf);
        rc.RecordSection("query by id done");
884

885
        ENGINE_LOG_DEBUG << "get uids " << index_->GetUids().size() << " from index " << location_;
C
Cai Yudong 已提交
886
        MapAndCopyResult(result, uids, offsets.size(), k, distances, labels);
887
        rc.RecordSection("map uids " + std::to_string(offsets.size() * k));
888 889 890 891 892 893
    }

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
894
    return Status::OK();
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
}

Status
ExecutionEngineImpl::GetVectorByID(const int64_t& id, float* vector, bool hybrid) {
    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
        return Status(DB_ERROR, "index is null");
    }

    if (hybrid) {
        HybridLoad();
    }

    // Only one id for now
    std::vector<int64_t> ids{id};
C
Cai Yudong 已提交
910 911 912 913
    auto dataset = knowhere::GenDatasetWithIds(1, index_->Dim(), nullptr, ids.data());
    auto result = index_->GetVectorById(dataset, knowhere::Config());
    float* res_vec = (float*)(result->Get<void*>(knowhere::meta::TENSOR));
    memcpy(vector, res_vec, sizeof(float) * 1 * index_->Dim());
914 915 916 917 918

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
919
    return Status::OK();
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
}

Status
ExecutionEngineImpl::GetVectorByID(const int64_t& id, uint8_t* vector, bool hybrid) {
    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
        return Status(DB_ERROR, "index is null");
    }

    ENGINE_LOG_DEBUG << "Get binary vector by id:  " << id;

    if (hybrid) {
        HybridLoad();
    }

    // Only one id for now
    std::vector<int64_t> ids{id};
C
Cai Yudong 已提交
937 938 939 940
    auto dataset = knowhere::GenDatasetWithIds(1, index_->Dim(), nullptr, ids.data());
    auto result = index_->GetVectorById(dataset, knowhere::Config());
    uint8_t* res_vec = (uint8_t*)(result->Get<void*>(knowhere::meta::TENSOR));
    memcpy(vector, res_vec, sizeof(uint8_t) * 1 * index_->Dim());
G
groot 已提交
941 942 943 944 945

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
946
    return Status::OK();
G
groot 已提交
947 948
}

S
starlord 已提交
949 950
Status
ExecutionEngineImpl::Cache() {
951
    cache::DataObjPtr obj = std::static_pointer_cast<cache::DataObj>(index_);
S
starlord 已提交
952
    milvus::cache::CpuCacheMgr::GetInstance()->InsertItem(location_, obj);
S
starlord 已提交
953 954 955 956

    return Status::OK();
}

S
starlord 已提交
957 958
Status
ExecutionEngineImpl::GpuCache(uint64_t gpu_id) {
G
groot 已提交
959
#ifdef MILVUS_GPU_VERSION
960
    cache::DataObjPtr obj = std::static_pointer_cast<cache::DataObj>(index_);
S
starlord 已提交
961
    milvus::cache::GpuCacheMgr::GetInstance(gpu_id)->InsertItem(location_, obj);
G
groot 已提交
962
#endif
963
    return Status::OK();
Y
Yu Kun 已提交
964 965
}

X
xj.lin 已提交
966
// TODO(linxj): remove.
S
starlord 已提交
967 968
Status
ExecutionEngineImpl::Init() {
G
groot 已提交
969
#ifdef MILVUS_GPU_VERSION
S
starlord 已提交
970
    server::Config& config = server::Config::GetInstance();
Y
yudong.cai 已提交
971
    std::vector<int64_t> gpu_ids;
972
    Status s = config.GetGpuResourceConfigBuildIndexResources(gpu_ids);
F
fishpenguin 已提交
973
    if (!s.ok()) {
974
        gpu_num_ = -1;
975
        return s;
F
fishpenguin 已提交
976
    }
977 978 979 980
    for (auto id : gpu_ids) {
        if (gpu_num_ == id) {
            return Status::OK();
        }
S
starlord 已提交
981
    }
S
starlord 已提交
982

983 984
    std::string msg = "Invalid gpu_num";
    return Status(SERVER_INVALID_ARGUMENT, msg);
G
groot 已提交
985 986 987
#else
    return Status::OK();
#endif
S
starlord 已提交
988 989
}

S
starlord 已提交
990 991
}  // namespace engine
}  // namespace milvus