summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorArne H Juul <arnej27959@users.noreply.github.com>2021-01-12 14:06:47 +0100
committerGitHub <noreply@github.com>2021-01-12 14:06:47 +0100
commit00df4dedab5ea94283cbd2d2f359b01774402ffb (patch)
tree3335023c4c7017c1e77f6f8347d1977a2420c94a /eval
parent1f15e7ef0872f917d6eeeafc0e30cfc904837347 (diff)
parent024d645a666200544465db2b1e8a01b5583b343c (diff)
Merge pull request #16005 from vespa-engine/arnej/optimize-value-copy
Arnej/optimize value copy
Diffstat (limited to 'eval')
-rw-r--r--eval/src/tests/eval/fast_value/fast_value_test.cpp28
-rw-r--r--eval/src/tests/eval/simple_value/simple_value_test.cpp10
-rw-r--r--eval/src/tests/streamed/value/streamed_value_test.cpp10
-rw-r--r--eval/src/vespa/eval/eval/value.cpp48
4 files changed, 93 insertions, 3 deletions
diff --git a/eval/src/tests/eval/fast_value/fast_value_test.cpp b/eval/src/tests/eval/fast_value/fast_value_test.cpp
index 2124d4f169a..279f17a1ead 100644
--- a/eval/src/tests/eval/fast_value/fast_value_test.cpp
+++ b/eval/src/tests/eval/fast_value/fast_value_test.cpp
@@ -3,10 +3,12 @@
#include <vespa/eval/eval/fast_value.hpp>
#include <vespa/eval/eval/fast_value.h>
#include <vespa/eval/eval/value_codec.h>
+#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/vespalib/gtest/gtest.h>
using namespace vespalib;
using namespace vespalib::eval;
+using namespace vespalib::eval::test;
using Handle = SharedStringRepo::Handle;
@@ -140,4 +142,30 @@ TEST(FastValueBuilderTest, mixed_add_subspace_robustness) {
}
}
+std::vector<Layout> layouts = {
+ {},
+ {x(3)},
+ {x(3),y(5)},
+ {x(3),y(5),z(7)},
+ float_cells({x(3),y(5),z(7)}),
+ {x({"a","b","c"})},
+ {x({"a","b","c"}),y({"foo","bar"})},
+ {x({"a","b","c"}),y({"foo","bar"}),z({"i","j","k","l"})},
+ float_cells({x({"a","b","c"}),y({"foo","bar"}),z({"i","j","k","l"})}),
+ {x(3),y({"foo", "bar"}),z(7)},
+ {x({"a","b","c"}),y(5),z({"i","j","k","l"})},
+ float_cells({x({"a","b","c"}),y(5),z({"i","j","k","l"})})
+};
+
+TEST(FastValueBuilderFactoryTest, fast_values_can_be_copied) {
+ auto factory = FastValueBuilderFactory::get();
+ for (const auto &layout: layouts) {
+ TensorSpec expect = spec(layout, N());
+ std::unique_ptr<Value> value = value_from_spec(expect, factory);
+ std::unique_ptr<Value> copy = factory.copy(*value);
+ TensorSpec actual = spec_from_value(*copy);
+ EXPECT_EQ(actual, expect);
+ }
+}
+
GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/eval/src/tests/eval/simple_value/simple_value_test.cpp b/eval/src/tests/eval/simple_value/simple_value_test.cpp
index ffc58df4a16..3a653b75172 100644
--- a/eval/src/tests/eval/simple_value/simple_value_test.cpp
+++ b/eval/src/tests/eval/simple_value/simple_value_test.cpp
@@ -83,6 +83,16 @@ TEST(SimpleValueTest, simple_values_can_be_converted_from_and_to_tensor_spec) {
}
}
+TEST(SimpleValueTest, simple_values_can_be_copied) {
+ for (const auto &layout: layouts) {
+ TensorSpec expect = spec(layout, N());
+ std::unique_ptr<Value> value = value_from_spec(expect, SimpleValueBuilderFactory::get());
+ std::unique_ptr<Value> copy = SimpleValueBuilderFactory::get().copy(*value);
+ TensorSpec actual = spec_from_value(*copy);
+ EXPECT_EQ(actual, expect);
+ }
+}
+
TEST(SimpleValueTest, simple_value_can_be_built_and_inspected) {
ValueType type = ValueType::from_spec("tensor<float>(x{},y[2],z{})");
const auto &factory = SimpleValueBuilderFactory::get();
diff --git a/eval/src/tests/streamed/value/streamed_value_test.cpp b/eval/src/tests/streamed/value/streamed_value_test.cpp
index 075595c5d2c..2f91c3b9390 100644
--- a/eval/src/tests/streamed/value/streamed_value_test.cpp
+++ b/eval/src/tests/streamed/value/streamed_value_test.cpp
@@ -83,6 +83,16 @@ TEST(StreamedValueTest, streamed_values_can_be_converted_from_and_to_tensor_spec
}
}
+TEST(StreamedValueTest, streamed_values_can_be_copied) {
+ for (const auto &layout: layouts) {
+ TensorSpec expect = spec(layout, N());
+ std::unique_ptr<Value> value = value_from_spec(expect, StreamedValueBuilderFactory::get());
+ std::unique_ptr<Value> copy = StreamedValueBuilderFactory::get().copy(*value);
+ TensorSpec actual = spec_from_value(*copy);
+ EXPECT_EQ(actual, expect);
+ }
+}
+
TEST(StreamedValueTest, streamed_value_can_be_built_and_inspected) {
ValueType type = ValueType::from_spec("tensor<float>(x{},y[2],z{})");
const auto &factory = StreamedValueBuilderFactory::get();
diff --git a/eval/src/vespa/eval/eval/value.cpp b/eval/src/vespa/eval/eval/value.cpp
index 7dcd04c8ab2..bfa77d1a604 100644
--- a/eval/src/vespa/eval/eval/value.cpp
+++ b/eval/src/vespa/eval/eval/value.cpp
@@ -64,12 +64,54 @@ ValueType ScalarValue<T>::_type = ValueType::make_type(get_cell_type<T>(), {});
template class ScalarValue<double>;
template class ScalarValue<float>;
+namespace {
+
+struct CopyValue {
+ template <typename CT>
+ static std::unique_ptr<Value> invoke(const Value &value,
+ const ValueType &type,
+ const ValueBuilderFactory &factory)
+ {
+ size_t num_mapped = type.count_mapped_dimensions();
+ size_t dense_size = type.dense_subspace_size();
+ const auto & idx = value.index();
+ auto input_cells = value.cells().typify<CT>();
+ auto builder = factory.create_value_builder<CT>(type, num_mapped, dense_size, idx.size());
+ std::vector<string_id> addr(num_mapped);
+ if (num_mapped == 0) {
+ assert(idx.size() == 1);
+ auto array_ref = builder->add_subspace(addr);
+ for (size_t i = 0; i < dense_size; ++i) {
+ array_ref[i] = input_cells[i];
+ }
+ } else {
+ auto view = idx.create_view({});
+ view->lookup({});
+ std::vector<string_id*> addr_fetch;
+ addr_fetch.reserve(num_mapped);
+ for (auto & label : addr) {
+ addr_fetch.push_back(&label);
+ }
+ size_t subspace_idx;
+ while (view->next_result(addr_fetch, subspace_idx)) {
+ auto array_ref = builder->add_subspace(addr);
+ for (size_t i = 0; i < dense_size; ++i) {
+ array_ref[i] = input_cells[(dense_size * subspace_idx) + i];
+ }
+ }
+ }
+ return builder->build(std::move(builder));
+ }
+};
+
+} // namespace <unnamed>
+
std::unique_ptr<Value>
ValueBuilderFactory::copy(const Value &value) const
{
- nbostream stream;
- encode_value(value, stream);
- return decode_value(stream, *this);
+ const auto & type = value.type();
+ return typify_invoke<1,TypifyCellType,CopyValue>(type.cell_type(),
+ value, type, *this);
}
} // namespace vespalib::eval