aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2024-04-25 16:26:29 +0200
committerGitHub <noreply@github.com>2024-04-25 16:26:29 +0200
commit16ac700c95696e3c22c123816428ac877a86f233 (patch)
tree7e8e7189bde358e4e650b351e99eb6fa7c4b791d
parentcccd53e6df76e2abc9adf9a7f8cc47cff17ef736 (diff)
parente9c1e954efcc991ac9b0ada1be3d908b5cfa1905 (diff)
Merge pull request #31046 from vespa-engine/balder/use-non_existing_attibute_value-flag
Use non_existing_attribute_value to signal that value is the default … MERGEOK
-rw-r--r--eval/src/tests/eval/typed_cells/typed_cells_test.cpp185
-rw-r--r--eval/src/vespa/eval/eval/typed_cells.h17
-rw-r--r--searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp2
-rw-r--r--searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp13
-rw-r--r--searchlib/src/vespa/searchlib/tensor/distance_calculator.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp4
7 files changed, 116 insertions, 113 deletions
diff --git a/eval/src/tests/eval/typed_cells/typed_cells_test.cpp b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp
index f4171937ce3..53e0f7c84d3 100644
--- a/eval/src/tests/eval/typed_cells/typed_cells_test.cpp
+++ b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp
@@ -1,39 +1,13 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/eval/eval/typed_cells.h>
#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/vespalib/util/arrayref.h>
#include <memory>
using namespace vespalib;
+using namespace eval;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// Low-level typed cells reference
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-enum class CellType : char { DOUBLE, FLOAT, INT };
-template <typename T> bool check_type(CellType type);
-template <> bool check_type<double>(CellType type) { return (type == CellType::DOUBLE); }
-template <> bool check_type<float>(CellType type) { return (type == CellType::FLOAT); }
-template <> bool check_type<int>(CellType type) { return (type == CellType::INT); }
-
-struct TypedCells {
- const void *data;
- CellType type;
- size_t size:56;
- explicit TypedCells(ConstArrayRef<double> cells) : data(cells.begin()), type(CellType::DOUBLE), size(cells.size()) {}
- explicit TypedCells(ConstArrayRef<float> cells) : data(cells.begin()), type(CellType::FLOAT), size(cells.size()) {}
- explicit TypedCells(ConstArrayRef<int> cells) : data(cells.begin()), type(CellType::INT), size(cells.size()) {}
- template <typename T> bool check_type() const { return ::check_type<T>(type); }
- template <typename T> ConstArrayRef<T> typify() const {
- assert(check_type<T>());
- return ConstArrayRef<T>((const T *)data, size);
- }
- template <typename T> ConstArrayRef<T> unsafe_typify() const {
- return ConstArrayRef<T>((const T *)data, size);
- }
-};
TEST("require that structures are of expected size") {
EXPECT_EQUAL(sizeof(void*), 8u);
@@ -102,27 +76,27 @@ struct Typify {
switch(a.type) {
case CellType::DOUBLE: return T::call(a.unsafe_typify<double>(), std::forward<Args>(args)...);
case CellType::FLOAT: return T::call(a.unsafe_typify<float>(), std::forward<Args>(args)...);
- case CellType::INT: return T::call(a.unsafe_typify<int>(), std::forward<Args>(args)...);
+ case CellType::INT8: return T::call(a.unsafe_typify<Int8Float>(), std::forward<Args>(args)...);
+ default: abort();
}
- abort();
}
template <typename A, typename... Args>
static auto typify_2(A &&a, const TypedCells &b, Args &&...args) {
switch(b.type) {
case CellType::DOUBLE: return T::call(std::forward<A>(a), b.unsafe_typify<double>(), std::forward<Args>(args)...);
case CellType::FLOAT: return T::call(std::forward<A>(a), b.unsafe_typify<float>(), std::forward<Args>(args)...);
- case CellType::INT: return T::call(std::forward<A>(a), b.unsafe_typify<int>(), std::forward<Args>(args)...);
+ case CellType::INT8: return T::call(std::forward<A>(a), b.unsafe_typify<Int8Float>(), std::forward<Args>(args)...);
+ default: abort();
}
- abort();
}
template <typename A, typename B, typename... Args>
static auto typify_3(A &&a, B &&b, const TypedCells &c, Args &&...args) {
switch(c.type) {
case CellType::DOUBLE: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<double>(), std::forward<Args>(args)...);
case CellType::FLOAT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<float>(), std::forward<Args>(args)...);
- case CellType::INT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<int>(), std::forward<Args>(args)...);
+ case CellType::INT8: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<Int8Float>(), std::forward<Args>(args)...);
+ default: abort();
}
- abort();
}
};
@@ -200,15 +174,15 @@ struct Dispatch1 {
//-----------------------------------------------------------------------------
TEST("require that direct dispatch 'a op b -> c' works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- std::vector<double> c(3, 0.0);
- ConstArrayRef<int> a_ref(a);
- ConstArrayRef<float> b_ref(b);
- ConstArrayRef<double> c_ref(c);
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- TypedCells c_cells(c);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ std::vector<double> c(3, 0.0);
+ ConstArrayRef<Int8Float> a_ref(a);
+ ConstArrayRef<float> b_ref(b);
+ ConstArrayRef<double> c_ref(c);
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ TypedCells c_cells(c);
Dispatch3<CellwiseAdd>::call(a_cells, b_cells, c_cells, 3);
Dispatch3<CellwiseAdd>::call(a_cells, b_ref, c_cells, 3);
@@ -225,13 +199,13 @@ TEST("require that direct dispatch 'a op b -> c' works") {
}
TEST("require that direct dispatch 'dot product' with return value works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- ConstArrayRef<int> a_ref(a);
- ConstArrayRef<float> b_ref(b);
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ ConstArrayRef<Int8Float> a_ref(a);
+ ConstArrayRef<float> b_ref(b);
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_cells, 3));
EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_ref, 3));
@@ -240,10 +214,10 @@ TEST("require that direct dispatch 'dot product' with return value works") {
}
TEST("require that direct dispatch 'sum' with return value works") {
- std::vector<int> a({1,2,3});
- ConstArrayRef<int> a_ref(a);
- TypedCells a_cells(a);
- double expect = (1 + 2 + 3);
+ std::vector<Int8Float> a({1,2,3});
+ ConstArrayRef<Int8Float> a_ref(a);
+ TypedCells a_cells(a);
+ double expect = (1 + 2 + 3);
EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_cells));
EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_ref));
@@ -259,7 +233,7 @@ struct CellwiseAdd2 {
virtual void call(const TypedCells &a, const TypedCells &b, const TypedCells &c, size_t cnt) const = 0;
template <typename A, typename B, typename C>
static std::unique_ptr<CellwiseAdd2> create();
- virtual ~CellwiseAdd2() {}
+ virtual ~CellwiseAdd2() = default;
};
template <typename A, typename B, typename C>
@@ -286,7 +260,7 @@ struct DotProduct2 {
virtual double call(const TypedCells &a, const TypedCells &b, size_t cnt) const = 0;
template <typename A, typename B>
static std::unique_ptr<DotProduct2> create();
- virtual ~DotProduct2() {}
+ virtual ~DotProduct2() = default;
};
template <typename A, typename B>
@@ -314,7 +288,7 @@ struct Sum2 {
virtual double call(const TypedCells &a) const = 0;
template <typename A>
static std::unique_ptr<Sum2> create();
- virtual ~Sum2() {}
+ virtual ~Sum2() = default;
};
template <typename A>
@@ -343,9 +317,9 @@ std::unique_ptr<T> create(CellType a_type) {
switch(a_type) {
case CellType::DOUBLE: return T::template create<double, Args...>();
case CellType::FLOAT: return T::template create<float, Args...>();
- case CellType::INT: return T::template create<int, Args...>();
+ case CellType::INT8: return T::template create<Int8Float, Args...>();
+ default: abort();
}
- abort();
}
template <typename T, typename... Args>
@@ -353,9 +327,9 @@ std::unique_ptr<T> create(CellType a_type, CellType b_type) {
switch(b_type) {
case CellType::DOUBLE: return create<T, double, Args...>(a_type);
case CellType::FLOAT: return create<T, float, Args...>(a_type);
- case CellType::INT: return create<T, int, Args...>(a_type);
+ case CellType::INT8: return create<T, Int8Float, Args...>(a_type);
+ default: abort();
}
- abort();
}
template <typename T>
@@ -363,20 +337,20 @@ std::unique_ptr<T> create(CellType a_type, CellType b_type, CellType c_type) {
switch(c_type) {
case CellType::DOUBLE: return create<T, double>(a_type, b_type);
case CellType::FLOAT: return create<T, float>(a_type, b_type);
- case CellType::INT: return create<T, int>(a_type, b_type);
+ case CellType::INT8: return create<T, Int8Float>(a_type, b_type);
+ default: abort();
}
- abort();
}
//-----------------------------------------------------------------------------
TEST("require that pre-resolved subclass 'a op b -> c' works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- std::vector<double> c(3, 0.0);
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- TypedCells c_cells(c);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ std::vector<double> c(3, 0.0);
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ TypedCells c_cells(c);
auto op = create<CellwiseAdd2>(a_cells.type, b_cells.type, c_cells.type);
op->call(a_cells, b_cells, c_cells, 3);
@@ -387,11 +361,11 @@ TEST("require that pre-resolved subclass 'a op b -> c' works") {
}
TEST("require that pre-resolved subclass 'dot product' with return value works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
auto op = create<DotProduct2>(a_cells.type, b_cells.type);
@@ -399,9 +373,9 @@ TEST("require that pre-resolved subclass 'dot product' with return value works")
}
TEST("require that pre-resolved subclass 'sum' with return value works") {
- std::vector<int> a({1,2,3});
- TypedCells a_cells(a);
- double expect = (1 + 2 + 3);
+ std::vector<Int8Float> a({1,2,3});
+ TypedCells a_cells(a);
+ double expect = (1 + 2 + 3);
auto op = create<Sum2>(a_cells.type);
@@ -419,9 +393,9 @@ auto get_fun(CellType a_type) {
switch(a_type) {
case CellType::DOUBLE: return T::template get_fun<double, Args...>();
case CellType::FLOAT: return T::template get_fun<float, Args...>();
- case CellType::INT: return T::template get_fun<int, Args...>();
+ case CellType::INT8: return T::template get_fun<Int8Float, Args...>();
+ default: abort();
}
- abort();
}
template <typename T, typename... Args>
@@ -429,9 +403,9 @@ auto get_fun(CellType a_type, CellType b_type) {
switch(b_type) {
case CellType::DOUBLE: return get_fun<T, double, Args...>(a_type);
case CellType::FLOAT: return get_fun<T, float, Args...>(a_type);
- case CellType::INT: return get_fun<T, int, Args...>(a_type);
+ case CellType::INT8: return get_fun<T, Int8Float, Args...>(a_type);
+ default: abort();
}
- abort();
}
template <typename T>
@@ -439,9 +413,9 @@ auto get_fun(CellType a_type, CellType b_type, CellType c_type) {
switch(c_type) {
case CellType::DOUBLE: return get_fun<T, double>(a_type, b_type);
case CellType::FLOAT: return get_fun<T, float>(a_type, b_type);
- case CellType::INT: return get_fun<T, int>(a_type, b_type);
+ case CellType::INT8: return get_fun<T, Int8Float>(a_type, b_type);
+ default: abort();
}
- abort();
}
//-----------------------------------------------------------------------------
@@ -575,17 +549,17 @@ Sum3::Self::Self()
//-----------------------------------------------------------------------------
TEST("require that self-updating cached function pointer 'a op b -> c' works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- std::vector<double> c(3, 0.0);
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- TypedCells c_cells(c);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ std::vector<double> c(3, 0.0);
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ TypedCells c_cells(c);
CellwiseAdd3 op;
EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>));
op.call(a_cells, b_cells, c_cells, 3);
- EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<int,float,double>));
+ EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<Int8Float,float,double>));
EXPECT_NOT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>));
EXPECT_EQUAL(c[0], 2.5);
@@ -594,29 +568,40 @@ TEST("require that self-updating cached function pointer 'a op b -> c' works") {
}
TEST("require that self-updating cached function pointer 'dot product' with return value works") {
- std::vector<int> a({1,2,3});
- std::vector<float> b({1.5,2.5,3.5});
- TypedCells a_cells(a);
- TypedCells b_cells(b);
- double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
+ std::vector<Int8Float> a({1,2,3});
+ std::vector<float> b({1.5,2.5,3.5});
+ TypedCells a_cells(a);
+ TypedCells b_cells(b);
+ double expect = 1.5 + (2 * 2.5) + (3 * 3.5);
DotProduct3 op;
EXPECT_EQUAL(op.self.my_fun, (&dot_product<double,double>));
EXPECT_EQUAL(expect, op.call(a_cells, b_cells, 3));
- EXPECT_EQUAL(op.self.my_fun, (&dot_product<int,float>));
+ EXPECT_EQUAL(op.self.my_fun, (&dot_product<Int8Float,float>));
EXPECT_NOT_EQUAL(op.self.my_fun, (&dot_product<double,double>));
}
TEST("require that self-updating cached function pointer 'sum' with return value works") {
- std::vector<int> a({1,2,3});
- TypedCells a_cells(a);
- double expect = (1 + 2 + 3);
+ std::vector<Int8Float> a({1,2,3});
+ TypedCells a_cells(a);
+ double expect = (1 + 2 + 3);
Sum3 op;
EXPECT_EQUAL(op.self.my_fun, (&sum<double>));
EXPECT_EQUAL(expect, op.call(a_cells));
- EXPECT_EQUAL(op.self.my_fun, (&sum<int>));
+ EXPECT_EQUAL(op.self.my_fun, (&sum<Int8Float>));
EXPECT_NOT_EQUAL(op.self.my_fun, (&sum<double>));
}
+TEST("require that non_existing_attribute_value can be controlled") {
+ float values[3] = {0,1,2};
+ EXPECT_FALSE(TypedCells().non_existing_attribute_value());
+ EXPECT_FALSE(TypedCells(values, CellType::FLOAT, 3).non_existing_attribute_value());
+ EXPECT_FALSE(TypedCells(ConstArrayRef<double>()).non_existing_attribute_value());
+ EXPECT_FALSE(TypedCells(ConstArrayRef<float>()).non_existing_attribute_value());
+ EXPECT_FALSE(TypedCells(ConstArrayRef<Int8Float>()).non_existing_attribute_value());
+ EXPECT_FALSE(TypedCells(ConstArrayRef<BFloat16>()).non_existing_attribute_value());
+ EXPECT_TRUE(TypedCells::create_non_existing_attribute_value(values, CellType::FLOAT, 3).non_existing_attribute_value());
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/vespa/eval/eval/typed_cells.h b/eval/src/vespa/eval/eval/typed_cells.h
index 3dd8c30a3a9..7aa7debff30 100644
--- a/eval/src/vespa/eval/eval/typed_cells.h
+++ b/eval/src/vespa/eval/eval/typed_cells.h
@@ -11,7 +11,8 @@ namespace vespalib::eval {
struct TypedCells {
const void *data;
- size_t size:56;
+ size_t size:55;
+ bool _non_existing_attribute_value:1;
CellType type;
explicit TypedCells(ConstArrayRef<double> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::DOUBLE) {}
@@ -22,6 +23,12 @@ struct TypedCells {
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) {}
+ static TypedCells create_non_existing_attribute_value(const void *dp, CellType ct, size_t sz) {
+ TypedCells cells(dp, ct, sz);
+ cells._non_existing_attribute_value = true;
+ return cells;
+ }
+
template <typename T> bool check_type() const noexcept { return check_cell_type<T>(type); }
template <typename T> ConstArrayRef<T> typify() const noexcept {
@@ -36,7 +43,13 @@ struct TypedCells {
TypedCells(const TypedCells &other) noexcept = default;
TypedCells & operator= (TypedCells &&other) noexcept = default;
TypedCells & operator= (const TypedCells &other) noexcept = default;
- bool valid() const noexcept { return size != 0; }
+ /**
+ * This signals that this actually points to a value that is the default value
+ * when no value has set for the attribute.
+ * TODO: This does not belong here, but as it is used as an interface multiple places it must be so
+ * until we come up with a better solution.
+ */
+ bool non_existing_attribute_value() const noexcept { return _non_existing_attribute_value; }
};
} // namespace
diff --git a/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp b/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp
index d67757a3811..0c60b376361 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{};
+ std::vector<double> empty_cells{0, 0};
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/hnsw_index/hnsw_index_test.cpp b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
index 31b147c0b5c..d50677314df 100644
--- a/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
+++ b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp
@@ -12,6 +12,7 @@
#include <vespa/searchlib/tensor/random_level_generator.h>
#include <vespa/searchlib/tensor/inv_log_level_generator.h>
#include <vespa/searchlib/tensor/subspace_type.h>
+#include <vespa/searchlib/tensor/empty_subspace.h>
#include <vespa/searchlib/tensor/vector_bundle.h>
#include <vespa/searchlib/queryeval/global_filter.h>
#include <vespa/vespalib/datastore/compaction_spec.h>
@@ -49,6 +50,7 @@ private:
using ArrayRef = vespalib::ConstArrayRef<FloatType>;
mutable std::vector<Vector> _vectors;
SubspaceType _subspace_type;
+ EmptySubspace _empty;
mutable uint32_t _get_vector_count;
mutable uint32_t _schedule_clear_tensor;
mutable uint32_t _cleared_tensor_docid;
@@ -57,6 +59,7 @@ public:
MyDocVectorAccess()
: _vectors(),
_subspace_type(ValueType::make_type(get_cell_type<FloatType>(), {{"dims", 2}})),
+ _empty(_subspace_type),
_get_vector_count(0),
_schedule_clear_tensor(0),
_cleared_tensor_docid(0)
@@ -87,7 +90,7 @@ public:
if (subspace < bundle.subspaces()) {
return bundle.cells(subspace);
}
- return { nullptr, _subspace_type.cell_type(), 0 };
+ return _empty.cells();
}
VectorBundle get_vectors(uint32_t docid) const noexcept override {
ArrayRef ref(_vectors[docid]);
@@ -128,12 +131,12 @@ public:
double min_rawscore() const noexcept override { return _real->min_rawscore(); }
double calc(TypedCells rhs) const noexcept override {
- EXPECT_TRUE(rhs.valid());
+ EXPECT_FALSE(rhs.non_existing_attribute_value());
return _real->calc(rhs);
}
double calc_with_limit(TypedCells rhs, double limit) const noexcept override {
- EXPECT_TRUE(rhs.valid());
+ EXPECT_FALSE(rhs.non_existing_attribute_value());
return _real->calc_with_limit(rhs, limit);
}
};
@@ -152,12 +155,12 @@ public:
~MyDistanceFunctionFactory() override;
std::unique_ptr<BoundDistanceFunction> for_query_vector(TypedCells lhs) override {
- EXPECT_TRUE(lhs.valid());
+ EXPECT_FALSE(lhs.non_existing_attribute_value());
return std::make_unique<MyBoundDistanceFunction>(_real->for_query_vector(lhs));
}
std::unique_ptr<BoundDistanceFunction> for_insertion_vector(TypedCells lhs) override {
- EXPECT_TRUE(lhs.valid());
+ EXPECT_FALSE(lhs.non_existing_attribute_value());
return std::make_unique<MyBoundDistanceFunction>(_real->for_insertion_vector(lhs));
}
};
diff --git a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
index 7ff9448c5af..1bdd3b39711 100644
--- a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
+++ b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h
@@ -45,7 +45,7 @@ public:
if (has_single_subspace) {
auto cells = _attr_tensor.get_vector(docid, 0);
double min_rawscore = _dist_fun->min_rawscore();
- if ( ! cells.valid() ) [[unlikely]] {
+ if ( cells.non_existing_attribute_value() ) [[unlikely]] {
return min_rawscore;
}
return std::max(min_rawscore, _dist_fun->to_rawscore(_dist_fun->calc(cells)));
@@ -66,7 +66,7 @@ public:
double calc_with_limit(uint32_t docid, double limit) const noexcept {
if (has_single_subspace) {
auto cells = _attr_tensor.get_vector(docid, 0);
- if ( ! cells.valid() ) [[unlikely]] {
+ if ( cells.non_existing_attribute_value() ) [[unlikely]] {
return std::numeric_limits<double>::max();
}
return _dist_fun->calc_with_limit(cells, limit);
diff --git a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
index a7168b5eae6..131dcf05c60 100644
--- a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp
@@ -3,6 +3,8 @@
#include "empty_subspace.h"
#include "subspace_type.h"
+using vespalib::eval::TypedCells;
+
namespace search::tensor {
EmptySubspace::EmptySubspace(const SubspaceType& type)
@@ -11,7 +13,7 @@ EmptySubspace::EmptySubspace(const SubspaceType& type)
{
_empty_space.resize(type.mem_size());
// Set size to zero to signal empty/invalid subspace
- _cells = vespalib::eval::TypedCells(_empty_space.data(), type.cell_type(), 0);
+ _cells = TypedCells::create_non_existing_attribute_value(_empty_space.data(), type.cell_type(), type.size());
}
EmptySubspace::~EmptySubspace() = default;
diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
index cdc3e81782a..1db688156e0 100644
--- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
@@ -183,7 +183,7 @@ bool
HnswIndex<type>::have_closer_distance(HnswTraversalCandidate candidate, const HnswTraversalCandidateVector& result) const
{
auto candidate_vector = get_vector(candidate.nodeid);
- if (!candidate_vector.valid()) {
+ if (candidate_vector.non_existing_attribute_value()) {
/*
* We are in a read thread and the write thread has removed the
* tensor for the candidate. Return true to prevent the candidate
@@ -319,7 +319,7 @@ namespace {
double
calc_distance_helper(const BoundDistanceFunction &df, vespalib::eval::TypedCells rhs)
{
- if (!rhs.valid()) [[unlikely]] {
+ if (rhs.non_existing_attribute_value()) [[unlikely]] {
/*
* We are in a read thread and the write thread has removed the
* tensor.