diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2024-04-16 14:43:23 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2024-04-16 21:19:19 +0000 |
commit | 1862d47ff95d80fbd01ad77d3a79e3283f58603f (patch) | |
tree | 76034222fcc4da75b924b3ed7703aeeac6b02268 | |
parent | 302b8f03d28baef770719f8b73315d78fc6da950 (diff) |
- Optimize distance calculation for tensors with single dense subspace.
- Let EmptySubspace be invalid.
- Add noexcept to get_tensor(s).
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)); } }; |