aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2024-04-16 14:43:23 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2024-04-16 21:19:19 +0000
commit1862d47ff95d80fbd01ad77d3a79e3283f58603f (patch)
tree76034222fcc4da75b924b3ed7703aeeac6b02268
parent302b8f03d28baef770719f8b73315d78fc6da950 (diff)
- Optimize distance calculation for tensors with single dense subspace.
- Let EmptySubspace be invalid. - Add noexcept to get_tensor(s).
-rw-r--r--eval/src/vespa/eval/eval/cell_type.h2
-rw-r--r--eval/src/vespa/eval/eval/typed_cells.h18
-rw-r--r--searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp2
-rw-r--r--searchlib/src/tests/tensor/distance_calculator/distance_calculator_test.cpp4
-rw-r--r--searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp11
-rw-r--r--searchlib/src/tests/tensor/hnsw_index/stress_hnsw_mt.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/features/closenessfeature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.cpp42
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/bound_distance_function.h5
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h10
-rw-r--r--searchlib/src/vespa/searchlib/tensor/distance_calculator.h45
-rw-r--r--searchlib/src/vespa/searchlib/tensor/doc_vector_access.h6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp3
-rw-r--r--searchlib/src/vespa/searchlib/tensor/empty_subspace.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/hamming_distance.cpp5
-rw-r--r--searchlib/src/vespa/searchlib/tensor/i_tensor_attribute.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_buffer_operations.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_buffer_store.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/vector_bundle.h2
-rw-r--r--streamingvisitors/src/vespa/vsm/searcher/nearest_neighbor_field_searcher.cpp2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store.h6
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastore.h2
33 files changed, 143 insertions, 118 deletions
diff --git a/eval/src/vespa/eval/eval/cell_type.h b/eval/src/vespa/eval/eval/cell_type.h
index c15a5b68dba..3c474638480 100644
--- a/eval/src/vespa/eval/eval/cell_type.h
+++ b/eval/src/vespa/eval/eval/cell_type.h
@@ -70,7 +70,7 @@ struct CellMetaNotScalar {
struct CellMeta {
const CellType cell_type;
const bool is_scalar;
- constexpr CellMeta(CellType cell_type_in, bool is_scalar_in)
+ constexpr CellMeta(CellType cell_type_in, bool is_scalar_in) noexcept
: cell_type(cell_type_in), is_scalar(is_scalar_in)
{
// is_scalar -> double cell type
diff --git a/eval/src/vespa/eval/eval/typed_cells.h b/eval/src/vespa/eval/eval/typed_cells.h
index d05c3e3294a..6cb8675cd5f 100644
--- a/eval/src/vespa/eval/eval/typed_cells.h
+++ b/eval/src/vespa/eval/eval/typed_cells.h
@@ -11,24 +11,24 @@ namespace vespalib::eval {
struct TypedCells {
const void *data;
- size_t size:56;
- CellType type;
+ size_t size:56;
+ CellType type;
- explicit TypedCells(ConstArrayRef<double> cells) : data(cells.begin()), size(cells.size()), type(CellType::DOUBLE) {}
- explicit TypedCells(ConstArrayRef<float> cells) : data(cells.begin()), size(cells.size()), type(CellType::FLOAT) {}
- explicit TypedCells(ConstArrayRef<BFloat16> cells) : data(cells.begin()), size(cells.size()), type(CellType::BFLOAT16) {}
- explicit TypedCells(ConstArrayRef<Int8Float> cells) : data(cells.begin()), size(cells.size()), type(CellType::INT8) {}
+ explicit TypedCells(ConstArrayRef<double> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::DOUBLE) {}
+ explicit TypedCells(ConstArrayRef<float> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::FLOAT) {}
+ explicit TypedCells(ConstArrayRef<BFloat16> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::BFLOAT16) {}
+ explicit TypedCells(ConstArrayRef<Int8Float> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::INT8) {}
TypedCells() noexcept : data(nullptr), size(0), type(CellType::DOUBLE) {}
TypedCells(const void *dp, CellType ct, size_t sz) noexcept : data(dp), size(sz), type(ct) {}
- template <typename T> bool check_type() const { return vespalib::eval::check_cell_type<T>(type); }
+ template <typename T> bool check_type() const noexcept { return check_cell_type<T>(type); }
- template <typename T> ConstArrayRef<T> typify() const {
+ template <typename T> ConstArrayRef<T> typify() const noexcept {
assert(check_type<T>());
return ConstArrayRef<T>((const T *)data, size);
}
- template <typename T> ConstArrayRef<T> unsafe_typify() const {
+ template <typename T> ConstArrayRef<T> unsafe_typify() const noexcept {
return ConstArrayRef<T>((const T *)data, size);
}
diff --git a/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp b/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp
index 48270694394..d67757a3811 100644
--- a/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp
+++ b/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp
@@ -224,7 +224,7 @@ void ExtendAttributeTest::testExtendRaw(AttributeVector& attr)
void ExtendAttributeTest::testExtendTensor(AttributeVector& attr)
{
- std::vector<double> empty_cells{0.0, 0.0};
+ std::vector<double> empty_cells{};
std::vector<double> spec0_dense_cells{1.0, 2.0};
std::vector<double> spec0_mixed_cells0{3.0, 4.0};
std::vector<double> spec0_mixed_cells1{5.0, 6.0};
diff --git a/searchlib/src/tests/tensor/distance_calculator/distance_calculator_test.cpp b/searchlib/src/tests/tensor/distance_calculator/distance_calculator_test.cpp
index b7702398857..dab335675d8 100644
--- a/searchlib/src/tests/tensor/distance_calculator/distance_calculator_test.cpp
+++ b/searchlib/src/tests/tensor/distance_calculator/distance_calculator_test.cpp
@@ -44,7 +44,9 @@ public:
double calc_distance(uint32_t docid, const vespalib::string& query_tensor) {
auto qt = make_tensor(query_tensor);
auto calc = DistanceCalculator::make_with_validation(*attr, *qt);
- return calc->calc_with_limit(docid, std::numeric_limits<double>::max());
+ return calc->has_single_subspace()
+ ? calc->calc_with_limit<true>(docid, std::numeric_limits<double>::max())
+ : calc->calc_with_limit<false>(docid, std::numeric_limits<double>::max());
}
double calc_rawscore(uint32_t docid, const vespalib::string& query_tensor) {
auto qt = make_tensor(query_tensor);
diff --git a/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
index c01fc33767a..b697effeab4 100644
--- a/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
+++ b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
@@ -62,14 +62,14 @@ public:
_vectors[docid] = vec;
return *this;
}
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override {
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override {
return get_vectors(docid).cells(subspace);
}
- VectorBundle get_vectors(uint32_t docid) const override {
+ VectorBundle get_vectors(uint32_t docid) const noexcept override {
ArrayRef ref(_vectors[docid]);
assert((ref.size() % _subspace_type.size()) == 0);
uint32_t subspaces = ref.size() / _subspace_type.size();
- return VectorBundle(ref.data(), subspaces, _subspace_type);
+ return {ref.data(), subspaces, _subspace_type};
}
void clear() { _vectors.clear(); }
@@ -106,7 +106,7 @@ public:
.set(7, {3, 5}).set(8, {0, 3}).set(9, {4, 5});
}
- ~HnswIndexTest() override {}
+ ~HnswIndexTest() override;
auto dff() {
return search::tensor::make_distance_function_factory(
@@ -280,6 +280,9 @@ public:
static constexpr bool is_single = std::is_same_v<IndexType, HnswIndex<HnswIndexType::SINGLE>>;
};
+template <typename IndexType>
+HnswIndexTest<IndexType>::~HnswIndexTest() = default;
+
using HnswIndexTestTypes = ::testing::Types<HnswIndex<HnswIndexType::SINGLE>, HnswIndex<HnswIndexType::MULTI>>;
TYPED_TEST_SUITE(HnswIndexTest, HnswIndexTestTypes);
diff --git a/searchlib/src/tests/tensor/hnsw_index/stress_hnsw_mt.cpp b/searchlib/src/tests/tensor/hnsw_index/stress_hnsw_mt.cpp
index 1feb968fbb4..dce09a87fb8 100644
--- a/searchlib/src/tests/tensor/hnsw_index/stress_hnsw_mt.cpp
+++ b/searchlib/src/tests/tensor/hnsw_index/stress_hnsw_mt.cpp
@@ -1,13 +1,5 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <fcntl.h>
-#include <cstdio>
-#include <unistd.h>
-#include <chrono>
-#include <cstdlib>
-#include <future>
-#include <vector>
-
#include <vespa/eval/eval/typed_cells.h>
#include <vespa/eval/eval/value_type.h>
#include <vespa/searchlib/common/bitvector.h>
@@ -25,6 +17,9 @@
#include <vespa/vespalib/util/lambdatask.h>
#include <vespa/vespalib/util/size_literals.h>
#include <vespa/vespalib/data/simple_buffer.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <future>
#include <vespa/log/log.h>
LOG_SETUP("stress_hnsw_mt");
@@ -119,17 +114,17 @@ public:
memcpy(&_vectors[docid], vec.cbegin(), sizeof(MallocPointVector));
return *this;
}
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override {
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override {
assert(docid < NUM_POSSIBLE_DOCS);
(void) subspace;
ConstVectorRef ref(_vectors[docid]);
return vespalib::eval::TypedCells(ref);
}
- VectorBundle get_vectors(uint32_t docid) const override {
+ VectorBundle get_vectors(uint32_t docid) const noexcept override {
assert(docid < NUM_POSSIBLE_DOCS);
ConstVectorRef ref(_vectors[docid]);
assert(subspace_type.size() == ref.size());
- return VectorBundle(ref.data(), 1, subspace_type);
+ return {ref.data(), 1, subspace_type};
}
};
@@ -257,7 +252,7 @@ public:
loaded_vectors.load();
}
- ~Stressor() {}
+ ~Stressor() override;
auto dff() {
return search::tensor::make_distance_function_factory(
@@ -352,6 +347,9 @@ public:
}
};
+template <typename IndexType>
+Stressor<IndexType>::~Stressor() = default;
+
using StressorTypes = ::testing::Types<HnswIndex<HnswIndexType::SINGLE>>;
TYPED_TEST_SUITE(Stressor, StressorTypes);
diff --git a/searchlib/src/vespa/searchlib/features/closenessfeature.cpp b/searchlib/src/vespa/searchlib/features/closenessfeature.cpp
index b0955fe60bd..d19b979c360 100644
--- a/searchlib/src/vespa/searchlib/features/closenessfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/closenessfeature.cpp
@@ -52,7 +52,7 @@ ConvertRawScoreToCloseness::execute(uint32_t docId)
feature_t converted = tfmd->getRawScore();
max_closeness = std::max(max_closeness, converted);
} else if (elem.calc) {
- feature_t converted = elem.calc->calc_raw_score(docId);
+ feature_t converted = elem.calc->calc_raw_score<false>(docId);
max_closeness = std::max(max_closeness, converted);
}
}
diff --git a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.cpp b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.cpp
index d28f6077905..c76fe3363e4 100644
--- a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.cpp
@@ -19,17 +19,17 @@ namespace search::queryeval {
* Keeps a heap of the K best hit distances.
* Currently always does brute-force scanning, which is very expensive.
**/
-template <bool strict, bool has_filter>
-class NearestNeighborImpl : public NearestNeighborIterator
+template <bool strict, bool has_filter, bool has_single_subspace>
+class NearestNeighborImpl final : public NearestNeighborIterator
{
public:
- NearestNeighborImpl(Params params_in)
+ explicit NearestNeighborImpl(Params params_in)
: NearestNeighborIterator(std::move(params_in)),
_lastScore(0.0)
{
}
- ~NearestNeighborImpl();
+ ~NearestNeighborImpl() override;
void doSeek(uint32_t docId) override {
double distanceLimit = params().distanceHeap.distanceLimit();
@@ -61,39 +61,47 @@ public:
private:
double computeDistance(uint32_t docId, double limit) {
- return params().distance_calc->calc_with_limit(docId, limit);
+ return params().distance_calc->template calc_with_limit<has_single_subspace>(docId, limit);
}
double _lastScore;
};
-template <bool strict, bool has_filter>
-NearestNeighborImpl<strict, has_filter>::~NearestNeighborImpl() = default;
+template <bool strict, bool has_filter, bool has_single_subspace>
+NearestNeighborImpl<strict, has_filter, has_single_subspace>::~NearestNeighborImpl() = default;
namespace {
+template <bool strict, bool has_filter>
+std::unique_ptr<NearestNeighborIterator>
+resolve_single_subspace(NearestNeighborIterator::Params params)
+{
+ if (params.distance_calc->has_single_subspace()) {
+ using NNI = NearestNeighborImpl<strict, has_filter, true>;
+ return std::make_unique<NNI>(std::move(params));
+ } else {
+ using NNI = NearestNeighborImpl<strict, has_filter, false>;
+ return std::make_unique<NNI>(std::move(params));
+ }
+}
+
template <bool has_filter>
std::unique_ptr<NearestNeighborIterator>
resolve_strict(bool strict, NearestNeighborIterator::Params params)
{
if (strict) {
- using NNI = NearestNeighborImpl<true, has_filter>;
- return std::make_unique<NNI>(std::move(params));
+ return resolve_single_subspace<true, has_filter>(std::move(params));
} else {
- using NNI = NearestNeighborImpl<false, has_filter>;
- return std::make_unique<NNI>(std::move(params));
+ return resolve_single_subspace<false, has_filter>(std::move(params));
}
}
} // namespace <unnamed>
std::unique_ptr<NearestNeighborIterator>
-NearestNeighborIterator::create(
- bool strict,
- fef::TermFieldMatchData &tfmd,
- std::unique_ptr<search::tensor::DistanceCalculator> distance_calc,
- NearestNeighborDistanceHeap &distanceHeap,
- const GlobalFilter &filter)
+NearestNeighborIterator::create(bool strict, fef::TermFieldMatchData &tfmd,
+ std::unique_ptr<search::tensor::DistanceCalculator> distance_calc,
+ NearestNeighborDistanceHeap &distanceHeap, const GlobalFilter &filter)
{
Params params(tfmd, std::move(distance_calc), distanceHeap, filter);
if (filter.is_active()) {
diff --git a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.h b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.h
index b34c9df47b9..177c732a44d 100644
--- a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.h
+++ b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_iterator.h
@@ -39,7 +39,7 @@ public:
{}
};
- NearestNeighborIterator(Params params_in)
+ explicit NearestNeighborIterator(Params params_in)
: _params(std::move(params_in))
{}
diff --git a/searchlib/src/vespa/searchlib/tensor/bound_distance_function.h b/searchlib/src/vespa/searchlib/tensor/bound_distance_function.h
index c89619d9a77..2865f5f55e6 100644
--- a/searchlib/src/vespa/searchlib/tensor/bound_distance_function.h
+++ b/searchlib/src/vespa/searchlib/tensor/bound_distance_function.h
@@ -25,14 +25,13 @@ public:
BoundDistanceFunction() = default;
- virtual ~BoundDistanceFunction() = default;
+ ~BoundDistanceFunction() override = default;
// calculate internal distance (comparable)
virtual double calc(const vespalib::eval::TypedCells& rhs) const = 0;
// calculate internal distance, early return allowed if > limit
- virtual double calc_with_limit(const vespalib::eval::TypedCells& rhs,
- double limit) const = 0;
+ virtual double calc_with_limit(const vespalib::eval::TypedCells& rhs, double limit) const = 0;
};
}
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
index fb74dd51fa3..0dbb9c34010 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
@@ -30,14 +30,14 @@ DenseTensorAttribute::extract_cells_ref(DocId docId) const
}
vespalib::eval::TypedCells
-DenseTensorAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+DenseTensorAttribute::get_vector(uint32_t docid, uint32_t subspace) const noexcept
{
EntryRef ref = (subspace == 0) ? acquire_entry_ref(docid) : EntryRef();
return _denseTensorStore.get_typed_cells(ref);
}
VectorBundle
-DenseTensorAttribute::get_vectors(uint32_t docid) const
+DenseTensorAttribute::get_vectors(uint32_t docid) const noexcept
{
EntryRef ref = acquire_entry_ref(docid);
return _denseTensorStore.get_vectors(ref);
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
index 03c976bd6b3..c07bfcc358e 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
@@ -26,8 +26,8 @@ public:
bool supports_extract_cells_ref() const override { return true; }
// Implements DocVectorAccess
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
- VectorBundle get_vectors(uint32_t docid) const override;
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override;
+ VectorBundle get_vectors(uint32_t docid) const noexcept override;
};
}
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.cpp
index 12dd6aa2bca..cf0e9adc095 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.cpp
@@ -74,7 +74,7 @@ DirectTensorAttribute::get_tensor_ref(DocId docId) const
}
vespalib::eval::TypedCells
-DirectTensorAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+DirectTensorAttribute::get_vector(uint32_t docid, uint32_t subspace) const noexcept
{
EntryRef ref = acquire_entry_ref(docid);
auto vectors = _direct_store.get_vectors(ref);
@@ -82,7 +82,7 @@ DirectTensorAttribute::get_vector(uint32_t docid, uint32_t subspace) const
}
VectorBundle
-DirectTensorAttribute::get_vectors(uint32_t docid) const
+DirectTensorAttribute::get_vectors(uint32_t docid) const noexcept
{
EntryRef ref = acquire_entry_ref(docid);
return _direct_store.get_vectors(ref);
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.h b/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.h
index a4f673ea99f..64f62650615 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_attribute.h
@@ -26,8 +26,8 @@ public:
bool supports_get_tensor_ref() const override { return true; }
// Implements DocVectorAccess
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
- VectorBundle get_vectors(uint32_t docid) const override;
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override;
+ VectorBundle get_vectors(uint32_t docid) const noexcept override;
};
} // namespace search::tensor
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
index 44bbbba65d6..6edb654d5bf 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
@@ -42,11 +42,11 @@ private:
EntryRef add_entry(TensorSP tensor);
public:
- DirectTensorStore(const vespalib::eval::ValueType& tensor_type);
+ explicit DirectTensorStore(const vespalib::eval::ValueType& tensor_type);
~DirectTensorStore() override;
using RefType = TensorStoreType::RefType;
- const vespalib::eval::Value * get_tensor_ptr(EntryRef ref) const {
+ const vespalib::eval::Value * get_tensor_ptr(EntryRef ref) const noexcept {
if (!ref.valid()) {
return nullptr;
}
@@ -65,12 +65,12 @@ public:
vespalib::eval::TypedCells get_empty_subspace() const noexcept {
return _empty.cells();
}
- VectorBundle get_vectors(EntryRef ref) const {
+ VectorBundle get_vectors(EntryRef ref) const noexcept {
auto tensor = get_tensor_ptr(ref);
if (tensor == nullptr) {
- return VectorBundle();
+ return {};
}
- return VectorBundle(tensor->cells().data, tensor->index().size(), _subspace_type);
+ return {tensor->cells().data, static_cast<uint32_t>(tensor->index().size()), _subspace_type};
}
};
diff --git a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
index eab75537071..9848c1caca8 100644
--- a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
+++ b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
@@ -36,27 +36,44 @@ public:
assert(_query_tensor != nullptr);
return *_query_tensor;
}
- const BoundDistanceFunction& function() const { return *_dist_fun; }
+ const BoundDistanceFunction& function() const noexcept { return *_dist_fun; }
+ bool has_single_subspace() const noexcept { return _attr_tensor.getTensorType().is_dense(); }
+ template<bool has_single_subspace=false>
double calc_raw_score(uint32_t docid) const {
- auto vectors = _attr_tensor.get_vectors(docid);
- double result = _dist_fun->min_rawscore();
- for (uint32_t i = 0; i < vectors.subspaces(); ++i) {
- double distance = _dist_fun->calc(vectors.cells(i));
- double score = _dist_fun->to_rawscore(distance);
- result = std::max(result, score);
+ if (has_single_subspace) {
+ double distance = _dist_fun->calc(_attr_tensor.get_vector(docid, 0));
+ return _dist_fun->to_rawscore(distance);
+ } else {
+ auto vectors = _attr_tensor.get_vectors(docid);
+ double result = _dist_fun->min_rawscore();
+ for (uint32_t i = 0; i < vectors.subspaces(); ++i) {
+ double distance = _dist_fun->calc(vectors.cells(i));
+ double score = _dist_fun->to_rawscore(distance);
+ result = std::max(result, score);
+ }
+ return result;
}
- return result;
+
}
+ template<bool has_single_subspace>
double calc_with_limit(uint32_t docid, double limit) const {
- auto vectors = _attr_tensor.get_vectors(docid);
- double result = std::numeric_limits<double>::max();
- for (uint32_t i = 0; i < vectors.subspaces(); ++i) {
- double distance = _dist_fun->calc_with_limit(vectors.cells(i), limit);
- result = std::min(result, distance);
+ if (has_single_subspace) {
+ auto cells = _attr_tensor.get_vector(docid, 0);
+ if (cells.size == 0) [[unlikely]] {
+ return std::numeric_limits<double>::max();
+ }
+ return _dist_fun->calc_with_limit(cells, limit);
+ } else {
+ auto vectors = _attr_tensor.get_vectors(docid);
+ double result = std::numeric_limits<double>::max();
+ for (uint32_t i = 0; i < vectors.subspaces(); ++i) {
+ double distance = _dist_fun->calc_with_limit(vectors.cells(i), limit);
+ result = std::min(result, distance);
+ }
+ return result;
}
- return result;
}
void calc_closest_subspace(VectorBundle vectors, std::optional<uint32_t>& closest_subspace, double& best_distance) {
diff --git a/searchlib/src/vespa/searchlib/tensor/doc_vector_access.h b/searchlib/src/vespa/searchlib/tensor/doc_vector_access.h
index 477d5e1dc8a..dd68171dd59 100644
--- a/searchlib/src/vespa/searchlib/tensor/doc_vector_access.h
+++ b/searchlib/src/vespa/searchlib/tensor/doc_vector_access.h
@@ -16,9 +16,9 @@ class VectorBundle;
*/
class DocVectorAccess {
public:
- virtual ~DocVectorAccess() {}
- virtual vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const = 0;
- virtual VectorBundle get_vectors(uint32_t docid) const = 0;
+ virtual ~DocVectorAccess() = default;
+ virtual vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept = 0;
+ virtual VectorBundle get_vectors(uint32_t docid) const noexcept = 0;
};
}
diff --git a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
index cfc420d9ecd..d581dbd129e 100644
--- a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
@@ -10,7 +10,8 @@ EmptySubspace::EmptySubspace(const SubspaceType& type)
_cells()
{
_empty_space.resize(type.mem_size());
- _cells = vespalib::eval::TypedCells(&_empty_space[0], type.cell_type(), type.size());
+ // Set size to zero to signal empty/invalid subspace
+ _cells = vespalib::eval::TypedCells(&_empty_space[0], type.cell_type(), 0);
}
EmptySubspace::~EmptySubspace() = default;
diff --git a/searchlib/src/vespa/searchlib/tensor/empty_subspace.h b/searchlib/src/vespa/searchlib/tensor/empty_subspace.h
index dd0ab9264c4..4043ec122e6 100644
--- a/searchlib/src/vespa/searchlib/tensor/empty_subspace.h
+++ b/searchlib/src/vespa/searchlib/tensor/empty_subspace.h
@@ -10,7 +10,7 @@ namespace search::tensor {
class SubspaceType;
/*
- * Class containg an empty subspace, used as a bad fallback when we cannot
+ * Class containing an empty subspace, used as a bad fallback when we cannot
* get a real subspace.
*/
class EmptySubspace
diff --git a/searchlib/src/vespa/searchlib/tensor/hamming_distance.cpp b/searchlib/src/vespa/searchlib/tensor/hamming_distance.cpp
index a1dc8cc52f7..659e2cae372 100644
--- a/searchlib/src/vespa/searchlib/tensor/hamming_distance.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/hamming_distance.cpp
@@ -38,7 +38,7 @@ private:
mutable TemporaryVectorStore<FloatType> _tmpSpace;
const vespalib::ConstArrayRef<FloatType> _lhs_vector;
public:
- BoundHammingDistance(const vespalib::eval::TypedCells& lhs)
+ explicit BoundHammingDistance(const vespalib::eval::TypedCells& lhs)
: _tmpSpace(lhs.size),
_lhs_vector(_tmpSpace.storeLhs(lhs))
{}
@@ -62,8 +62,7 @@ public:
return threshold;
}
double to_rawscore(double distance) const override {
- double score = 1.0 / (1.0 + distance);
- return score;
+ return 1.0 / (1.0 + distance);
}
double calc_with_limit(const vespalib::eval::TypedCells& rhs, double) const override {
// consider optimizing:
diff --git a/searchlib/src/vespa/searchlib/tensor/i_tensor_attribute.h b/searchlib/src/vespa/searchlib/tensor/i_tensor_attribute.h
index 1f2da032619..b48ec93c10e 100644
--- a/searchlib/src/vespa/searchlib/tensor/i_tensor_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/i_tensor_attribute.h
@@ -21,7 +21,7 @@ class SerializedTensorRef;
*/
class ITensorAttribute : public DocVectorAccess {
public:
- virtual ~ITensorAttribute() {}
+ virtual ~ITensorAttribute() = default;
virtual std::unique_ptr<vespalib::eval::Value> getTensor(uint32_t docId) const = 0;
virtual std::unique_ptr<vespalib::eval::Value> getEmptyTensor() const = 0;
virtual vespalib::eval::TypedCells extract_cells_ref(uint32_t docid) const = 0;
diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp
index 5ad6224f6d4..223a0a5750f 100644
--- a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp
@@ -28,9 +28,7 @@ ImportedTensorAttributeVectorReadGuard::ImportedTensorAttributeVectorReadGuard(s
{
}
-ImportedTensorAttributeVectorReadGuard::~ImportedTensorAttributeVectorReadGuard()
-{
-}
+ImportedTensorAttributeVectorReadGuard::~ImportedTensorAttributeVectorReadGuard() = default;
const ITensorAttribute *
ImportedTensorAttributeVectorReadGuard::asTensorAttribute() const
@@ -63,13 +61,13 @@ ImportedTensorAttributeVectorReadGuard::get_tensor_ref(uint32_t docid) const
}
vespalib::eval::TypedCells
-ImportedTensorAttributeVectorReadGuard::get_vector(uint32_t docid, uint32_t subspace) const
+ImportedTensorAttributeVectorReadGuard::get_vector(uint32_t docid, uint32_t subspace) const noexcept
{
return _target_tensor_attribute.get_vector(getTargetLid(docid), subspace);
}
search::tensor::VectorBundle
-ImportedTensorAttributeVectorReadGuard::get_vectors(uint32_t docid) const
+ImportedTensorAttributeVectorReadGuard::get_vectors(uint32_t docid) const noexcept
{
return _target_tensor_attribute.get_vectors(getTargetLid(docid));
}
diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h
index e07de5486b6..5e6bf8961df 100644
--- a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h
+++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h
@@ -27,7 +27,7 @@ public:
ImportedTensorAttributeVectorReadGuard(std::shared_ptr<MetaStoreReadGuard> targetMetaStoreReadGuard,
const attribute::ImportedAttributeVector &imported_attribute,
bool stableEnumGuard);
- ~ImportedTensorAttributeVectorReadGuard();
+ ~ImportedTensorAttributeVectorReadGuard() override;
const ITensorAttribute *asTensorAttribute() const override;
@@ -45,8 +45,8 @@ public:
bool supports_get_serialized_tensor_ref() const override;
uint32_t get_num_docs() const override { return getNumDocs(); }
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
- VectorBundle get_vectors(uint32_t docid) const override;
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override;
+ VectorBundle get_vectors(uint32_t docid) const noexcept override;
const vespalib::eval::ValueType &getTensorType() const override;
void get_state(const vespalib::slime::Inserter& inserter) const override;
diff --git a/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.cpp
index 75927112b89..3c1bb51f4ea 100644
--- a/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.cpp
@@ -42,7 +42,7 @@ SerializedFastValueAttribute::supports_get_serialized_tensor_ref() const
}
vespalib::eval::TypedCells
-SerializedFastValueAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+SerializedFastValueAttribute::get_vector(uint32_t docid, uint32_t subspace) const noexcept
{
EntryRef ref = acquire_entry_ref(docid);
auto vectors = _tensorBufferStore.get_vectors(ref);
@@ -50,7 +50,7 @@ SerializedFastValueAttribute::get_vector(uint32_t docid, uint32_t subspace) cons
}
VectorBundle
-SerializedFastValueAttribute::get_vectors(uint32_t docid) const
+SerializedFastValueAttribute::get_vectors(uint32_t docid) const noexcept
{
EntryRef ref = acquire_entry_ref(docid);
return _tensorBufferStore.get_vectors(ref);
diff --git a/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.h b/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.h
index 386b0d91add..43b5a23d176 100644
--- a/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/serialized_fast_value_attribute.h
@@ -27,8 +27,8 @@ public:
bool supports_get_serialized_tensor_ref() const override;
// Implements DocVectorAccess
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
- VectorBundle get_vectors(uint32_t docid) const override;
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override;
+ VectorBundle get_vectors(uint32_t docid) const noexcept override;
};
}
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_buffer_operations.h b/searchlib/src/vespa/searchlib/tensor/tensor_buffer_operations.h
index 9a2192cf736..b93249b7e21 100644
--- a/searchlib/src/vespa/searchlib/tensor/tensor_buffer_operations.h
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_buffer_operations.h
@@ -105,18 +105,18 @@ public:
vespalib::eval::TypedCells get_empty_subspace() const noexcept {
return _empty.cells();
}
- VectorBundle get_vectors(vespalib::ConstArrayRef<char> buf) const {
+ VectorBundle get_vectors(vespalib::ConstArrayRef<char> buf) const noexcept {
auto num_subspaces = get_num_subspaces(buf);
auto cells_mem_size = get_cells_mem_size(num_subspaces);
auto aligner = select_aligner(cells_mem_size);
- return VectorBundle(buf.data() + get_cells_offset(num_subspaces, aligner), num_subspaces, _subspace_type);
+ return {buf.data() + get_cells_offset(num_subspaces, aligner), num_subspaces, _subspace_type};
}
- SerializedTensorRef get_serialized_tensor_ref(vespalib::ConstArrayRef<char> buf) const {
+ SerializedTensorRef get_serialized_tensor_ref(vespalib::ConstArrayRef<char> buf) const noexcept {
auto num_subspaces = get_num_subspaces(buf);
auto cells_mem_size = get_cells_mem_size(num_subspaces);
auto aligner = select_aligner(cells_mem_size);
vespalib::ConstArrayRef<vespalib::string_id> labels(reinterpret_cast<const vespalib::string_id*>(buf.data() + get_labels_offset()), num_subspaces * _num_mapped_dimensions);
- return SerializedTensorRef(VectorBundle(buf.data() + get_cells_offset(num_subspaces, aligner), num_subspaces, _subspace_type), _num_mapped_dimensions, labels);
+ return {VectorBundle(buf.data() + get_cells_offset(num_subspaces, aligner), num_subspaces, _subspace_type), _num_mapped_dimensions, labels};
}
bool is_dense() const noexcept { return _num_mapped_dimensions == 0; }
};
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_buffer_store.h b/searchlib/src/vespa/searchlib/tensor/tensor_buffer_store.h
index c8d96adc220..07275c77566 100644
--- a/searchlib/src/vespa/searchlib/tensor/tensor_buffer_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_buffer_store.h
@@ -41,16 +41,16 @@ public:
vespalib::eval::TypedCells get_empty_subspace() const noexcept {
return _ops.get_empty_subspace();
}
- VectorBundle get_vectors(EntryRef ref) const {
+ VectorBundle get_vectors(EntryRef ref) const noexcept {
if (!ref.valid()) {
- return VectorBundle();
+ return {};
}
auto buf = _array_store.get(ref);
return _ops.get_vectors(buf);
}
- SerializedTensorRef get_serialized_tensor_ref(EntryRef ref) const {
+ SerializedTensorRef get_serialized_tensor_ref(EntryRef ref) const noexcept {
if (!ref.valid()) {
- return SerializedTensorRef();
+ return {};
}
auto buf = _array_store.get(ref);
return _ops.get_serialized_tensor_ref(buf);
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
index 1f85dba6afe..716d54d0a71 100644
--- a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
@@ -86,20 +86,20 @@ TensorExtAttribute::getExtendInterface()
}
TypedCells
-TensorExtAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+TensorExtAttribute::get_vector(uint32_t docid, uint32_t subspace) const noexcept
{
auto vectors = get_vectors(docid);
return (subspace < vectors.subspaces()) ? vectors.cells(subspace) : _empty.cells();
}
VectorBundle
-TensorExtAttribute::get_vectors(uint32_t docid) const
+TensorExtAttribute::get_vectors(uint32_t docid) const noexcept
{
auto tensor = _data[docid];
if (tensor == nullptr) {
- return VectorBundle();
+ return {};
}
- return VectorBundle(tensor->cells().data, tensor->index().size(), _subspace_type);
+ return {tensor->cells().data, static_cast<uint32_t>(tensor->index().size()), _subspace_type};
}
std::unique_ptr<Value>
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
index 890b568c26e..0434c2ab65f 100644
--- a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
@@ -37,8 +37,8 @@ public:
bool add(const vespalib::eval::Value& v, int32_t) override;
IExtendAttribute* getExtendInterface() override;
// DocVectorAccess API
- vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
- VectorBundle get_vectors(uint32_t docid) const override;
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const noexcept override;
+ VectorBundle get_vectors(uint32_t docid) const noexcept override;
// ITensorAttribute API
std::unique_ptr<vespalib::eval::Value> getTensor(uint32_t docid) const override;
diff --git a/searchlib/src/vespa/searchlib/tensor/vector_bundle.h b/searchlib/src/vespa/searchlib/tensor/vector_bundle.h
index 7ff7ea943de..087c0f43b60 100644
--- a/searchlib/src/vespa/searchlib/tensor/vector_bundle.h
+++ b/searchlib/src/vespa/searchlib/tensor/vector_bundle.h
@@ -40,7 +40,7 @@ public:
uint32_t subspaces() const noexcept { return _subspaces; }
vespalib::eval::TypedCells cells(uint32_t subspace) const noexcept {
assert(subspace < _subspaces);
- return vespalib::eval::TypedCells(static_cast<const char*>(_data) + _subspace_mem_size * subspace, _cell_type, _subspace_size);
+ return {static_cast<const char*>(_data) + _subspace_mem_size * subspace, _cell_type, _subspace_size};
}
};
diff --git a/streamingvisitors/src/vespa/vsm/searcher/nearest_neighbor_field_searcher.cpp b/streamingvisitors/src/vespa/vsm/searcher/nearest_neighbor_field_searcher.cpp
index 816317bf86d..2fd23100f46 100644
--- a/streamingvisitors/src/vespa/vsm/searcher/nearest_neighbor_field_searcher.cpp
+++ b/streamingvisitors/src/vespa/vsm/searcher/nearest_neighbor_field_searcher.cpp
@@ -131,7 +131,7 @@ NearestNeighborFieldSearcher::onValue(const document::FieldValue& fv)
_attr->add(*tfv->getAsTensorPtr(), 1);
for (auto& elem : _calcs) {
double distance_limit = elem->heap.distanceLimit();
- double distance = elem->calc->calc_with_limit(scratch_docid, distance_limit);
+ double distance = elem->calc->calc_with_limit<false>(scratch_docid, distance_limit);
if (distance <= distance_limit) {
elem->node->set_distance(distance);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store.h b/vespalib/src/vespa/vespalib/datastore/array_store.h
index 4549b81283e..51a1f9fe950 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store.h
+++ b/vespalib/src/vespa/vespalib/datastore/array_store.h
@@ -94,7 +94,7 @@ private:
EntryRef allocate_dynamic_array(size_t array_size, uint32_t type_id);
EntryRef addLargeArray(ConstArrayRef array);
EntryRef allocate_large_array(size_t array_size);
- ConstArrayRef getSmallArray(RefT ref, size_t arraySize) const {
+ ConstArrayRef getSmallArray(RefT ref, size_t arraySize) const noexcept {
const ElemT *buf = _store.template getEntryArray<ElemT>(ref, arraySize);
return ConstArrayRef(buf, arraySize);
}
@@ -104,7 +104,7 @@ private:
auto size = BufferType::get_dynamic_array_size(entry);
return ConstArrayRef(entry, size);
}
- ConstArrayRef getLargeArray(RefT ref) const {
+ ConstArrayRef getLargeArray(RefT ref) const noexcept {
const LargeArray *buf = _store.template getEntry<LargeArray>(ref);
return ConstArrayRef(&(*buf)[0], buf->size());
}
@@ -114,7 +114,7 @@ public:
ArrayStore(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator, TypeMapper&& mapper);
~ArrayStore() override;
EntryRef add(ConstArrayRef array);
- ConstArrayRef get(EntryRef ref) const {
+ ConstArrayRef get(EntryRef ref) const noexcept {
if (!ref.valid()) [[unlikely]] {
return ConstArrayRef();
}
diff --git a/vespalib/src/vespa/vespalib/datastore/datastore.h b/vespalib/src/vespa/vespalib/datastore/datastore.h
index fa231e9cf94..0226c780cf1 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastore.h
+++ b/vespalib/src/vespa/vespalib/datastore/datastore.h
@@ -96,7 +96,7 @@ public:
EntryRef addEntry(const EntryType &e);
- const EntryType &getEntry(EntryRef ref) const {
+ const EntryType &getEntry(EntryRef ref) const noexcept {
return *this->template getEntry<EntryType>(RefType(ref));
}
};