VecIndex.cpp 8.8 KB
Newer Older
J
jinhai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

S
starlord 已提交
18
#include "wrapper/VecIndex.h"
S
starlord 已提交
19 20
#include "VecImpl.h"
#include "knowhere/common/Exception.h"
X
xiaojun.lin 已提交
21
#include "knowhere/index/vector_index/IndexIDMAP.h"
S
starlord 已提交
22 23 24
#include "knowhere/index/vector_index/IndexIVF.h"
#include "knowhere/index/vector_index/IndexIVFPQ.h"
#include "knowhere/index/vector_index/IndexIVFSQ.h"
X
xiaojun.lin 已提交
25 26
#include "knowhere/index/vector_index/IndexKDT.h"
#include "knowhere/index/vector_index/IndexNSG.h"
S
starlord 已提交
27
#include "utils/Log.h"
X
MS-154  
xj.lin 已提交
28

Y
youny626 已提交
29
#ifdef MILVUS_GPU_VERSION
30
#include <cuda.h>
Y
youny626 已提交
31
#include "knowhere/index/vector_index/IndexGPUIDMAP.h"
Y
youny626 已提交
32 33 34 35
#include "knowhere/index/vector_index/IndexGPUIVF.h"
#include "knowhere/index/vector_index/IndexGPUIVFPQ.h"
#include "knowhere/index/vector_index/IndexGPUIVFSQ.h"
#include "knowhere/index/vector_index/IndexIVFSQHybrid.h"
Y
youny626 已提交
36
#include "wrapper/gpu/GPUVecImpl.h"
Y
youny626 已提交
37
#endif
38

X
xj.lin 已提交
39
namespace milvus {
X
MS-154  
xj.lin 已提交
40 41
namespace engine {

42 43
int64_t
VecIndex::Size() {
44 45 46
    if (size_ != 0) {
        return size_;
    }
47 48 49
    return Count() * Dimension() * sizeof(float);
}

50 51 52 53 54
void
VecIndex::set_size(int64_t size) {
    size_ = size;
}

X
xj.lin 已提交
55 56 57 58
struct FileIOReader {
    std::fstream fs;
    std::string name;

S
starlord 已提交
59
    explicit FileIOReader(const std::string& fname);
60

X
xj.lin 已提交
61
    ~FileIOReader();
62 63

    size_t
S
starlord 已提交
64
    operator()(void* ptr, size_t size);
65 66

    size_t
S
starlord 已提交
67
    operator()(void* ptr, size_t size, size_t pos);
X
xj.lin 已提交
68 69
};

S
starlord 已提交
70
FileIOReader::FileIOReader(const std::string& fname) {
X
xj.lin 已提交
71 72 73 74 75 76 77 78
    name = fname;
    fs = std::fstream(name, std::ios::in | std::ios::binary);
}

FileIOReader::~FileIOReader() {
    fs.close();
}

79
size_t
S
starlord 已提交
80 81
FileIOReader::operator()(void* ptr, size_t size) {
    fs.read(reinterpret_cast<char*>(ptr), size);
X
xj.lin 已提交
82 83
}

84
size_t
S
starlord 已提交
85
FileIOReader::operator()(void* ptr, size_t size, size_t pos) {
X
xj.lin 已提交
86 87 88
    return 0;
}

89 90 91 92
struct FileIOWriter {
    std::fstream fs;
    std::string name;

S
starlord 已提交
93
    explicit FileIOWriter(const std::string& fname);
94
    ~FileIOWriter();
S
starlord 已提交
95 96
    size_t
    operator()(void* ptr, size_t size);
97 98
};

S
starlord 已提交
99
FileIOWriter::FileIOWriter(const std::string& fname) {
X
xj.lin 已提交
100 101 102 103 104 105 106 107
    name = fname;
    fs = std::fstream(name, std::ios::out | std::ios::binary);
}

FileIOWriter::~FileIOWriter() {
    fs.close();
}

108
size_t
S
starlord 已提交
109 110
FileIOWriter::operator()(void* ptr, size_t size) {
    fs.write(reinterpret_cast<char*>(ptr), size);
X
xj.lin 已提交
111 112
}

113
VecIndexPtr
S
starlord 已提交
114
GetVecIndexFactory(const IndexType& type, const Config& cfg) {
S
starlord 已提交
115
    std::shared_ptr<knowhere::VectorIndex> index;
S
starlord 已提交
116
    auto gpu_device = -1;  // TODO(linxj): remove hardcode here
X
xj.lin 已提交
117 118
    switch (type) {
        case IndexType::FAISS_IDMAP: {
S
starlord 已提交
119
            index = std::make_shared<knowhere::IDMAP>();
X
xj.lin 已提交
120 121 122
            return std::make_shared<BFIndex>(index);
        }
        case IndexType::FAISS_IVFFLAT_CPU: {
S
starlord 已提交
123
            index = std::make_shared<knowhere::IVF>();
X
xj.lin 已提交
124 125
            break;
        }
Y
youny626 已提交
126 127
        case IndexType::FAISS_IVFPQ_CPU: {
            index = std::make_shared<knowhere::IVFPQ>();
X
xj.lin 已提交
128 129
            break;
        }
Y
youny626 已提交
130 131 132
        case IndexType::SPTAG_KDT_RNT_CPU: {
            index = std::make_shared<knowhere::CPUKDTRNG>();
            break;
X
xj.lin 已提交
133
        }
Y
youny626 已提交
134 135
        case IndexType::FAISS_IVFSQ8_CPU: {
            index = std::make_shared<knowhere::IVFSQ>();
X
xj.lin 已提交
136 137
            break;
        }
Y
youny626 已提交
138 139 140 141

#ifdef MILVUS_GPU_VERSION
        case IndexType::FAISS_IVFFLAT_GPU: {
            index = std::make_shared<knowhere::GPUIVF>(gpu_device);
X
xj.lin 已提交
142 143
            break;
        }
Y
youny626 已提交
144 145
        case IndexType::FAISS_IVFPQ_GPU: {
            index = std::make_shared<knowhere::GPUIVFPQ>(gpu_device);
X
xj.lin 已提交
146
            break;
X
xj.lin 已提交
147 148
        }
        case IndexType::FAISS_IVFSQ8_MIX: {
S
starlord 已提交
149
            index = std::make_shared<knowhere::GPUIVFSQ>(gpu_device);
X
xj.lin 已提交
150
            return std::make_shared<IVFMixIndex>(index, IndexType::FAISS_IVFSQ8_MIX);
X
xj.lin 已提交
151
        }
X
xj.lin 已提交
152
        case IndexType::FAISS_IVFSQ8_GPU: {
S
starlord 已提交
153
            index = std::make_shared<knowhere::GPUIVFSQ>(gpu_device);
X
xj.lin 已提交
154 155
            break;
        }
Y
youny626 已提交
156 157 158 159
        case IndexType::FAISS_IVFFLAT_MIX: {
            index = std::make_shared<knowhere::GPUIVF>(gpu_device);
            return std::make_shared<IVFMixIndex>(index, IndexType::FAISS_IVFFLAT_MIX);
        }
X
xiaojun.lin 已提交
160
#ifdef CUSTOMIZATION
X
xiaojun.lin 已提交
161
        case IndexType::FAISS_IVFSQ8_HYBRID: {
162
            index = std::make_shared<knowhere::IVFSQHybrid>(gpu_device);
W
wxyu 已提交
163
            return std::make_shared<IVFHybridIndex>(index, IndexType::FAISS_IVFSQ8_HYBRID);
X
xiaojun.lin 已提交
164
        }
Y
youny626 已提交
165
#endif
X
xiaojun.lin 已提交
166
#endif
167
        case IndexType::NSG_MIX: {  // TODO(linxj): bug.
S
starlord 已提交
168
            index = std::make_shared<knowhere::NSG>(gpu_device);
X
xj.lin 已提交
169 170
            break;
        }
Y
youny626 已提交
171
        default: { return nullptr; }
X
MS-154  
xj.lin 已提交
172
    }
X
xj.lin 已提交
173
    return std::make_shared<VecIndexImpl>(index, type);
X
MS-154  
xj.lin 已提交
174 175
}

176
VecIndexPtr
177
LoadVecIndex(const IndexType& index_type, const knowhere::BinarySet& index_binary, int64_t size) {
X
MS-154  
xj.lin 已提交
178
    auto index = GetVecIndexFactory(index_type);
X
xiaojun.lin 已提交
179 180
    if (index == nullptr)
        return nullptr;
X
xiaojun.lin 已提交
181
    // else
X
MS-154  
xj.lin 已提交
182
    index->Load(index_binary);
183
    index->set_size(size);
X
MS-154  
xj.lin 已提交
184 185 186
    return index;
}

187
VecIndexPtr
S
starlord 已提交
188
read_index(const std::string& location) {
X
xj.lin 已提交
189 190 191
    knowhere::BinarySet load_data_list;
    FileIOReader reader(location);
    reader.fs.seekg(0, reader.fs.end);
192
    int64_t length = reader.fs.tellg();
193
    if (length <= 0) {
194 195 196
        return nullptr;
    }

X
xj.lin 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    reader.fs.seekg(0);

    size_t rp = 0;
    auto current_type = IndexType::INVALID;
    reader(&current_type, sizeof(current_type));
    rp += sizeof(current_type);
    while (rp < length) {
        size_t meta_length;
        reader(&meta_length, sizeof(meta_length));
        rp += sizeof(meta_length);
        reader.fs.seekg(rp);

        auto meta = new char[meta_length];
        reader(meta, meta_length);
        rp += meta_length;
        reader.fs.seekg(rp);

        size_t bin_length;
        reader(&bin_length, sizeof(bin_length));
        rp += sizeof(bin_length);
        reader.fs.seekg(rp);

        auto bin = new uint8_t[bin_length];
        reader(bin, bin_length);
        rp += bin_length;

        auto binptr = std::make_shared<uint8_t>();
        binptr.reset(bin);
        load_data_list.Append(std::string(meta, meta_length), binptr, bin_length);
226
        delete[] meta;
X
xj.lin 已提交
227 228
    }

229
    return LoadVecIndex(current_type, load_data_list, length);
X
xj.lin 已提交
230 231
}

232
Status
S
starlord 已提交
233
write_index(VecIndexPtr index, const std::string& location) {
X
xj.lin 已提交
234 235 236 237 238 239
    try {
        auto binaryset = index->Serialize();
        auto index_type = index->GetType();

        FileIOWriter writer(location);
        writer(&index_type, sizeof(IndexType));
S
starlord 已提交
240
        for (auto& iter : binaryset.binary_map_) {
X
xj.lin 已提交
241 242 243
            auto meta = iter.first.c_str();
            size_t meta_length = iter.first.length();
            writer(&meta_length, sizeof(meta_length));
S
starlord 已提交
244
            writer((void*)meta, meta_length);
X
xj.lin 已提交
245 246 247 248

            auto binary = iter.second;
            int64_t binary_length = binary->size;
            writer(&binary_length, sizeof(binary_length));
S
starlord 已提交
249
            writer((void*)binary->data.get(), binary_length);
X
xj.lin 已提交
250
        }
S
starlord 已提交
251
    } catch (knowhere::KnowhereException& e) {
X
xj.lin 已提交
252
        WRAPPER_LOG_ERROR << e.what();
253
        return Status(KNOWHERE_UNEXPECTED_ERROR, e.what());
S
starlord 已提交
254
    } catch (std::exception& e) {
X
xj.lin 已提交
255
        WRAPPER_LOG_ERROR << e.what();
256 257 258
        std::string estring(e.what());
        if (estring.find("No space left on device") != estring.npos) {
            WRAPPER_LOG_ERROR << "No space left on the device";
259
            return Status(KNOWHERE_NO_SPACE, "No space left on the device");
260
        } else {
261
            return Status(KNOWHERE_ERROR, e.what());
262
        }
X
xj.lin 已提交
263
    }
264
    return Status::OK();
X
xj.lin 已提交
265 266
}

267
IndexType
S
starlord 已提交
268
ConvertToCpuIndexType(const IndexType& type) {
X
xj.lin 已提交
269
    // TODO(linxj): add IDMAP
W
wxyu 已提交
270
    switch (type) {
X
xj.lin 已提交
271
        case IndexType::FAISS_IVFFLAT_GPU:
W
wxyu 已提交
272 273 274
        case IndexType::FAISS_IVFFLAT_MIX: {
            return IndexType::FAISS_IVFFLAT_CPU;
        }
X
xj.lin 已提交
275
        case IndexType::FAISS_IVFSQ8_GPU:
W
wxyu 已提交
276
        case IndexType::FAISS_IVFSQ8_MIX: {
X
xj.lin 已提交
277
            return IndexType::FAISS_IVFSQ8_CPU;
W
wxyu 已提交
278
        }
Y
youny626 已提交
279
        default: { return type; }
W
wxyu 已提交
280 281 282
    }
}

283
IndexType
S
starlord 已提交
284
ConvertToGpuIndexType(const IndexType& type) {
X
xj.lin 已提交
285 286 287 288 289 290 291 292 293
    switch (type) {
        case IndexType::FAISS_IVFFLAT_MIX:
        case IndexType::FAISS_IVFFLAT_CPU: {
            return IndexType::FAISS_IVFFLAT_GPU;
        }
        case IndexType::FAISS_IVFSQ8_MIX:
        case IndexType::FAISS_IVFSQ8_CPU: {
            return IndexType::FAISS_IVFSQ8_GPU;
        }
Y
youny626 已提交
294
        default: { return type; }
X
xj.lin 已提交
295 296 297
    }
}

S
starlord 已提交
298 299
}  // namespace engine
}  // namespace milvus