ExecutionEngineImpl.cpp 35.4 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"
44
#include "utils/Error.h"
S
starlord 已提交
45
#include "utils/Exception.h"
S
starlord 已提交
46
#include "utils/Log.h"
C
Cai Yudong 已提交
47
#include "utils/Status.h"
48
#include "utils/TimeRecorder.h"
G
groot 已提交
49
#include "utils/ValidationUtil.h"
X
xj.lin 已提交
50

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

G
groot 已提交
54 55 56
namespace {

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

    return Status::OK();
}

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

}  // namespace

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

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

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

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

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

129 130 131 132 133
    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 已提交
134 135
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckTrain(conf, index_->index_mode())) {
136 137
        throw Exception(DB_ERROR, "Illegal index params");
    }
X
xiaojun.lin 已提交
138

C
Cai Yudong 已提交
139 140 141 142 143
    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);
144
    }
S
starlord 已提交
145 146
}

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

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

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

233
void
W
wxyu 已提交
234
ExecutionEngineImpl::HybridLoad() const {
C
Cai Yudong 已提交
235 236 237 238
#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 已提交
239 240 241
        return;
    }

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

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

    // 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 已提交
267
            hybrid_index->SetQuantizer(quantizer);
W
wxyu 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
            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];

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

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

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

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

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

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

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

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

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

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

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

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

C
Cai Yudong 已提交
371
    index_ = std::static_pointer_cast<knowhere::VecIndex>(cache::CpuCacheMgr::GetInstance()->GetIndex(location_));
372 373 374 375 376
    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 已提交
377
        knowhere::VecIndexFactory& vec_index_factory = knowhere::VecIndexFactory::GetInstance();
378

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

393
            auto status = segment_reader_ptr->Load();
394 395 396 397 398 399 400 401 402 403 404 405 406
            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);
407
            ENGINE_LOG_DEBUG << "set uids " << index_->GetUids().size() << " for index " << location_;
408 409 410 411 412 413 414 415 416 417 418

            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 已提交
419
            auto dataset = knowhere::GenDataset(vectors->GetCount(), this->dim_, vectors_data.data());
420
            if (index_type_ == EngineType::FAISS_IDMAP) {
C
Cai Yudong 已提交
421 422 423 424
                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);
425
            } else if (index_type_ == EngineType::FAISS_BIN_IDMAP) {
C
Cai Yudong 已提交
426 427 428 429
                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);
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 463
            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);
464
                    ENGINE_LOG_DEBUG << "set uids " << index_->GetUids().size() << " for index " << location_;
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

                    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 已提交
480

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

        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
505
                milvus::json quantizer_conf{{knowhere::meta::DEVICEID : device_id}, {"mode" : 2}};
X
xiaojun.lin 已提交
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
                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 已提交
531 532
        return Status::OK();
    }
X
xiaojun.lin 已提交
533
#endif
Y
youny626 已提交
534

G
groot 已提交
535
#ifdef MILVUS_GPU_VERSION
C
Cai Yudong 已提交
536 537
    auto data_obj_ptr = cache::GpuCacheMgr::GetInstance(device_id)->GetIndex(location_);
    auto index = std::static_pointer_cast<knowhere::VecIndex>(data_obj_ptr);
Y
youny626 已提交
538 539 540 541 542 543 544 545 546 547
    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 {
548
            /* Index data is copied to GPU first, then added into GPU cache.
549 550
             * Add lock here to avoid multiple INDEX are copied to one GPU card at same time.
             * And reserve space to avoid GPU out of memory issue.
551 552
             */
            ENGINE_LOG_DEBUG << "CPU to GPU" << device_id << " start";
553
            auto gpu_cache_mgr = cache::GpuCacheMgr::GetInstance(device_id);
554 555
            // gpu_cache_mgr->Lock();
            // gpu_cache_mgr->Reserve(index_->Size());
C
Cai Yudong 已提交
556
            index_ = knowhere::cloner::CopyCpuToGpu(index_, device_id, knowhere::Config());
557 558
            // gpu_cache_mgr->InsertItem(location_, std::static_pointer_cast<cache::DataObj>(index_));
            // gpu_cache_mgr->Unlock();
559
            ENGINE_LOG_DEBUG << "CPU to GPU" << device_id << " finished";
Y
youny626 已提交
560 561 562 563
        } catch (std::exception& e) {
            ENGINE_LOG_ERROR << e.what();
            return Status(DB_ERROR, e.what());
        }
564
    }
G
groot 已提交
565
#endif
Y
youny626 已提交
566

567 568 569
    return Status::OK();
}

Y
Yu Kun 已提交
570 571
Status
ExecutionEngineImpl::CopyToIndexFileToGpu(uint64_t device_id) {
G
groot 已提交
572
#ifdef MILVUS_GPU_VERSION
G
groot 已提交
573
    // the ToIndexData is only a placeholder, cpu-copy-to-gpu action is performed in
574
    if (index_) {
575 576
        auto gpu_cache_mgr = milvus::cache::GpuCacheMgr::GetInstance(device_id);
        gpu_cache_mgr->Lock();
577
        gpu_num_ = device_id;
578 579
        gpu_cache_mgr->Reserve(index_->Size());
        gpu_cache_mgr->Unlock();
580
    }
G
groot 已提交
581
#endif
Y
Yu Kun 已提交
582 583 584
    return Status::OK();
}

S
starlord 已提交
585 586
Status
ExecutionEngineImpl::CopyToCpu() {
C
Cai Yudong 已提交
587 588
#ifdef MILVUS_GPU_VERSION
    auto index = std::static_pointer_cast<knowhere::VecIndex>(cache::CpuCacheMgr::GetInstance()->GetIndex(location_));
W
wxyu 已提交
589 590 591 592
    bool already_in_cache = (index != nullptr);
    if (already_in_cache) {
        index_ = index;
    } else {
S
starlord 已提交
593
        if (index_ == nullptr) {
S
starlord 已提交
594
            ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to copy to cpu";
S
starlord 已提交
595
            return Status(DB_ERROR, "index is null");
S
starlord 已提交
596 597
        }

Y
Yu Kun 已提交
598
        try {
C
Cai Yudong 已提交
599
            index_ = knowhere::cloner::CopyGpuToCpu(index_, knowhere::Config());
Y
Yu Kun 已提交
600
            ENGINE_LOG_DEBUG << "GPU to CPU";
S
starlord 已提交
601
        } catch (std::exception& e) {
S
starlord 已提交
602
            ENGINE_LOG_ERROR << e.what();
S
starlord 已提交
603
            return Status(DB_ERROR, e.what());
Y
Yu Kun 已提交
604 605 606
        }
    }

W
wxyu 已提交
607
    if (!already_in_cache) {
Y
Yu Kun 已提交
608
        Cache();
609 610
    }
    return Status::OK();
C
Cai Yudong 已提交
611 612 613 614
#else
    ENGINE_LOG_ERROR << "Calling ExecutionEngineImpl::CopyToCpu when using CPU version";
    return Status(DB_ERROR, "Calling ExecutionEngineImpl::CopyToCpu when using CPU version");
#endif
615 616
}

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

C
Cai Yudong 已提交
621 622
    auto from_index = std::dynamic_pointer_cast<knowhere::IDMAP>(index_);
    auto bin_from_index = std::dynamic_pointer_cast<knowhere::BinaryIDMAP>(index_);
G
groot 已提交
623
    if (from_index == nullptr && bin_from_index == nullptr) {
S
starlord 已提交
624 625 626 627
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: from_index is null, failed to build index";
        return nullptr;
    }

S
starlord 已提交
628
    auto to_index = CreatetVecIndex(engine_type);
X
xj.lin 已提交
629
    if (!to_index) {
630
        throw Exception(DB_ERROR, "Unsupported index type");
X
xj.lin 已提交
631 632
    }

633 634 635 636 637 638
    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 已提交
639 640
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(to_index->index_type());
    if (!adapter->CheckTrain(conf, to_index->index_mode())) {
641 642 643
        throw Exception(DB_ERROR, "Illegal index params");
    }
    ENGINE_LOG_DEBUG << "Index config: " << conf.dump();
644 645

    std::vector<segment::doc_id_t> uids;
Z
update  
Zhiru Zhu 已提交
646
    faiss::ConcurrentBitsetPtr blacklist;
G
groot 已提交
647
    if (from_index) {
C
Cai Yudong 已提交
648 649 650
        auto dataset =
            knowhere::GenDatasetWithIds(Count(), Dimension(), from_index->GetRawVectors(), from_index->GetRawIds());
        to_index->BuildAll(dataset, conf);
651
        uids = from_index->GetUids();
Z
update  
Zhiru Zhu 已提交
652
        from_index->GetBlacklist(blacklist);
G
groot 已提交
653
    } else if (bin_from_index) {
C
Cai Yudong 已提交
654 655 656
        auto dataset = knowhere::GenDatasetWithIds(Count(), Dimension(), bin_from_index->GetRawVectors(),
                                                   bin_from_index->GetRawIds());
        to_index->BuildAll(dataset, conf);
657
        uids = bin_from_index->GetUids();
Z
update  
Zhiru Zhu 已提交
658
        bin_from_index->GetBlacklist(blacklist);
G
groot 已提交
659
    }
C
Cai Yudong 已提交
660 661 662 663 664 665 666 667 668

#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

669
    to_index->SetUids(uids);
Z
update  
Zhiru Zhu 已提交
670 671 672 673 674
    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;
    }
675

676
    ENGINE_LOG_DEBUG << "Finish build index: " << location;
677
    return std::make_shared<ExecutionEngineImpl>(to_index, location, engine_type, metric_type_, index_params_);
S
starlord 已提交
678 679
}

680
void
C
Cai Yudong 已提交
681 682 683 684 685 686 687 688 689
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;
690
    for (int64_t i = 0; i < num; ++i) {
C
Cai Yudong 已提交
691
        int64_t offset = res_ids[i];
692
        if (offset != -1) {
C
Cai Yudong 已提交
693 694 695
            labels[i] = uids[offset];
        } else {
            labels[i] = -1;
696 697
        }
    }
C
Cai Yudong 已提交
698 699 700

    free(res_ids);
    free(res_dist);
701 702
}

S
starlord 已提交
703
Status
704 705
ExecutionEngineImpl::Search(int64_t n, const float* data, int64_t k, const milvus::json& extra_params, float* distances,
                            int64_t* labels, bool hybrid) {
706
#if 0
J
JinHai-CN 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
    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
729
                    milvus::json quantizer_conf{{knowhere::meta::DEVICEID : device_id}, {"mode" : 2}};
J
JinHai-CN 已提交
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
                    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);
            }
        }
    }
757
#endif
758
    TimeRecorder rc("ExecutionEngineImpl::Search float");
J
JinHai-CN 已提交
759

S
starlord 已提交
760
    if (index_ == nullptr) {
S
starlord 已提交
761
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
S
starlord 已提交
762
        return Status(DB_ERROR, "index is null");
S
starlord 已提交
763 764
    }

765 766
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
767 768
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
769 770
        throw Exception(DB_ERROR, "Illegal search params");
    }
X
xiaojun.lin 已提交
771

W
wxyu 已提交
772 773 774
    if (hybrid) {
        HybridLoad();
    }
W
wxyu 已提交
775

C
Cai Yudong 已提交
776 777 778 779
    rc.RecordSection("query prepare");
    auto dataset = knowhere::GenDataset(n, index_->Dim(), data);
    auto result = index_->Query(dataset, conf);
    rc.RecordSection("query done");
780

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

W
wxyu 已提交
785 786 787
    if (hybrid) {
        HybridUnset();
    }
W
wxyu 已提交
788

C
Cai Yudong 已提交
789
    return Status::OK();
S
starlord 已提交
790 791
}

G
groot 已提交
792
Status
793 794
ExecutionEngineImpl::Search(int64_t n, const uint8_t* data, int64_t k, const milvus::json& extra_params,
                            float* distances, int64_t* labels, bool hybrid) {
795
    TimeRecorder rc("ExecutionEngineImpl::Search uint8");
796

G
groot 已提交
797 798 799 800 801
    if (index_ == nullptr) {
        ENGINE_LOG_ERROR << "ExecutionEngineImpl: index is null, failed to search";
        return Status(DB_ERROR, "index is null");
    }

802 803
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
804 805
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
806 807
        throw Exception(DB_ERROR, "Illegal search params");
    }
G
groot 已提交
808 809 810 811 812

    if (hybrid) {
        HybridLoad();
    }

C
Cai Yudong 已提交
813 814 815 816
    rc.RecordSection("query prepare");
    auto dataset = knowhere::GenDataset(n, index_->Dim(), data);
    auto result = index_->Query(dataset, conf);
    rc.RecordSection("query done");
817

818
    ENGINE_LOG_DEBUG << "get uids " << index_->GetUids().size() << " from index " << location_;
C
Cai Yudong 已提交
819
    MapAndCopyResult(result, index_->GetUids(), n, k, distances, labels);
820
    rc.RecordSection("map uids " + std::to_string(n * k));
821 822 823 824 825

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
826
    return Status::OK();
827 828 829
}

Status
830 831
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) {
832
    TimeRecorder rc("ExecutionEngineImpl::Search vector of ids");
833 834 835 836 837 838

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

839 840
    milvus::json conf = extra_params;
    conf[knowhere::meta::TOPK] = k;
C
Cai Yudong 已提交
841 842
    auto adapter = knowhere::AdapterMgr::GetInstance().GetAdapter(index_->index_type());
    if (!adapter->CheckSearch(conf, index_->index_type(), index_->index_mode())) {
843 844
        throw Exception(DB_ERROR, "Illegal search params");
    }
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 881 882 883 884 885 886 887 888 889 890 891

    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 已提交
892 893 894
        auto dataset = knowhere::GenDatasetWithIds(offsets.size(), index_->Dim(), nullptr, offsets.data());
        auto result = index_->QueryById(dataset, conf);
        rc.RecordSection("query by id done");
895

896
        ENGINE_LOG_DEBUG << "get uids " << index_->GetUids().size() << " from index " << location_;
C
Cai Yudong 已提交
897
        MapAndCopyResult(result, uids, offsets.size(), k, distances, labels);
898
        rc.RecordSection("map uids " + std::to_string(offsets.size() * k));
899 900 901 902 903 904
    }

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
905
    return Status::OK();
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
}

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 已提交
921 922 923 924
    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());
925 926 927 928 929

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
930
    return Status::OK();
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
}

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 已提交
948 949 950 951
    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 已提交
952 953 954 955 956

    if (hybrid) {
        HybridUnset();
    }

C
Cai Yudong 已提交
957
    return Status::OK();
G
groot 已提交
958 959
}

S
starlord 已提交
960 961
Status
ExecutionEngineImpl::Cache() {
962 963
    auto cpu_cache_mgr = milvus::cache::CpuCacheMgr::GetInstance();
    cpu_cache_mgr->Lock();
964
    cache::DataObjPtr obj = std::static_pointer_cast<cache::DataObj>(index_);
965 966
    cpu_cache_mgr->InsertItem(location_, obj);
    cpu_cache_mgr->Unlock();
967
    return Status::OK();
Y
Yu Kun 已提交
968 969
}

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

987 988
    std::string msg = "Invalid gpu_num";
    return Status(SERVER_INVALID_ARGUMENT, msg);
G
groot 已提交
989 990 991
#else
    return Status::OK();
#endif
S
starlord 已提交
992 993
}

S
starlord 已提交
994 995
}  // namespace engine
}  // namespace milvus