ExecutionEngineImpl.cpp 9.0 KB
Newer Older
S
starlord 已提交
1 2 3 4 5
/*******************************************************************************
 * Copyright 上海赜睿信息科技有限公司(Zilliz) - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited.
 * Proprietary and confidential.
 ******************************************************************************/
X
xj.lin 已提交
6 7
#include <stdexcept>

S
starlord 已提交
8 9 10
#include "src/server/ServerConfig.h"
#include "src/metrics/Metrics.h"
#include "db/Log.h"
J
jinhai 已提交
11
#include "utils/CommonUtil.h"
S
starlord 已提交
12

X
xj.lin 已提交
13 14 15
#include "src/cache/CpuCacheMgr.h"
#include "ExecutionEngineImpl.h"
#include "wrapper/knowhere/vec_index.h"
S
starlord 已提交
16
#include "wrapper/knowhere/vec_impl.h"
X
xj.lin 已提交
17
#include "knowhere/common/exception.h"
S
starlord 已提交
18
#include "db/Exception.h"
X
xj.lin 已提交
19

S
starlord 已提交
20 21 22 23 24

namespace zilliz {
namespace milvus {
namespace engine {

X
xj.lin 已提交
25 26 27 28 29 30 31 32
namespace {
std::string GetMetricType() {
    server::ServerConfig &config = server::ServerConfig::GetInstance();
    server::ConfigNode engine_config = config.GetConfig(server::CONFIG_ENGINE);
    return engine_config.GetValue(server::CONFIG_METRICTYPE, "L2");
}
}

S
starlord 已提交
33
ExecutionEngineImpl::ExecutionEngineImpl(uint16_t dimension,
X
xj.lin 已提交
34 35 36
                                         const std::string &location,
                                         EngineType type)
    : location_(location), dim(dimension), build_type(type) {
X
xj.lin 已提交
37
    current_type = EngineType::FAISS_IDMAP;
X
xj.lin 已提交
38 39 40 41

    index_ = CreatetVecIndex(EngineType::FAISS_IDMAP);
    if (!index_) throw Exception("Create Empty VecIndex");

X
xj.lin 已提交
42 43
    Config build_cfg;
    build_cfg["dim"] = dimension;
X
xj.lin 已提交
44
    build_cfg["metric_type"] = GetMetricType();
X
xj.lin 已提交
45 46
    AutoGenParams(index_->GetType(), 0, build_cfg);
    auto ec = std::static_pointer_cast<BFIndex>(index_)->Build(build_cfg);
X
xj.lin 已提交
47
    if (ec != server::KNOWHERE_SUCCESS) { throw Exception("Build index error"); }
S
starlord 已提交
48 49
}

X
xj.lin 已提交
50 51 52 53
ExecutionEngineImpl::ExecutionEngineImpl(VecIndexPtr index,
                                         const std::string &location,
                                         EngineType type)
    : index_(std::move(index)), location_(location), build_type(type) {
X
xj.lin 已提交
54
    current_type = type;
X
xj.lin 已提交
55
}
S
starlord 已提交
56

X
xj.lin 已提交
57 58 59 60 61
VecIndexPtr ExecutionEngineImpl::CreatetVecIndex(EngineType type) {
    std::shared_ptr<VecIndex> index;
    switch (type) {
        case EngineType::FAISS_IDMAP: {
            index = GetVecIndexFactory(IndexType::FAISS_IDMAP);
S
starlord 已提交
62 63
            break;
        }
J
jinhai 已提交
64
        case EngineType::FAISS_IVFFLAT: {
X
xj.lin 已提交
65
            index = GetVecIndexFactory(IndexType::FAISS_IVFFLAT_MIX);
S
starlord 已提交
66 67
            break;
        }
J
jinhai 已提交
68 69
        case EngineType::FAISS_IVFSQ8: {
            index = GetVecIndexFactory(IndexType::FAISS_IVFSQ8_MIX);
S
starlord 已提交
70 71
            break;
        }
X
xj.lin 已提交
72 73 74 75
        case EngineType::NSG_MIX: {
            index = GetVecIndexFactory(IndexType::NSG_MIX);
            break;
        }
X
xj.lin 已提交
76
        default: {
S
starlord 已提交
77 78 79 80
            ENGINE_LOG_ERROR << "Invalid engine type";
            return nullptr;
        }
    }
X
xj.lin 已提交
81
    return index;
S
starlord 已提交
82 83 84
}

Status ExecutionEngineImpl::AddWithIds(long n, const float *xdata, const long *xids) {
X
xj.lin 已提交
85
    auto ec = index_->Add(n, xdata, xids);
X
xj.lin 已提交
86 87 88
    if (ec != server::KNOWHERE_SUCCESS) {
        return Status::Error("Add error");
    }
S
starlord 已提交
89 90 91 92
    return Status::OK();
}

size_t ExecutionEngineImpl::Count() const {
X
xj.lin 已提交
93
    return index_->Count();
S
starlord 已提交
94 95 96
}

size_t ExecutionEngineImpl::Size() const {
X
xj.lin 已提交
97
    return (size_t) (Count() * Dimension()) * sizeof(float);
S
starlord 已提交
98 99 100
}

size_t ExecutionEngineImpl::Dimension() const {
X
xj.lin 已提交
101
    return index_->Dimension();
S
starlord 已提交
102 103 104
}

size_t ExecutionEngineImpl::PhysicalSize() const {
J
jinhai 已提交
105
    return server::CommonUtil::GetFileSize(location_);
S
starlord 已提交
106 107 108
}

Status ExecutionEngineImpl::Serialize() {
X
xj.lin 已提交
109 110 111 112
    auto ec = write_index(index_, location_);
    if (ec != server::KNOWHERE_SUCCESS) {
        return Status::Error("Serialize: write to disk error");
    }
S
starlord 已提交
113 114 115
    return Status::OK();
}

J
jinhai 已提交
116
Status ExecutionEngineImpl::Load(bool to_cache) {
X
xj.lin 已提交
117
    index_ = zilliz::milvus::cache::CpuCacheMgr::GetInstance()->GetIndex(location_);
J
jinhai 已提交
118
    bool already_in_cache = (index_ != nullptr);
X
xj.lin 已提交
119 120
    auto start_time = METRICS_NOW_TIME;
    if (!index_) {
X
xj.lin 已提交
121 122 123 124 125 126 127 128 129
        try {
            index_ = read_index(location_);
            ENGINE_LOG_DEBUG << "Disk io from: " << location_;
        } catch (knowhere::KnowhereException &e) {
            ENGINE_LOG_ERROR << e.what();
            return Status::Error(e.what());
        } catch (std::exception &e) {
            return Status::Error(e.what());
        }
X
xj.lin 已提交
130 131
    }

J
jinhai 已提交
132
    if (!already_in_cache && to_cache) {
X
xj.lin 已提交
133 134 135
        Cache();
        auto end_time = METRICS_NOW_TIME;
        auto total_time = METRICS_MICROSECONDS(start_time, end_time);
X
xj.lin 已提交
136

X
xj.lin 已提交
137
        server::Metrics::GetInstance().FaissDiskLoadDurationSecondsHistogramObserve(total_time);
J
jinhai 已提交
138
        double physical_size = PhysicalSize();
X
xj.lin 已提交
139

J
jinhai 已提交
140 141
        server::Metrics::GetInstance().FaissDiskLoadSizeBytesHistogramObserve(physical_size);
        server::Metrics::GetInstance().FaissDiskLoadIOSpeedGaugeSet(physical_size / double(total_time));
X
xj.lin 已提交
142 143
    }
    return Status::OK();
X
xj.lin 已提交
144 145
}

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
Status ExecutionEngineImpl::CopyToGpu(uint64_t device_id) {
    try {
        index_ = index_->CopyToGpu(device_id);
        ENGINE_LOG_DEBUG << "CPU to GPU" << device_id;
    } catch (knowhere::KnowhereException &e) {
        ENGINE_LOG_ERROR << e.what();
        return Status::Error(e.what());
    } catch (std::exception &e) {
        return Status::Error(e.what());
    }
    return Status::OK();
}

Status ExecutionEngineImpl::CopyToCpu() {
    try {
        index_ = index_->CopyToCpu();
        ENGINE_LOG_DEBUG << "GPU to CPU";
    } catch (knowhere::KnowhereException &e) {
        ENGINE_LOG_ERROR << e.what();
        return Status::Error(e.what());
    } catch (std::exception &e) {
        return Status::Error(e.what());
    }
    return Status::OK();
}

X
xj.lin 已提交
172 173 174 175 176
Status ExecutionEngineImpl::Merge(const std::string &location) {
    if (location == location_) {
        return Status::Error("Cannot Merge Self");
    }
    ENGINE_LOG_DEBUG << "Merge index file: " << location << " to: " << location_;
S
starlord 已提交
177

X
xj.lin 已提交
178 179
    auto to_merge = zilliz::milvus::cache::CpuCacheMgr::GetInstance()->GetIndex(location);
    if (!to_merge) {
X
xj.lin 已提交
180 181 182 183 184 185 186 187
        try {
            to_merge = read_index(location);
        } catch (knowhere::KnowhereException &e) {
            ENGINE_LOG_ERROR << e.what();
            return Status::Error(e.what());
        } catch (std::exception &e) {
            return Status::Error(e.what());
        }
X
xj.lin 已提交
188 189
    }

X
xj.lin 已提交
190
    if (auto file_index = std::dynamic_pointer_cast<BFIndex>(to_merge)) {
X
xj.lin 已提交
191 192 193 194 195
        auto ec = index_->Add(file_index->Count(), file_index->GetRawVectors(), file_index->GetRawIds());
        if (ec != server::KNOWHERE_SUCCESS) {
            ENGINE_LOG_ERROR << "Merge: Add Error";
            return Status::Error("Merge: Add Error");
        }
X
xj.lin 已提交
196 197 198 199
        return Status::OK();
    } else {
        return Status::Error("file index type is not idmap");
    }
S
starlord 已提交
200 201 202
}

ExecutionEnginePtr
X
xj.lin 已提交
203 204 205 206 207
ExecutionEngineImpl::BuildIndex(const std::string &location) {
    ENGINE_LOG_DEBUG << "Build index file: " << location << " from: " << location_;

    auto from_index = std::dynamic_pointer_cast<BFIndex>(index_);
    auto to_index = CreatetVecIndex(build_type);
X
xj.lin 已提交
208 209 210 211
    if (!to_index) {
        throw Exception("Create Empty VecIndex");
    }

X
xj.lin 已提交
212 213
    Config build_cfg;
    build_cfg["dim"] = Dimension();
X
xj.lin 已提交
214
    build_cfg["metric_type"] = GetMetricType();
X
xj.lin 已提交
215
    build_cfg["gpu_id"] = gpu_num;
X
xj.lin 已提交
216
    build_cfg["nlist"] = nlist_;
X
xj.lin 已提交
217 218
    AutoGenParams(to_index->GetType(), Count(), build_cfg);

X
xj.lin 已提交
219 220 221
    auto ec = to_index->BuildAll(Count(),
                                 from_index->GetRawVectors(),
                                 from_index->GetRawIds(),
X
xj.lin 已提交
222
                                 build_cfg);
X
xj.lin 已提交
223
    if (ec != server::KNOWHERE_SUCCESS) { throw Exception("Build index error"); }
X
xj.lin 已提交
224 225

    return std::make_shared<ExecutionEngineImpl>(to_index, location, build_type);
S
starlord 已提交
226 227 228
}

Status ExecutionEngineImpl::Search(long n,
X
xj.lin 已提交
229 230
                                   const float *data,
                                   long k,
Y
Yu Kun 已提交
231
                                   long nprobe,
X
xj.lin 已提交
232 233
                                   float *distances,
                                   long *labels) const {
Y
Yu Kun 已提交
234 235
    ENGINE_LOG_DEBUG << "Search Params: [k]  " << k << " [nprobe] " << nprobe;
    auto ec = index_->Search(n, data, distances, labels, Config::object{{"k", k}, {"nprobe", nprobe}});
X
xj.lin 已提交
236 237 238 239
    if (ec != server::KNOWHERE_SUCCESS) {
        ENGINE_LOG_ERROR << "Search error";
        return Status::Error("Search: Search Error");
    }
S
starlord 已提交
240 241 242 243
    return Status::OK();
}

Status ExecutionEngineImpl::Cache() {
X
xj.lin 已提交
244
    zilliz::milvus::cache::CpuCacheMgr::GetInstance()->InsertItem(location_, index_);
S
starlord 已提交
245 246 247 248

    return Status::OK();
}

X
xj.lin 已提交
249
// TODO(linxj): remove.
S
starlord 已提交
250
Status ExecutionEngineImpl::Init() {
X
xj.lin 已提交
251 252 253 254 255 256
    using namespace zilliz::milvus::server;
    ServerConfig &config = ServerConfig::GetInstance();
    ConfigNode server_config = config.GetConfig(CONFIG_SERVER);
    gpu_num = server_config.GetInt32Value("gpu_index", 0);

    switch (build_type) {
J
jinhai 已提交
257 258
        case EngineType::FAISS_IVFSQ8:
        case EngineType::FAISS_IVFFLAT: {
X
xj.lin 已提交
259
            ConfigNode engine_config = config.GetConfig(CONFIG_ENGINE);
X
xj.lin 已提交
260
            nlist_ = engine_config.GetInt32Value(CONFIG_NLIST, 16384);
X
xj.lin 已提交
261 262 263
            break;
        }
    }
S
starlord 已提交
264 265 266 267 268 269 270 271

    return Status::OK();
}


} // namespace engine
} // namespace milvus
} // namespace zilliz