Skip to content

Commit de7d75a

Browse files
committed
enhance: intermin index support index without raw data and metric type fp16/bf16
Signed-off-by: cqy123456 <[email protected]>
1 parent 82dc57a commit de7d75a

30 files changed

+928
-255
lines changed

configs/milvus.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,11 @@ queryNode:
407407
# Milvus will eventually seals and indexes all segments, but enabling this optimizes search performance for immediate queries following data insertion.
408408
# This defaults to true, indicating that Milvus creates temporary index for growing segments and the sealed segments that are not indexed upon searches.
409409
enableIndex: true
410-
nlist: 128 # temp index nlist, recommend to set sqrt(chunkRows), must smaller than chunkRows/8
410+
nlist: 128 # interim index nlist, recommend to set sqrt(chunkRows), must smaller than chunkRows/8
411411
nprobe: 16 # nprobe to search small index, based on your accuracy requirement, must smaller than nlist
412+
subDim: 4 # interim index sub dim, recommend to (subDim % vector dim == 0)
413+
refineRatio: 4.5 # interim index parameters, should set to be >= 1.0
414+
denseVectorIndexType: IVF_FLAT_CC # Dense vector intermin index type
412415
memExpansionRate: 1.15 # extra memory needed by building interim index
413416
buildParallelRate: 0.5 # the ratio of building interim index parallel matched with cpu num
414417
multipleChunkedEnable: true # Enable multiple chunked search

internal/core/src/common/type_c.h

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ typedef struct CMmapConfig {
103103
uint64_t fix_file_size;
104104
bool growing_enable_mmap;
105105
bool scalar_index_enable_mmap;
106+
bool scalar_field_enable_mmap;
107+
bool vector_index_enable_mmap;
108+
bool vector_field_enable_mmap;
106109
} CMmapConfig;
107110

108111
typedef struct CTraceConfig {

internal/core/src/index/VectorMemIndex.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,30 @@ VectorMemIndex<T>::VectorMemIndex(
8383
}
8484
}
8585

86+
template <typename T>
87+
VectorMemIndex<T>::VectorMemIndex(const IndexType& index_type,
88+
const MetricType& metric_type,
89+
const IndexVersion& version,
90+
const knowhere::ViewDataOp view_data)
91+
: VectorIndex(index_type, metric_type) {
92+
CheckMetricTypeSupport<T>(metric_type);
93+
AssertInfo(!is_unsupported(index_type, metric_type),
94+
index_type + " doesn't support metric: " + metric_type);
95+
96+
auto view_data_pack = knowhere::Pack(view_data);
97+
auto get_index_obj = knowhere::IndexFactory::Instance().Create<T>(
98+
GetIndexType(), version, view_data_pack);
99+
if (get_index_obj.has_value()) {
100+
index_ = get_index_obj.value();
101+
} else {
102+
auto err = get_index_obj.error();
103+
if (err == knowhere::Status::invalid_index_error) {
104+
PanicInfo(ErrorCode::Unsupported, get_index_obj.what());
105+
}
106+
PanicInfo(ErrorCode::KnowhereError, get_index_obj.what());
107+
}
108+
}
109+
86110
template <typename T>
87111
knowhere::expected<std::vector<knowhere::IndexNode::IteratorPtr>>
88112
VectorMemIndex<T>::VectorIterators(const milvus::DatasetPtr dataset,

internal/core/src/index/VectorMemIndex.h

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class VectorMemIndex : public VectorIndex {
3939
const storage::FileManagerContext& file_manager_context =
4040
storage::FileManagerContext());
4141

42+
// knowhere data view index special constucter for intermin index, no need to hold file_manager_ to upload or download files
43+
VectorMemIndex(const IndexType& index_type,
44+
const MetricType& metric_type,
45+
const IndexVersion& version,
46+
const knowhere::ViewDataOp view_data);
47+
4248
BinarySet
4349
Serialize(const Config& config) override;
4450

internal/core/src/mmap/ChunkVector.h

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#pragma once
1717
#include "mmap/ChunkData.h"
1818
#include "storage/MmapManager.h"
19+
#include "segcore/SegcoreConfig.h"
1920
namespace milvus {
2021
template <typename Type>
2122
class ChunkVectorBase {

internal/core/src/query/SearchOnGrowing.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,9 @@ FloatSegmentIndexSearch(const segcore::SegmentGrowingImpl& segment,
4242
// TODO(SPARSE): see todo in PlanImpl.h::PlaceHolder.
4343
auto dim = is_sparse ? 0 : field.get_dim();
4444

45-
AssertInfo(field.get_data_type() == DataType::VECTOR_FLOAT ||
46-
field.get_data_type() == DataType::VECTOR_SPARSE_FLOAT,
47-
"[FloatSearch]Field data type isn't VECTOR_FLOAT or "
48-
"VECTOR_SPARSE_FLOAT");
45+
AssertInfo(IsVectorDataType(field.get_data_type()),
46+
"[FloatSearch]Field data type isn't VECTOR_FLOAT, "
47+
"VECTOR_FLOAT16, VECTOR_BFLOAT16 or VECTOR_SPARSE_FLOAT");
4948
dataset::SearchDataset search_dataset{info.metric_type_,
5049
num_queries,
5150
info.topk_,

internal/core/src/segcore/ChunkedSegmentSealedImpl.cpp

+71-28
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "common/Tracer.h"
4141
#include "common/Types.h"
4242
#include "google/protobuf/message_lite.h"
43+
#include "index/VectorIndex.h"
4344
#include "index/VectorMemIndex.h"
4445
#include "mmap/ChunkedColumn.h"
4546
#include "mmap/Utils.h"
@@ -115,7 +116,8 @@ ChunkedSegmentSealedImpl::LoadVecIndex(const LoadIndexInfo& info) {
115116
if (get_bit(field_data_ready_bitset_, field_id)) {
116117
fields_.erase(field_id);
117118
set_bit(field_data_ready_bitset_, field_id, false);
118-
} else if (get_bit(binlog_index_bitset_, field_id)) {
119+
}
120+
if (get_bit(binlog_index_bitset_, field_id)) {
119121
set_bit(binlog_index_bitset_, field_id, false);
120122
vector_indexings_.drop_field_indexing(field_id);
121123
}
@@ -136,8 +138,7 @@ ChunkedSegmentSealedImpl::WarmupChunkCache(const FieldId field_id,
136138
auto& field_meta = schema_->operator[](field_id);
137139
AssertInfo(field_meta.is_vector(), "vector field is not vector type");
138140

139-
if (!get_bit(index_ready_bitset_, field_id) &&
140-
!get_bit(binlog_index_bitset_, field_id)) {
141+
if (!get_bit(index_ready_bitset_, field_id)) {
141142
return;
142143
}
143144

@@ -496,21 +497,13 @@ ChunkedSegmentSealedImpl::LoadFieldData(FieldId field_id, FieldDataInfo& data) {
496497
insert_record_.seal_pks();
497498
}
498499

499-
bool use_temp_index = false;
500500
{
501-
// update num_rows to build temperate binlog index
501+
// update num_rows to build temperate intermin index
502502
std::unique_lock lck(mutex_);
503503
update_row_count(num_rows);
504504
}
505505

506-
if (generate_interim_index(field_id)) {
507-
std::unique_lock lck(mutex_);
508-
fields_.erase(field_id);
509-
set_bit(field_data_ready_bitset_, field_id, false);
510-
use_temp_index = true;
511-
}
512-
513-
if (!use_temp_index) {
506+
if (!generate_interim_index(field_id)) {
514507
std::unique_lock lck(mutex_);
515508
set_bit(field_data_ready_bitset_, field_id, true);
516509
}
@@ -1746,8 +1739,12 @@ ChunkedSegmentSealedImpl::bulk_subscript(FieldId field_id,
17461739
if (count == 0) {
17471740
return fill_with_empty(field_id, count);
17481741
}
1749-
1750-
if (HasIndex(field_id)) {
1742+
AssertInfo(HasFieldData(field_id) || HasIndex(field_id),
1743+
"Not found raw data in index or field data struct.");
1744+
if (HasFieldData(field_id)) {
1745+
Assert(get_bit(field_data_ready_bitset_, field_id));
1746+
return get_raw_data(field_id, field_meta, seg_offsets, count);
1747+
} else {
17511748
// if field has load scalar index, reverse raw data from index
17521749
if (!IsVectorDataType(field_meta.get_data_type())) {
17531750
// AssertInfo(num_chunk() == 1,
@@ -1761,10 +1758,6 @@ ChunkedSegmentSealedImpl::bulk_subscript(FieldId field_id,
17611758
}
17621759
return get_vector(field_id, seg_offsets, count);
17631760
}
1764-
1765-
Assert(get_bit(field_data_ready_bitset_, field_id));
1766-
1767-
return get_raw_data(field_id, field_meta, seg_offsets, count);
17681761
}
17691762

17701763
std::unique_ptr<DataArray>
@@ -1821,15 +1814,22 @@ ChunkedSegmentSealedImpl::HasRawData(int64_t field_id) const {
18211814
auto fieldID = FieldId(field_id);
18221815
const auto& field_meta = schema_->operator[](fieldID);
18231816
if (IsVectorDataType(field_meta.get_data_type())) {
1824-
if (get_bit(index_ready_bitset_, fieldID) |
1825-
get_bit(binlog_index_bitset_, fieldID)) {
1817+
if (get_bit(index_ready_bitset_, fieldID)) {
18261818
AssertInfo(vector_indexings_.is_ready(fieldID),
18271819
"vector index is not ready");
18281820
auto field_indexing = vector_indexings_.get_field_indexing(fieldID);
18291821
auto vec_index = dynamic_cast<index::VectorIndex*>(
18301822
field_indexing->indexing_.get());
18311823
return vec_index->HasRawData();
18321824
}
1825+
} else if (get_bit(binlog_index_bitset_, fieldID)) {
1826+
AssertInfo(vector_indexings_.is_ready(fieldID),
1827+
"vector index is not ready");
1828+
auto field_indexing = vector_indexings_.get_field_indexing(fieldID);
1829+
auto vec_index =
1830+
dynamic_cast<index::VectorIndex*>(field_indexing->indexing_.get());
1831+
return vec_index->HasRawData() ||
1832+
get_bit(field_data_ready_bitset_, fieldID);
18331833
} else {
18341834
auto scalar_index = scalar_indexings_.find(fieldID);
18351835
if (scalar_index != scalar_indexings_.end()) {
@@ -2020,6 +2020,8 @@ ChunkedSegmentSealedImpl::generate_interim_index(const FieldId field_id) {
20202020
}
20212021
// check data type
20222022
if (field_meta.get_data_type() != DataType::VECTOR_FLOAT &&
2023+
field_meta.get_data_type() != DataType::VECTOR_FLOAT16 &&
2024+
field_meta.get_data_type() != DataType::VECTOR_BFLOAT16 &&
20232025
!is_sparse) {
20242026
return false;
20252027
}
@@ -2065,16 +2067,50 @@ ChunkedSegmentSealedImpl::generate_interim_index(const FieldId field_id) {
20652067
is_sparse
20662068
? dynamic_cast<ChunkedSparseFloatColumn*>(vec_data.get())->Dim()
20672069
: field_meta.get_dim();
2070+
auto index_metric = field_binlog_config->GetMetricType();
2071+
std::unique_ptr<index::VectorIndex> vec_index = nullptr;
2072+
if (!is_sparse) {
2073+
knowhere::ViewDataOp view_data = [field_raw_data_ptr =
2074+
vec_data](size_t id) {
2075+
return field_raw_data_ptr->ValueAt(id);
2076+
};
2077+
if (field_meta.get_data_type() == DataType::VECTOR_FLOAT) {
2078+
vec_index = std::make_unique<index::VectorMemIndex<float>>(
2079+
field_binlog_config->GetIndexType(),
2080+
index_metric,
2081+
knowhere::Version::GetCurrentVersion().VersionNumber(),
2082+
view_data);
2083+
} else if (field_meta.get_data_type() == DataType::VECTOR_FLOAT16) {
2084+
vec_index =
2085+
std::make_unique<index::VectorMemIndex<knowhere::fp16>>(
2086+
field_binlog_config->GetIndexType(),
2087+
index_metric,
2088+
knowhere::Version::GetCurrentVersion().VersionNumber(),
2089+
view_data);
2090+
} else if (field_meta.get_data_type() ==
2091+
DataType::VECTOR_BFLOAT16) {
2092+
vec_index =
2093+
std::make_unique<index::VectorMemIndex<knowhere::bf16>>(
2094+
field_binlog_config->GetIndexType(),
2095+
index_metric,
2096+
knowhere::Version::GetCurrentVersion().VersionNumber(),
2097+
view_data);
2098+
}
2099+
} else {
2100+
vec_index = std::make_unique<index::VectorMemIndex<float>>(
2101+
field_binlog_config->GetIndexType(),
2102+
index_metric,
2103+
knowhere::Version::GetCurrentVersion().VersionNumber());
2104+
}
2105+
if (vec_index == nullptr) {
2106+
LOG_INFO("fail to generate intermin index, invalid data type.");
2107+
return false;
2108+
}
20682109

20692110
auto build_config = field_binlog_config->GetBuildBaseParams();
20702111
build_config[knowhere::meta::DIM] = std::to_string(dim);
20712112
build_config[knowhere::meta::NUM_BUILD_THREAD] = std::to_string(1);
2072-
auto index_metric = field_binlog_config->GetMetricType();
20732113

2074-
auto vec_index = std::make_unique<index::VectorMemIndex<float>>(
2075-
field_binlog_config->GetIndexType(),
2076-
index_metric,
2077-
knowhere::Version::GetCurrentVersion().VersionNumber());
20782114
auto num_chunk = vec_data->num_chunks();
20792115
for (int i = 0; i < num_chunk; ++i) {
20802116
auto dataset = knowhere::GenDataSet(
@@ -2091,19 +2127,26 @@ ChunkedSegmentSealedImpl::generate_interim_index(const FieldId field_id) {
20912127

20922128
if (enable_binlog_index()) {
20932129
std::unique_lock lck(mutex_);
2130+
if (vec_index->HasRawData()) {
2131+
fields_.erase(field_id);
2132+
set_bit(field_data_ready_bitset_, field_id, false);
2133+
} else {
2134+
// some knowhere view data index not has raw data, still keep it
2135+
set_bit(field_data_ready_bitset_, field_id, true);
2136+
}
20942137
vector_indexings_.append_field_indexing(
20952138
field_id, index_metric, std::move(vec_index));
20962139

20972140
vec_binlog_config_[field_id] = std::move(field_binlog_config);
20982141
set_bit(binlog_index_bitset_, field_id, true);
20992142
LOG_INFO(
2100-
"replace binlog with binlog index in segment {}, field {}.",
2143+
"replace binlog with intermin index in segment {}, field {}.",
21012144
this->get_segment_id(),
21022145
field_id.get());
21032146
}
21042147
return true;
21052148
} catch (std::exception& e) {
2106-
LOG_WARN("fail to generate binlog index, because {}", e.what());
2149+
LOG_WARN("fail to generate intermin index, because {}", e.what());
21072150
return false;
21082151
}
21092152
}

internal/core/src/segcore/ConcurrentVector.h

+13
Original file line numberDiff line numberDiff line change
@@ -541,4 +541,17 @@ class ConcurrentVector<BFloat16Vector>
541541
}
542542
};
543543

544+
static bool
545+
ConcurrentDenseVectorCheck(const VectorBase* vec_base, DataType data_type) {
546+
if (data_type == DataType::VECTOR_FLOAT) {
547+
return dynamic_cast<const ConcurrentVector<FloatVector>*>(vec_base);
548+
} else if (data_type == DataType::VECTOR_FLOAT16) {
549+
return dynamic_cast<const ConcurrentVector<Float16Vector>*>(vec_base);
550+
} else if (data_type == DataType::VECTOR_BFLOAT16) {
551+
return dynamic_cast<const ConcurrentVector<BFloat16Vector>*>(vec_base);
552+
} else {
553+
return false;
554+
}
555+
}
556+
544557
} // namespace milvus::segcore

0 commit comments

Comments
 (0)