diff options
author | Arne H Juul <arnej27959@users.noreply.github.com> | 2021-01-12 14:06:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-12 14:06:47 +0100 |
commit | 00df4dedab5ea94283cbd2d2f359b01774402ffb (patch) | |
tree | 3335023c4c7017c1e77f6f8347d1977a2420c94a /eval | |
parent | 1f15e7ef0872f917d6eeeafc0e30cfc904837347 (diff) | |
parent | 024d645a666200544465db2b1e8a01b5583b343c (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.cpp | 28 | ||||
-rw-r--r-- | eval/src/tests/eval/simple_value/simple_value_test.cpp | 10 | ||||
-rw-r--r-- | eval/src/tests/streamed/value/streamed_value_test.cpp | 10 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/value.cpp | 48 |
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 |