diff options
author | HÃ¥vard Pettersen <3535158+havardpe@users.noreply.github.com> | 2020-12-04 11:28:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-04 11:28:52 +0100 |
commit | cdadb685bc4a91a8b9c2d613e64e3d9ed2b68099 (patch) | |
tree | 0d964586ce8d48f97fd11511a56ab287920a4157 /eval/src | |
parent | 52f71249dd83068ba54eeb5e84988b74de62ae76 (diff) | |
parent | 05188fd6874fd740471cee100562be13f28315c6 (diff) |
Merge pull request #15654 from vespa-engine/arnej/remove-old-prod
Arnej/remove old prod
Diffstat (limited to 'eval/src')
58 files changed, 16 insertions, 2313 deletions
diff --git a/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp b/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp index b5ff2ec3b48..cfecdb97aa0 100644 --- a/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp +++ b/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp @@ -110,24 +110,5 @@ TEST(GenericConcatTest, dense_concat_plan_can_be_created) { EXPECT_EQ(plan.right.out_stride, expect_right_out_s); } -TensorSpec immediate_generic_concat(const TensorSpec &a, const TensorSpec &b, const std::string &concat_dim) { - const auto &factory = SimpleValueBuilderFactory::get(); - auto lhs = value_from_spec(a, factory); - auto rhs = value_from_spec(b, factory); - auto up = GenericConcat::perform_concat(*lhs, *rhs, concat_dim, factory); - return spec_from_value(*up); -} - -TEST(GenericConcatTest, immediate_generic_concat_works) { - ASSERT_TRUE((concat_layouts.size() % 2) == 0); - for (size_t i = 0; i < concat_layouts.size(); i += 2) { - const TensorSpec lhs = spec(concat_layouts[i], N()); - const TensorSpec rhs = spec(concat_layouts[i + 1], Div16(N())); - SCOPED_TRACE(fmt("\n===\nin LHS: %s\nin RHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); - auto actual = immediate_generic_concat(lhs, rhs, "y"); - auto expect = ReferenceOperations::concat(lhs, rhs, "y"); - EXPECT_EQ(actual, expect); - } -} GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_join/generic_join_test.cpp b/eval/src/tests/instruction/generic_join/generic_join_test.cpp index a81294c8d25..f4046b3d059 100644 --- a/eval/src/tests/instruction/generic_join/generic_join_test.cpp +++ b/eval/src/tests/instruction/generic_join/generic_join_test.cpp @@ -123,26 +123,5 @@ TEST(GenericJoinTest, generic_join_works_for_simple_and_fast_values) { } } -TensorSpec immediate_generic_join(const TensorSpec &a, const TensorSpec &b, join_fun_t function) { - const auto &factory = SimpleValueBuilderFactory::get(); - auto lhs = value_from_spec(a, factory); - auto rhs = value_from_spec(b, factory); - auto up = GenericJoin::perform_join(*lhs, *rhs, function, factory); - return spec_from_value(*up); -} - -TEST(GenericJoinTest, immediate_generic_join_works) { - ASSERT_TRUE((join_layouts.size() % 2) == 0); - for (size_t i = 0; i < join_layouts.size(); i += 2) { - TensorSpec lhs = spec(join_layouts[i], Div16(N())); - TensorSpec rhs = spec(join_layouts[i + 1], Div16(N())); - for (auto fun: {operation::Add::f, operation::Sub::f, operation::Mul::f, operation::Div::f}) { - SCOPED_TRACE(fmt("\n===\nLHS: %s\nRHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); - auto expect = ReferenceOperations::join(lhs, rhs, fun); - auto actual = immediate_generic_join(lhs, rhs, fun); - EXPECT_EQ(actual, expect); - } - } -} GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_map/generic_map_test.cpp b/eval/src/tests/instruction/generic_map/generic_map_test.cpp index ba6a1630777..687b6aa60ac 100644 --- a/eval/src/tests/instruction/generic_map/generic_map_test.cpp +++ b/eval/src/tests/instruction/generic_map/generic_map_test.cpp @@ -60,24 +60,4 @@ TEST(GenericMapTest, generic_map_works_for_fast_values) { test_generic_map_with(FastValueBuilderFactory::get()); } -TensorSpec immediate_generic_map(const TensorSpec &a, map_fun_t func, const ValueBuilderFactory &factory) -{ - auto lhs = value_from_spec(a, factory); - auto up = GenericMap::perform_map(*lhs, func, factory); - return spec_from_value(*up); -} - -TEST(GenericMapTest, immediate_generic_map_works) { - for (const auto & layout : map_layouts) { - TensorSpec lhs = spec(layout, Div16(N())); - ValueType lhs_type = ValueType::from_spec(lhs.type()); - for (auto func : {operation::Floor::f, operation::Fabs::f, operation::Square::f, operation::Inv::f}) { - SCOPED_TRACE(fmt("\n===\nLHS: %s\n===\n", lhs.to_string().c_str())); - auto expect = ReferenceOperations::map(lhs, func); - auto actual = immediate_generic_map(lhs, func, SimpleValueBuilderFactory::get()); - EXPECT_EQ(actual, expect); - } - } -} - GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp index a43169a6959..60a27e6f6e9 100644 --- a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp +++ b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp @@ -65,26 +65,5 @@ TEST(GenericMergeTest, generic_merge_works_for_fast_values) { test_generic_merge_with(FastValueBuilderFactory::get()); } -TensorSpec immediate_generic_merge(const TensorSpec &a, const TensorSpec &b, join_fun_t fun) { - const auto &factory = SimpleValueBuilderFactory::get(); - auto lhs = value_from_spec(a, factory); - auto rhs = value_from_spec(b, factory); - auto up = GenericMerge::perform_merge(*lhs, *rhs, fun, factory); - return spec_from_value(*up); -} - -TEST(GenericMergeTest, immediate_generic_merge_works) { - ASSERT_TRUE((merge_layouts.size() % 2) == 0); - for (size_t i = 0; i < merge_layouts.size(); i += 2) { - TensorSpec lhs = spec(merge_layouts[i], N()); - TensorSpec rhs = spec(merge_layouts[i + 1], Div16(N())); - SCOPED_TRACE(fmt("\n===\nLHS: %s\nRHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); - for (auto fun: {operation::Add::f, operation::Mul::f, operation::Sub::f, operation::Max::f}) { - auto expect = ReferenceOperations::merge(lhs, rhs, fun); - auto actual = immediate_generic_merge(lhs, rhs, fun); - EXPECT_EQ(actual, expect); - } - } -} GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp b/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp index 273c69a395d..3ab971dd34d 100644 --- a/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp +++ b/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp @@ -90,28 +90,5 @@ TEST(GenericReduceTest, generic_reduce_works_for_fast_values) { test_generic_reduce_with(FastValueBuilderFactory::get()); } -TensorSpec immediate_generic_reduce(const TensorSpec &a, Aggr aggr, const std::vector<vespalib::string> &dims) { - const auto &factory = SimpleValueBuilderFactory::get(); - auto lhs = value_from_spec(a, factory); - auto up = GenericReduce::perform_reduce(*lhs, aggr, dims, factory); - return spec_from_value(*up); -} - -TEST(GenericReduceTest, immediate_generic_reduce_works) { - for (const Layout &layout: layouts) { - TensorSpec input = spec(layout, Div16(N())); - for (Aggr aggr: {Aggr::SUM, Aggr::AVG, Aggr::MIN, Aggr::MAX}) { - for (const Domain &domain: layout) { - auto expect = ReferenceOperations::reduce(input, aggr, {domain.dimension}).normalize(); - auto actual = immediate_generic_reduce(input, aggr, {domain.dimension}); - EXPECT_EQ(actual, expect); - } - auto expect = ReferenceOperations::reduce(input, aggr, {}).normalize(); - auto actual = immediate_generic_reduce(input, aggr, {}); - EXPECT_EQ(actual, expect); - } - } -} - GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp b/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp index a7e6b8d807b..20d155822b5 100644 --- a/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp +++ b/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp @@ -134,29 +134,4 @@ TEST(GenericRenameTest, generic_rename_works_for_fast_values) { test_generic_rename_with(FastValueBuilderFactory::get()); } -TensorSpec immediate_generic_rename(const TensorSpec &a, const FromTo &ft) -{ - auto &factory = SimpleValueBuilderFactory::get(); - auto lhs = value_from_spec(a, factory); - auto up = GenericRename::perform_rename(*lhs, ft.from, ft.to, factory); - return spec_from_value(*up); -} - -TEST(GenericRenameTest, immediate_generic_rename_works) { - for (const auto & layout : rename_layouts) { - TensorSpec lhs = spec(layout, N()); - ValueType lhs_type = ValueType::from_spec(lhs.type()); - // printf("lhs_type: %s\n", lhs_type.to_spec().c_str()); - for (const auto & from_to : rename_from_to) { - ValueType renamed_type = lhs_type.rename(from_to.from, from_to.to); - if (renamed_type.is_error()) continue; - // printf("type %s -> %s\n", lhs_type.to_spec().c_str(), renamed_type.to_spec().c_str()); - SCOPED_TRACE(fmt("\n===\nLHS: %s\n===\n", lhs.to_string().c_str())); - auto expect = ReferenceOperations::rename(lhs, from_to.from, from_to.to); - auto actual = immediate_generic_rename(lhs, from_to); - EXPECT_EQ(actual, expect); - } - } -} - GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/partial_add/partial_add_test.cpp b/eval/src/tests/tensor/partial_add/partial_add_test.cpp index 711bf7a1c49..42db77a311f 100644 --- a/eval/src/tests/tensor/partial_add/partial_add_test.cpp +++ b/eval/src/tests/tensor/partial_add/partial_add_test.cpp @@ -3,7 +3,6 @@ #include <vespa/eval/eval/simple_value.h> #include <vespa/eval/eval/test/tensor_model.hpp> #include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/tensor/default_tensor_engine.h> #include <vespa/eval/tensor/partial_update.h> #include <vespa/eval/tensor/tensor.h> #include <vespa/vespalib/util/stringfmt.h> diff --git a/eval/src/tests/tensor/partial_modify/partial_modify_test.cpp b/eval/src/tests/tensor/partial_modify/partial_modify_test.cpp index ab04f195b1f..a39bcc87ab3 100644 --- a/eval/src/tests/tensor/partial_modify/partial_modify_test.cpp +++ b/eval/src/tests/tensor/partial_modify/partial_modify_test.cpp @@ -3,7 +3,6 @@ #include <vespa/eval/eval/simple_value.h> #include <vespa/eval/eval/test/tensor_model.hpp> #include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/tensor/default_tensor_engine.h> #include <vespa/eval/tensor/partial_update.h> #include <vespa/eval/tensor/tensor.h> #include <vespa/vespalib/util/stringfmt.h> diff --git a/eval/src/tests/tensor/partial_remove/partial_remove_test.cpp b/eval/src/tests/tensor/partial_remove/partial_remove_test.cpp index fc22a364e5c..410331c5eb7 100644 --- a/eval/src/tests/tensor/partial_remove/partial_remove_test.cpp +++ b/eval/src/tests/tensor/partial_remove/partial_remove_test.cpp @@ -3,7 +3,6 @@ #include <vespa/eval/eval/simple_value.h> #include <vespa/eval/eval/test/tensor_model.hpp> #include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/tensor/default_tensor_engine.h> #include <vespa/eval/tensor/partial_update.h> #include <vespa/eval/tensor/tensor.h> #include <vespa/vespalib/util/stringfmt.h> diff --git a/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt deleted file mode 100644 index 275043c8c54..00000000000 --- a/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_tensor_add_operation_test_app TEST - SOURCES - tensor_add_operation_test.cpp - DEPENDS - vespaeval - GTest::GTest -) -vespa_add_test(NAME eval_tensor_add_operation_test_app COMMAND eval_tensor_add_operation_test_app) diff --git a/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp b/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp deleted file mode 100644 index 1d39a557114..00000000000 --- a/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/tensor/default_tensor_engine.h> -#include <vespa/eval/tensor/sparse/sparse_tensor.h> -#include <vespa/eval/tensor/test/test_utils.h> -#include <vespa/vespalib/gtest/gtest.h> - -using vespalib::eval::Value; -using vespalib::eval::TensorSpec; -using vespalib::tensor::test::makeTensor; -using namespace vespalib::tensor; - -void -assertAdd(const TensorSpec &source, const TensorSpec &arg, const TensorSpec &expected) -{ - auto sourceTensor = makeTensor<Tensor>(source); - auto argTensor = makeTensor<Tensor>(arg); - auto resultTensor = sourceTensor->add(*argTensor); - auto actual = resultTensor->toSpec(); - EXPECT_EQ(actual, expected); -} - -void -assertNullTensor(const TensorSpec &source, const TensorSpec &arg) -{ - auto sourceTensor = makeTensor<Tensor>(source); - auto argTensor = makeTensor<Tensor>(arg); - auto resultTensor = sourceTensor->add(*argTensor); - EXPECT_FALSE(resultTensor); -} - -TEST(TensorAddTest, cells_can_be_added_to_a_sparse_tensor) -{ - assertAdd(TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 2) - .add({{"x","c"},{"y","d"}}, 3), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 5) - .add({{"x","e"},{"y","f"}}, 7), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 5) - .add({{"x","c"},{"y","d"}}, 3) - .add({{"x","e"},{"y","f"}}, 7)); -} - -TEST(TensorAddTest, cells_can_be_added_to_a_mixed_tensor) -{ - assertAdd(TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3) - .add({{"x","b"},{"y",0}}, 4) - .add({{"x","b"},{"y",1}}, 5), - TensorSpec("tensor(x{},y[2])") - .add({{"x","b"},{"y",0}}, 6) - .add({{"x","b"},{"y",1}}, 7) - .add({{"x","c"},{"y",0}}, 8) - .add({{"x","c"},{"y",1}}, 9), - TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3) - .add({{"x","b"},{"y",0}}, 6) - .add({{"x","b"},{"y",1}}, 7) - .add({{"x","c"},{"y",0}}, 8) - .add({{"x","c"},{"y",1}}, 9)); -} - -TEST(TensorAddTest, cells_can_be_added_to_empty_mixed_tensor) -{ - assertAdd(TensorSpec("tensor(x{},y[2])"), - TensorSpec("tensor(x{},y[2])") - .add({{"x","b"},{"y",0}}, 6) - .add({{"x","b"},{"y",1}}, 7), - TensorSpec("tensor(x{},y[2])") - .add({{"x","b"},{"y",0}}, 6) - .add({{"x","b"},{"y",1}}, 7)); -} - -TEST(TensorAddTest, tensors_of_different_types_cannot_be_added_together) -{ - assertNullTensor(TensorSpec("tensor(x{},y[2])"), TensorSpec("tensor(x{},y{})")); - assertNullTensor(TensorSpec("tensor(x{},y[2])"), TensorSpec("tensor(x{},y[3])")); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt deleted file mode 100644 index cd4643deae0..00000000000 --- a/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_tensor_modify_operation_test_app TEST - SOURCES - tensor_modify_operation_test.cpp - DEPENDS - vespaeval - GTest::GTest -) -vespa_add_test(NAME eval_tensor_modify_operation_test_app COMMAND eval_tensor_modify_operation_test_app) diff --git a/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp b/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp deleted file mode 100644 index 00ee55ed7af..00000000000 --- a/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/eval/eval/operation.h> -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/tensor/cell_values.h> -#include <vespa/eval/tensor/default_tensor_engine.h> -#include <vespa/eval/tensor/sparse/sparse_tensor.h> -#include <vespa/eval/tensor/test/test_utils.h> -#include <vespa/vespalib/gtest/gtest.h> -#include <vespa/vespalib/util/stringfmt.h> - -using vespalib::eval::Value; -using vespalib::eval::TensorSpec; -using vespalib::tensor::test::makeTensor; -using namespace vespalib::tensor; - -void -checkUpdate(const TensorSpec &source, const TensorSpec &update, const TensorSpec &expect) -{ - auto sourceTensor = makeTensor<Tensor>(source); - auto updateTensor = makeTensor<SparseTensor>(update); - const CellValues cellValues(*updateTensor); - - auto actualTensor = sourceTensor->modify(vespalib::eval::operation::Add::f, cellValues); - auto actual = actualTensor->toSpec(); - auto expectTensor = makeTensor<Tensor>(expect); - auto expectPadded = expectTensor->toSpec(); - EXPECT_EQ(actual, expectPadded); -} - -TEST(TensorModifyTest, sparse_tensors_can_be_modified) -{ - checkUpdate(TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 11) - .add({{"x","9"},{"y","9"}}, 11), - TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 2), - TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 13) - .add({{"x","9"},{"y","9"}}, 11)); -} - -TEST(TensorModifyTest, dense_tensors_can_be_modified) -{ - checkUpdate(TensorSpec("tensor(x[10],y[10])") - .add({{"x",8},{"y",9}}, 11) - .add({{"x",9},{"y",9}}, 11), - TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 2), - TensorSpec("tensor(x[10],y[10])") - .add({{"x",8},{"y",9}}, 13) - .add({{"x",9},{"y",9}}, 11)); -} - -TEST(TensorModifyTest, mixed_tensors_can_be_modified) -{ - checkUpdate(TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3) - .add({{"x","b"},{"y",0}}, 4) - .add({{"x","b"},{"y",1}}, 5), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","0"}}, 6) - .add({{"x","b"},{"y","1"}}, 7), - TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 8) - .add({{"x","a"},{"y",1}}, 3) - .add({{"x","b"},{"y",0}}, 4) - .add({{"x","b"},{"y",1}}, 12)); -} - -TEST(TensorModifyTest, sparse_tensors_ignore_updates_to_missing_cells) -{ - checkUpdate(TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 11) - .add({{"x","9"},{"y","9"}}, 11), - TensorSpec("tensor(x{},y{})") - .add({{"x","7"},{"y","9"}}, 2) - .add({{"x","8"},{"y","9"}}, 2), - TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 13) - .add({{"x","9"},{"y","9"}}, 11)); -} - -TEST(TensorModifyTest, dense_tensors_ignore_updates_to_out_of_range_cells) -{ - checkUpdate(TensorSpec("tensor(x[10],y[10])") - .add({{"x",8},{"y",9}}, 11) - .add({{"x",9},{"y",9}}, 11), - TensorSpec("tensor(x{},y{})") - .add({{"x","8"},{"y","9"}}, 2) - .add({{"x","10"},{"y","9"}}, 2), - TensorSpec("tensor(x[10],y[10])") - .add({{"x",8},{"y",9}}, 13) - .add({{"x",9},{"y",9}}, 11)); -} - -TEST(TensorModifyTest, mixed_tensors_ignore_updates_to_missing_or_out_of_range_cells) -{ - checkUpdate(TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","2"}}, 4) - .add({{"x","c"},{"y","0"}}, 5), - TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3)); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt deleted file mode 100644 index a302cc528e0..00000000000 --- a/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_tensor_remove_operation_test_app TEST - SOURCES - tensor_remove_operation_test.cpp - DEPENDS - vespaeval - GTest::GTest -) -vespa_add_test(NAME eval_tensor_remove_operation_test_app COMMAND eval_tensor_remove_operation_test_app) diff --git a/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp b/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp deleted file mode 100644 index ceeaf2c99da..00000000000 --- a/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/tensor/cell_values.h> -#include <vespa/eval/tensor/default_tensor_engine.h> -#include <vespa/eval/tensor/sparse/sparse_tensor.h> -#include <vespa/eval/tensor/test/test_utils.h> -#include <vespa/vespalib/gtest/gtest.h> - -using vespalib::eval::Value; -using vespalib::eval::TensorSpec; -using vespalib::tensor::test::makeTensor; -using namespace vespalib::tensor; - -void -assertRemove(const TensorSpec &source, const TensorSpec &arg, const TensorSpec &expected) -{ - auto sourceTensor = makeTensor<Tensor>(source); - auto argTensor = makeTensor<SparseTensor>(arg); - auto resultTensor = sourceTensor->remove(CellValues(*argTensor)); - auto actual = resultTensor->toSpec(); - EXPECT_EQ(actual, expected); -} - -TEST(TensorRemoveTest, cells_can_be_removed_from_a_sparse_tensor) -{ - assertRemove(TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 2) - .add({{"x","c"},{"y","d"}}, 3), - TensorSpec("tensor(x{},y{})") - .add({{"x","c"},{"y","d"}}, 1) - .add({{"x","e"},{"y","f"}}, 1), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 2)); -} - -TEST(TensorRemoveTest, all_cells_can_be_removed_from_a_sparse_tensor) -{ - assertRemove(TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 2), - TensorSpec("tensor(x{},y{})") - .add({{"x","a"},{"y","b"}}, 1), - TensorSpec("tensor(x{},y{})")); -} - -TEST(TensorRemoveTest, cells_can_be_removed_from_a_mixed_tensor) -{ - assertRemove(TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3) - .add({{"x","b"},{"y",0}}, 4) - .add({{"x","b"},{"y",1}}, 5), - TensorSpec("tensor(x{})") - .add({{"x","b"}}, 1) - .add({{"x","c"}}, 1), - TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3)); - - assertRemove(TensorSpec("tensor(x{},y{},z[2])") - .add({{"x","a"},{"y","c"},{"z",0}}, 2) - .add({{"x","a"},{"y","c"},{"z",1}}, 3) - .add({{"x","b"},{"y","c"},{"z",0}}, 4) - .add({{"x","b"},{"y","c"},{"z",1}}, 5), - TensorSpec("tensor(x{},y{})") - .add({{"x","b"},{"y","c"}}, 1) - .add({{"x","c"},{"y","c"}}, 1), - TensorSpec("tensor(x{},y{},z[2])") - .add({{"x","a"},{"y","c"},{"z",0}}, 2) - .add({{"x","a"},{"y","c"},{"z",1}}, 3)); - - assertRemove(TensorSpec("tensor(x{},y[1],z[2])") - .add({{"x","a"},{"y",0},{"z",0}}, 2) - .add({{"x","a"},{"y",0},{"z",1}}, 3) - .add({{"x","b"},{"y",0},{"z",0}}, 4) - .add({{"x","b"},{"y",0},{"z",1}}, 5), - TensorSpec("tensor(x{})") - .add({{"x","b"}}, 1) - .add({{"x","c"}}, 1), - TensorSpec("tensor(x{},y[1],z[2])") - .add({{"x","a"},{"y",0},{"z",0}}, 2) - .add({{"x","a"},{"y",0},{"z",1}}, 3)); -} - -TEST(TensorRemoveTest, all_cells_can_be_removed_from_a_mixed_tensor) -{ - assertRemove(TensorSpec("tensor(x{},y[2])") - .add({{"x","a"},{"y",0}}, 2) - .add({{"x","a"},{"y",1}}, 3), - TensorSpec("tensor(x{})") - .add({{"x","a"}}, 1), - TensorSpec("tensor(x{},y[2])")); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/tensor_serialization/.gitignore b/eval/src/tests/tensor/tensor_serialization/.gitignore deleted file mode 100644 index f8525561c6b..00000000000 --- a/eval/src/tests/tensor/tensor_serialization/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vespalib_tensor_serialization_test_app diff --git a/eval/src/tests/tensor/tensor_serialization/CMakeLists.txt b/eval/src/tests/tensor/tensor_serialization/CMakeLists.txt deleted file mode 100644 index b9fc7e0d544..00000000000 --- a/eval/src/tests/tensor/tensor_serialization/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_tensor_serialization_test_app TEST - SOURCES - tensor_serialization_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_tensor_serialization_test_app COMMAND eval_tensor_serialization_test_app) diff --git a/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp b/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp deleted file mode 100644 index 358f5d36101..00000000000 --- a/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/tensor/sparse/sparse_tensor.h> -#include <vespa/eval/tensor/types.h> -#include <vespa/eval/tensor/default_tensor_engine.h> -#include <vespa/eval/tensor/serialization/typed_binary_format.h> -#include <vespa/eval/tensor/serialization/sparse_binary_format.h> -#include <vespa/vespalib/objects/nbostream.h> -#include <vespa/vespalib/objects/hexdump.h> -#include <ostream> -#include <vespa/eval/tensor/dense/dense_tensor_view.h> -#include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/eval/simple_value.h> - -using namespace vespalib::tensor; -using vespalib::eval::TensorSpec; -using vespalib::nbostream; -using ExpBuffer = std::vector<uint8_t>; - -namespace std { - -bool operator==(const std::vector<uint8_t> &exp, const nbostream &stream) -{ - return ((exp.size() == stream.size()) && - (memcmp(&exp[0], stream.peek(), exp.size()) == 0)); -} - -std::ostream &operator<<(std::ostream &out, const std::vector<uint8_t> &rhs) -{ - out << vespalib::HexDump(&rhs[0], rhs.size()); - return out; -} - -} - -//----------------------------------------------------------------------------- - -template <typename T> -void verify_cells_only(const ExpBuffer &exp, const TensorSpec &spec) { - nbostream input(&exp[0], exp.size()); - std::vector<T> cells; - TypedBinaryFormat::deserializeCellsOnlyFromDenseTensors(input, cells); - ASSERT_EQUAL(cells.size(), spec.cells().size()); - size_t i = 0; - for (const auto &cell: spec.cells()) { - EXPECT_EQUAL(cells[i++], cell.second.value); - } - ASSERT_EQUAL(i, cells.size()); -} - -TensorSpec verify_new_value_serialized(const ExpBuffer &exp, const TensorSpec &spec) { - const auto &factory = vespalib::eval::SimpleValueBuilderFactory::get(); - auto new_value = vespalib::eval::value_from_spec(spec, factory); - auto new_value_spec = vespalib::eval::spec_from_value(*new_value); - nbostream actual; - vespalib::eval::encode_value(*new_value, actual); - ASSERT_EQUAL(exp, actual); - auto new_decoded = vespalib::eval::decode_value(actual, factory); - auto new_decoded_spec = vespalib::eval::spec_from_value(*new_decoded); - EXPECT_EQUAL(0u, actual.size()); - EXPECT_EQUAL(new_value_spec, new_decoded_spec); - if (new_value->type().is_dense()) { - TEST_DO(verify_cells_only<float>(exp, new_value_spec)); - TEST_DO(verify_cells_only<double>(exp, new_value_spec)); - } - return new_decoded_spec; -} - -void verify_serialized(const ExpBuffer &exp, const TensorSpec &spec) { - auto &engine = DefaultTensorEngine::ref(); - auto value = engine.from_spec(spec); - auto value_spec = engine.to_spec(*value); - nbostream actual; - engine.encode(*value, actual); - EXPECT_EQUAL(exp, actual); - auto decoded = engine.decode(actual); - auto decoded_spec = engine.to_spec(*decoded); - EXPECT_EQUAL(0u, actual.size()); - EXPECT_EQUAL(value_spec, decoded_spec); - if (value->type().is_dense()) { - TEST_DO(verify_cells_only<float>(exp, value_spec)); - TEST_DO(verify_cells_only<double>(exp, value_spec)); - } - auto new_value_spec = verify_new_value_serialized(exp, spec); - EXPECT_EQUAL(value_spec, new_value_spec); -} - -//----------------------------------------------------------------------------- - -TEST("test tensor serialization for SparseTensor") { - TEST_DO(verify_serialized({ 0x01, 0x01, 0x01, 0x78, 0x00 }, - TensorSpec("tensor(x{})"))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x00 }, - TensorSpec("tensor(x{},y{})"))); - TEST_DO(verify_serialized({ 0x01, 0x01, 0x01, 0x78, 0x01, 0x01, 0x31, 0x40, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - TensorSpec("tensor(x{})") - .add({{"x", "1"}}, 3))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x00, - 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 }, - TensorSpec("tensor(x{},y{})") - .add({{"x", ""}, {"y", ""}}, 3))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x01, - 0x31, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }, - TensorSpec("tensor(x{},y{})") - .add({{"x", "1"}, {"y", ""}}, 3))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x00, - 0x01, 0x33, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }, - TensorSpec("tensor(x{},y{})") - .add({{"x", ""}, {"y", "3"}}, 3))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x01, - 0x32, 0x01, 0x34, 0x40, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 }, - TensorSpec("tensor(x{},y{})") - .add({{"x", "2"}, {"y", "4"}}, 3))); - TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, - 0x01, 0x01, 0x31, 0x00, 0x40, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - TensorSpec("tensor(x{},y{})") - .add({{"x", "1"}, {"y", ""}}, 3))); -} - -TEST("test float cells from sparse tensor") { - TEST_DO(verify_serialized({ 0x05, 0x01, - 0x02, 0x01, 0x78, 0x01, 0x79, - 0x01, 0x01, 0x31, 0x00, - 0x40, 0x40, 0x00, 0x00 }, - TensorSpec("tensor<float>(x{},y{})") - .add({{"x", "1"}, {"y", ""}}, 3))); -} - -TEST("test tensor serialization for DenseTensor") { - TEST_DO(verify_serialized({0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("double"))); - TEST_DO(verify_serialized({0x02, 0x01, 0x01, 0x78, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[1])") - .add({{"x", 0}}, 0))); - TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[1],y[1])") - .add({{"x", 0}, {"y", 0}}, 0))); - TEST_DO(verify_serialized({0x02, 0x01, 0x01, 0x78, 0x02, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[2])") - .add({{"x", 1}}, 3))); - TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x01, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[1],y[1])") - .add({{"x", 0}, {"y", 0}}, 3))); - TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x02, - 0x01, 0x79, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[2],y[1])") - .add({{"x", 1}, {"y", 0}}, 3))); - TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x04, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[1],y[4])") - .add({{"x", 0}, {"y", 3}}, 3))); - TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x03, - 0x01, 0x79, 0x05, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - TensorSpec("tensor(x[3],y[5])") - .add({{"x", 2}, {"y", 4}}, 3))); -} - -TEST("test float cells for dense tensor") { - TEST_DO(verify_serialized({0x06, 0x01, 0x02, 0x01, 0x78, 0x03, - 0x01, 0x79, 0x05, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x40, 0x00, 0x00 }, - TensorSpec("tensor<float>(x[3],y[5])") - .add({{"x", 2}, {"y", 4}}, 3))); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/vespa/eval/CMakeLists.txt b/eval/src/vespa/eval/CMakeLists.txt index 952640195b1..65cf5f548f2 100644 --- a/eval/src/vespa/eval/CMakeLists.txt +++ b/eval/src/vespa/eval/CMakeLists.txt @@ -10,7 +10,6 @@ vespa_add_library(vespaeval $<TARGET_OBJECTS:eval_streamed> $<TARGET_OBJECTS:eval_tensor> $<TARGET_OBJECTS:eval_tensor_dense> - $<TARGET_OBJECTS:eval_tensor_serialization> $<TARGET_OBJECTS:eval_tensor_sparse> INSTALL lib64 DEPENDS diff --git a/eval/src/vespa/eval/eval/engine_or_factory.cpp b/eval/src/vespa/eval/eval/engine_or_factory.cpp index c40d681ab24..5b46fd61951 100644 --- a/eval/src/vespa/eval/eval/engine_or_factory.cpp +++ b/eval/src/vespa/eval/eval/engine_or_factory.cpp @@ -10,7 +10,7 @@ #include <vespa/eval/instruction/generic_merge.h> #include <vespa/eval/instruction/generic_reduce.h> #include <vespa/eval/instruction/generic_rename.h> -#include <vespa/eval/tensor/default_tensor_engine.h> +#include "tensor_engine.h" #include <vespa/vespalib/data/memory.h> #include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/exceptions.h> @@ -81,60 +81,6 @@ EngineOrFactory::copy(const Value &value) return decode(stream); } -const Value & -EngineOrFactory::map(const Value &a, operation::op1_t function, Stash &stash) const { - if (is_engine()) { - return engine().map(a, function, stash); - } else { - return *stash.create<Value::UP>(GenericMap::perform_map(a, function, factory())); - } -} - -const Value & -EngineOrFactory::join(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { - if (is_engine()) { - return engine().join(a, b, function, stash); - } else { - return *stash.create<Value::UP>(GenericJoin::perform_join(a, b, function, factory())); - } -} - -const Value & -EngineOrFactory::merge(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { - if (is_engine()) { - return engine().merge(a, b, function, stash); - } else { - return *stash.create<Value::UP>(GenericMerge::perform_merge(a, b, function, factory())); - } -} - -const Value & -EngineOrFactory::reduce(const Value &a, Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) const { - if (is_engine()) { - return engine().reduce(a, aggr, dimensions, stash); - } else { - return *stash.create<Value::UP>(GenericReduce::perform_reduce(a, aggr, dimensions, factory())); - } -} - -const Value & -EngineOrFactory::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const { - if (is_engine()) { - return engine().concat(a, b, dimension, stash); - } else { - return *stash.create<Value::UP>(GenericConcat::perform_concat(a, b, dimension, factory())); - } -} - -const Value & -EngineOrFactory::rename(const Value &a, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const { - if (is_engine()) { - return engine().rename(a, from, to, stash); - } else { - return *stash.create<Value::UP>(GenericRename::perform_rename(a, from, to, factory())); - } -} - void EngineOrFactory::set(EngineOrFactory wanted) { @@ -156,11 +102,6 @@ EngineOrFactory::get() vespalib::string EngineOrFactory::to_string() const { - if (is_engine()) { - if (&engine() == &tensor::DefaultTensorEngine::ref()) { - return "DefaultTensorEngine"; - } - } if (is_factory()) { if (&factory() == &FastValueBuilderFactory::get()) { return "FastValueBuilderFactory"; diff --git a/eval/src/vespa/eval/eval/engine_or_factory.h b/eval/src/vespa/eval/eval/engine_or_factory.h index e396d549ac3..7269f22159d 100644 --- a/eval/src/vespa/eval/eval/engine_or_factory.h +++ b/eval/src/vespa/eval/eval/engine_or_factory.h @@ -46,13 +46,6 @@ public: void encode(const Value &value, nbostream &output) const; std::unique_ptr<Value> decode(nbostream &input) const; std::unique_ptr<Value> copy(const Value &value); - // engine-only forwarding functions - const Value &map(const Value &a, operation::op1_t function, Stash &stash) const; - const Value &join(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const; - const Value &merge(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const; - const Value &reduce(const Value &a, Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) const; - const Value &concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const; - const Value &rename(const Value &a, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const; // global switch with default; call set before get to override the default static void set(EngineOrFactory wanted); static EngineOrFactory get(); diff --git a/eval/src/vespa/eval/eval/tensor.cpp b/eval/src/vespa/eval/eval/tensor.cpp index 645208ba8fb..9de812b46f0 100644 --- a/eval/src/vespa/eval/eval/tensor.cpp +++ b/eval/src/vespa/eval/eval/tensor.cpp @@ -10,15 +10,15 @@ namespace eval { bool operator==(const Tensor &lhs, const Tensor &rhs) { - auto lhs_spec = lhs.engine().to_spec(lhs); - auto rhs_spec = rhs.engine().to_spec(rhs); + auto lhs_spec = TensorSpec::from_value(lhs); + auto rhs_spec = TensorSpec::from_value(rhs); return (lhs_spec == rhs_spec); } std::ostream & operator<<(std::ostream &out, const Tensor &tensor) { - out << tensor.engine().to_spec(tensor).to_string(); + out << TensorSpec::from_value(tensor).to_string(); return out; } diff --git a/eval/src/vespa/eval/eval/tensor.h b/eval/src/vespa/eval/eval/tensor.h index ddc341ed910..a7cb1f2c516 100644 --- a/eval/src/vespa/eval/eval/tensor.h +++ b/eval/src/vespa/eval/eval/tensor.h @@ -8,8 +8,6 @@ namespace vespalib { namespace eval { -struct TensorEngine; - /** * Base class for all tensors. Tensor operations are defined by the * TensorEngine interface. The Tensor class itself is used as a tagged @@ -21,11 +19,8 @@ struct TensorEngine; **/ class Tensor : public Value { -private: - const TensorEngine &_engine; protected: - explicit Tensor(const TensorEngine &engine_in) - : _engine(engine_in) {} + Tensor() {} public: Tensor(const Tensor &) = delete; Tensor(Tensor &&) = delete; @@ -33,7 +28,6 @@ public: Tensor &operator=(Tensor &&) = delete; bool is_tensor() const override { return true; } const Tensor *as_tensor() const override { return this; } - const TensorEngine &engine() const { return _engine; } virtual ~Tensor() {} }; diff --git a/eval/src/vespa/eval/eval/tensor_spec.cpp b/eval/src/vespa/eval/eval/tensor_spec.cpp index ec94602781c..e082d3bc2ba 100644 --- a/eval/src/vespa/eval/eval/tensor_spec.cpp +++ b/eval/src/vespa/eval/eval/tensor_spec.cpp @@ -195,11 +195,7 @@ TensorSpec::from_slime(const slime::Inspector &tensor) TensorSpec TensorSpec::from_value(const eval::Value &value) { - if (auto tensor = dynamic_cast<const vespalib::eval::Tensor *>(&value)) { - return tensor->engine().to_spec(value); - } else { - return spec_from_value(value); - } + return spec_from_value(value); } TensorSpec diff --git a/eval/src/vespa/eval/instruction/generic_concat.cpp b/eval/src/vespa/eval/instruction/generic_concat.cpp index 7a2280c5db7..2d8c206b588 100644 --- a/eval/src/vespa/eval/instruction/generic_concat.cpp +++ b/eval/src/vespa/eval/instruction/generic_concat.cpp @@ -121,15 +121,6 @@ struct SelectGenericConcatOp { } }; -struct PerformGenericConcat { - template <typename LCT, typename RCT, typename OCT> - static auto invoke(const Value &a, const Value &b, const ConcatParam ¶m) { - return generic_concat<LCT, RCT, OCT>(a, b, - param.sparse_plan, param.dense_plan, - param.res_type, param.factory); - } -}; - enum class Case { NONE, OUT, CONCAT, BOTH }; } // namespace <unnamed> @@ -219,15 +210,4 @@ GenericConcat::make_instruction(const ValueType &lhs_type, const ValueType &rhs_ return Instruction(fun, wrap_param<ConcatParam>(param)); } -Value::UP -GenericConcat::perform_concat(const Value &a, const Value &b, - const vespalib::string &dimension, - const ValueBuilderFactory &factory) -{ - ConcatParam param(a.type(), b.type(), dimension, factory); - return typify_invoke<3,TypifyCellType,PerformGenericConcat>( - a.type().cell_type(), b.type().cell_type(), param.res_type.cell_type(), - a, b, param); -} - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_concat.h b/eval/src/vespa/eval/instruction/generic_concat.h index d41d161900a..5578c5a0dca 100644 --- a/eval/src/vespa/eval/instruction/generic_concat.h +++ b/eval/src/vespa/eval/instruction/generic_concat.h @@ -17,11 +17,6 @@ struct GenericConcat { make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, const vespalib::string &dimension, const ValueBuilderFactory &factory, Stash &stash); - - static Value::UP - perform_concat(const Value &a, const Value &b, - const vespalib::string &dimension, - const ValueBuilderFactory &factory); }; struct DenseConcatPlan { diff --git a/eval/src/vespa/eval/instruction/generic_join.cpp b/eval/src/vespa/eval/instruction/generic_join.cpp index 25829576ba5..026df5aa993 100644 --- a/eval/src/vespa/eval/instruction/generic_join.cpp +++ b/eval/src/vespa/eval/instruction/generic_join.cpp @@ -195,16 +195,6 @@ struct SelectGenericJoinOp { } }; -struct PerformGenericJoin { - template <typename LCT, typename RCT, typename OCT, typename Fun> - static auto invoke(const Value &a, const Value &b, const JoinParam ¶m) - { - return generic_mixed_join<LCT, RCT, OCT, Fun>(a, b, param); - } -}; - - - //----------------------------------------------------------------------------- } // namespace <unnamed> @@ -327,15 +317,4 @@ GenericJoin::make_instruction(const ValueType &lhs_type, const ValueType &rhs_ty return Instruction(fun, wrap_param<JoinParam>(param)); } - -Value::UP -GenericJoin::perform_join(const Value &a, const Value &b, join_fun_t function, - const ValueBuilderFactory &factory) -{ - JoinParam param(a.type(), b.type(), function, factory); - return typify_invoke<4,JoinTypify,PerformGenericJoin>( - a.type().cell_type(), b.type().cell_type(), param.res_type.cell_type(), function, - a, b, param); -} - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_join.h b/eval/src/vespa/eval/instruction/generic_join.h index 49cdb3499a9..e5ddf388211 100644 --- a/eval/src/vespa/eval/instruction/generic_join.h +++ b/eval/src/vespa/eval/instruction/generic_join.h @@ -21,10 +21,6 @@ struct GenericJoin { make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, join_fun_t function, const ValueBuilderFactory &factory, Stash &stash); - - static Value::UP - perform_join(const Value &a, const Value &b, join_fun_t function, - const ValueBuilderFactory &factory); }; //----------------------------------------------------------------------------- diff --git a/eval/src/vespa/eval/instruction/generic_map.cpp b/eval/src/vespa/eval/instruction/generic_map.cpp index 993f0a45925..8ad6c3ee68b 100644 --- a/eval/src/vespa/eval/instruction/generic_map.cpp +++ b/eval/src/vespa/eval/instruction/generic_map.cpp @@ -48,36 +48,6 @@ struct SelectGenericMapOp { } }; -struct PerformGenericMap { - template <typename CT, typename Func> - static auto invoke(const Value &input, map_fun_t function_in, - const ValueBuilderFactory &factory) - { - Func fun(function_in); - const auto &type = input.type(); - size_t subspace_size = type.dense_subspace_size(); - size_t num_mapped = type.count_mapped_dimensions(); - auto builder = factory.create_value_builder<CT>(type, num_mapped, subspace_size, input.index().size()); - auto input_cells = input.cells().typify<CT>(); - auto view = input.index().create_view({}); - std::vector<vespalib::stringref> output_address(num_mapped); - std::vector<vespalib::stringref *> input_address; - for (auto & label : output_address) { - input_address.push_back(&label); - } - view->lookup({}); - size_t subspace; - while (view->next_result(input_address, subspace)) { - auto dst = builder->add_subspace(output_address); - size_t input_offset = subspace_size * subspace; - for (size_t i = 0; i < subspace_size; ++i) { - dst[i] = fun(input_cells[input_offset + i]); - } - } - return builder->build(std::move(builder)); - } -}; - } // namespace <unnamed> using MapTypify = TypifyValue<TypifyCellType,operation::TypifyOp1>; @@ -89,12 +59,4 @@ GenericMap::make_instruction(const ValueType &lhs_type, map_fun_t function) return Instruction(op, to_param(function)); } -Value::UP -GenericMap::perform_map(const Value &a, map_fun_t function, - const ValueBuilderFactory &factory) -{ - return typify_invoke<2,MapTypify,PerformGenericMap>(a.type().cell_type(), function, - a, function, factory); -} - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_map.h b/eval/src/vespa/eval/instruction/generic_map.h index 9c8fb17c153..ad29d2c1073 100644 --- a/eval/src/vespa/eval/instruction/generic_map.h +++ b/eval/src/vespa/eval/instruction/generic_map.h @@ -15,10 +15,6 @@ using map_fun_t = vespalib::eval::operation::op1_t; struct GenericMap { static InterpretedFunction::Instruction make_instruction(const ValueType &input_type, map_fun_t function); - - static Value::UP - perform_map(const Value &a, map_fun_t function, - const ValueBuilderFactory &factory); }; } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_merge.cpp b/eval/src/vespa/eval/instruction/generic_merge.cpp index 8de4ea1adeb..02749a04eb9 100644 --- a/eval/src/vespa/eval/instruction/generic_merge.cpp +++ b/eval/src/vespa/eval/instruction/generic_merge.cpp @@ -156,13 +156,6 @@ struct SelectGenericMergeOp { } }; -struct PerformGenericMerge { - template <typename LCT, typename RCT, typename OCT, typename Fun> - static auto invoke(const Value &a, const Value &b, const MergeParam ¶m) { - return generic_mixed_merge<LCT,RCT,OCT,Fun>(a, b, param); - } -}; - //----------------------------------------------------------------------------- } // namespace <unnamed> @@ -178,18 +171,4 @@ GenericMerge::make_instruction(const ValueType &lhs_type, const ValueType &rhs_t return Instruction(fun, wrap_param<MergeParam>(param)); } - -Value::UP -GenericMerge::perform_merge(const Value &a, const Value &b, join_fun_t function, - const ValueBuilderFactory &factory) -{ - MergeParam param(a.type(), b.type(), function, factory); - return typify_invoke<4,MergeTypify,PerformGenericMerge>( - a.type().cell_type(), - b.type().cell_type(), - param.res_type.cell_type(), function, - a, b, param); -} - - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_merge.h b/eval/src/vespa/eval/instruction/generic_merge.h index e9ffcc87997..2b2964366cc 100644 --- a/eval/src/vespa/eval/instruction/generic_merge.h +++ b/eval/src/vespa/eval/instruction/generic_merge.h @@ -11,10 +11,6 @@ struct GenericMerge { make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, join_fun_t function, const ValueBuilderFactory &factory, Stash &stash); - - static Value::UP - perform_merge(const Value &a, const Value &b, join_fun_t function, - const ValueBuilderFactory &factory); }; } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_reduce.cpp b/eval/src/vespa/eval/instruction/generic_reduce.cpp index 9b2e72e45db..ad4692c2e80 100644 --- a/eval/src/vespa/eval/instruction/generic_reduce.cpp +++ b/eval/src/vespa/eval/instruction/generic_reduce.cpp @@ -153,13 +153,6 @@ struct SelectGenericReduceOp { } }; -struct PerformGenericReduce { - template <typename ICT, typename OCT, typename AGGR> - static auto invoke(const Value &input, const ReduceParam ¶m) { - return generic_reduce<ICT, OCT, typename AGGR::template templ<OCT>>(input, param); - } -}; - //----------------------------------------------------------------------------- } // namespace <unnamed> @@ -248,16 +241,4 @@ GenericReduce::make_instruction(const ValueType &type, Aggr aggr, const std::vec return Instruction(fun, wrap_param<ReduceParam>(param)); } - -Value::UP -GenericReduce::perform_reduce(const Value &a, Aggr aggr, - const std::vector<vespalib::string> &dimensions, - const ValueBuilderFactory &factory) -{ - ReduceParam param(a.type(), dimensions, factory); - return typify_invoke<3,ReduceTypify,PerformGenericReduce>( - a.type().cell_type(), param.res_type.cell_type(), aggr, - a, param); -} - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_reduce.h b/eval/src/vespa/eval/instruction/generic_reduce.h index cacc0f4cfd3..f753a3e51cd 100644 --- a/eval/src/vespa/eval/instruction/generic_reduce.h +++ b/eval/src/vespa/eval/instruction/generic_reduce.h @@ -41,11 +41,6 @@ struct GenericReduce { make_instruction(const ValueType &type, Aggr aggr, const std::vector<vespalib::string> &dimensions, const ValueBuilderFactory &factory, Stash &stash); - - static Value::UP - perform_reduce(const Value &a, Aggr aggr, - const std::vector<vespalib::string> &dimensions, - const ValueBuilderFactory &factory); }; //----------------------------------------------------------------------------- diff --git a/eval/src/vespa/eval/instruction/generic_rename.cpp b/eval/src/vespa/eval/instruction/generic_rename.cpp index 3d8de356001..1ce18597ec2 100644 --- a/eval/src/vespa/eval/instruction/generic_rename.cpp +++ b/eval/src/vespa/eval/instruction/generic_rename.cpp @@ -107,14 +107,6 @@ struct SelectGenericRenameOp { } }; -struct PerformGenericRename { - template <typename CT> - static auto invoke(const Value &a, const RenameParam ¶m) { - return generic_rename<CT>(a, param.sparse_plan, param.dense_plan, - param.res_type, param.factory); - } -}; - } // namespace <unnamed> //----------------------------------------------------------------------------- @@ -194,19 +186,5 @@ GenericRename::make_instruction(const ValueType &lhs_type, return Instruction(fun, wrap_param<RenameParam>(param)); } - -Value::UP -GenericRename::perform_rename(const Value &a, - const std::vector<vespalib::string> &rename_dimension_from, - const std::vector<vespalib::string> &rename_dimension_to, - const ValueBuilderFactory &factory) -{ - RenameParam param(a.type(), - rename_dimension_from, rename_dimension_to, - factory); - return typify_invoke<1,TypifyCellType,PerformGenericRename>(a.type().cell_type(), - a, param); -} - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_rename.h b/eval/src/vespa/eval/instruction/generic_rename.h index 4088e817b90..6c94ff02b24 100644 --- a/eval/src/vespa/eval/instruction/generic_rename.h +++ b/eval/src/vespa/eval/instruction/generic_rename.h @@ -44,12 +44,6 @@ struct GenericRename { const std::vector<vespalib::string> &rename_dimension_from, const std::vector<vespalib::string> &rename_dimension_to, const ValueBuilderFactory &factory, Stash &stash); - - static Value::UP - perform_rename(const Value &a, - const std::vector<vespalib::string> &rename_dimension_from, - const std::vector<vespalib::string> &rename_dimension_to, - const ValueBuilderFactory &factory); }; } // namespace diff --git a/eval/src/vespa/eval/tensor/CMakeLists.txt b/eval/src/vespa/eval/tensor/CMakeLists.txt index 30f36abacbf..c2968bd3efd 100644 --- a/eval/src/vespa/eval/tensor/CMakeLists.txt +++ b/eval/src/vespa/eval/tensor/CMakeLists.txt @@ -1,9 +1,7 @@ # Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. vespa_add_library(eval_tensor OBJECT SOURCES - default_tensor_engine.cpp partial_update.cpp tensor.cpp tensor_address.cpp - wrapped_simple_value.cpp ) diff --git a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp deleted file mode 100644 index 3ac342217ac..00000000000 --- a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "default_tensor_engine.h" -#include "tensor.h" -#include "wrapped_simple_value.h" -#include "serialization/typed_binary_format.h" -#include "sparse/sparse_tensor_address_builder.h" -#include "sparse/direct_sparse_tensor_builder.h" -#include "dense/dense_tensor.h" -#include "dense/typed_dense_tensor_builder.h" -#include <vespa/eval/instruction/dense_dot_product_function.h> -#include <vespa/eval/instruction/dense_xw_product_function.h> -#include <vespa/eval/instruction/dense_matmul_function.h> -#include <vespa/eval/instruction/dense_multi_matmul_function.h> -#include "dense/dense_fast_rename_optimizer.h" -#include "dense/dense_add_dimension_optimizer.h" -#include "dense/dense_single_reduce_function.h" -#include "dense/dense_remove_dimension_optimizer.h" -#include <vespa/eval/instruction/dense_lambda_peek_optimizer.h> -#include "dense/dense_lambda_function.h" -#include <vespa/eval/instruction/dense_simple_expand_function.h> -#include "dense/dense_simple_join_function.h" -#include "dense/dense_number_join_function.h" -#include "dense/dense_pow_as_map_optimizer.h" -#include "dense/dense_simple_map_function.h" -#include "dense/vector_from_doubles_function.h" -#include "dense/dense_tensor_create_function.h" -#include <vespa/eval/instruction/dense_tensor_peek_function.h> -#include <vespa/eval/eval/value.h> -#include <vespa/eval/eval/engine_or_factory.h> -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/eval/simple_value.h> -#include <vespa/eval/eval/operation.h> -#include <vespa/vespalib/objects/nbostream.h> -#include <vespa/vespalib/util/exceptions.h> -#include <cassert> - -#include <vespa/log/log.h> -LOG_SETUP(".eval.tensor.default_tensor_engine"); - -namespace vespalib::tensor { - -using eval::Aggr; -using eval::Aggregator; -using eval::DoubleValue; -using eval::TensorFunction; -using eval::TensorSpec; -using eval::Value; -using eval::ValueType; -using vespalib::IllegalArgumentException; -using vespalib::make_string; - -using map_fun_t = vespalib::eval::operation::op1_t; -using join_fun_t = vespalib::eval::operation::op2_t; - -namespace { - -constexpr size_t UNDEFINED_IDX = std::numeric_limits<size_t>::max(); - -const eval::EngineOrFactory &simple_engine() { - static eval::EngineOrFactory engine(eval::SimpleValueBuilderFactory::get()); - return engine; -} -const eval::TensorEngine &default_engine() { return DefaultTensorEngine::ref(); } - -// map tensors to simple tensors before fall-back evaluation - -const Value &to_simple(const Value &value, Stash &stash) { - if (auto tensor = value.as_tensor()) { - if (auto wrapped = dynamic_cast<const WrappedSimpleValue *>(tensor)) { - return wrapped->unwrap(); - } - nbostream data; - tensor->engine().encode(*tensor, data); - return *stash.create<Value::UP>(simple_engine().decode(data)); - } - return value; -} - -// map tensors to default tensors after fall-back evaluation - -const Value &to_default(const Value &value, Stash &stash) { - if (! value.type().is_double()) { - if (! Tensor::supported({value.type()})) { - return stash.create<WrappedSimpleValue>(value); - } - nbostream data; - simple_engine().encode(value, data); - return *stash.create<Value::UP>(default_engine().decode(data)); - } - return value; -} - -const Value &to_value(std::unique_ptr<Tensor> tensor, Stash &stash) { - assert(tensor); - if (tensor->type().is_tensor()) { - return *stash.create<Value::UP>(std::move(tensor)); - } - return stash.create<DoubleValue>(tensor->as_double()); -} - -Value::UP to_value(std::unique_ptr<Tensor> tensor) { - if (tensor->type().is_tensor()) { - return tensor; - } - return std::make_unique<DoubleValue>(tensor->as_double()); -} - -const Value &fallback_join(const Value &a, const Value &b, join_fun_t function, Stash &stash) { - return to_default(simple_engine().join(to_simple(a, stash), to_simple(b, stash), function, stash), stash); -} - -const Value &fallback_merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) { - return to_default(simple_engine().merge(to_simple(a, stash), to_simple(b, stash), function, stash), stash); -} - -const Value &fallback_reduce(const Value &a, eval::Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) { - return to_default(simple_engine().reduce(to_simple(a, stash), aggr, dimensions, stash), stash); -} - -size_t calculate_cell_index(const ValueType &type, const TensorSpec::Address &address) { - if (type.dimensions().size() != address.size()) { - return UNDEFINED_IDX; - } - size_t d = 0; - size_t idx = 0; - for (const auto &binding: address) { - const auto &dim = type.dimensions()[d++]; - if ((dim.name != binding.first) || (binding.second.index >= dim.size)) { - return UNDEFINED_IDX; - } - idx *= dim.size; - idx += binding.second.index; - } - return idx; -} - -bool build_cell_address(const ValueType &type, const TensorSpec::Address &address, - SparseTensorAddressBuilder &builder) -{ - if (type.dimensions().size() != address.size()) { - return false; - } - size_t d = 0; - builder.clear(); - for (const auto &binding: address) { - const auto &dim = type.dimensions()[d++]; - if (dim.name != binding.first) { - return false; - } - builder.add(binding.second.name); - } - return true; -} - -void bad_spec(const TensorSpec &spec) { - throw IllegalArgumentException(make_string("malformed tensor spec: %s", spec.to_string().c_str())); -} - -} // namespace vespalib::tensor::<unnamed> - -const DefaultTensorEngine DefaultTensorEngine::_engine; - -TensorSpec -DefaultTensorEngine::to_spec(const Value &value) const -{ - if (value.is_double()) { - return TensorSpec("double").add({}, value.as_double()); - } else if (auto tensor = value.as_tensor()) { - assert(&tensor->engine() == this); - const tensor::Tensor &my_tensor = static_cast<const tensor::Tensor &>(*tensor); - return my_tensor.toSpec(); - } else { - return TensorSpec("error"); - } -} - -struct CallDenseTensorBuilder { - template <typename CT> - static Value::UP - invoke(const ValueType &type, const TensorSpec &spec) - { - TypedDenseTensorBuilder<CT> builder(type); - for (const auto &cell: spec.cells()) { - const auto &address = cell.first; - size_t cell_idx = calculate_cell_index(type, address); - if (cell_idx == UNDEFINED_IDX) { - bad_spec(spec); - } - builder.insertCell(cell_idx, cell.second); - } - return builder.build(); - } -}; - -struct CallSparseTensorBuilder { - template <typename CT> - static Value::UP - invoke(const ValueType &type, const TensorSpec &spec) - { - DirectSparseTensorBuilder<CT> builder(type); - builder.reserve(spec.cells().size()); - SparseTensorAddressBuilder address_builder; - for (const auto &cell: spec.cells()) { - const auto &address = cell.first; - if (build_cell_address(type, address, address_builder)) { - builder.insertCell(address_builder, cell.second); - } else { - bad_spec(spec); - } - } - return builder.build(); - } -}; - -using MyTypify = eval::TypifyCellType; - -Value::UP -DefaultTensorEngine::from_spec(const TensorSpec &spec) const -{ - ValueType type = ValueType::from_spec(spec.type()); - if (type.is_error()) { - bad_spec(spec); - } else if (type.is_double()) { - double value = spec.cells().empty() ? 0.0 : spec.cells().begin()->second.value; - return std::make_unique<DoubleValue>(value); - } else if (type.is_dense()) { - return typify_invoke<1,MyTypify,CallDenseTensorBuilder>(type.cell_type(), type, spec); - } else if (type.is_sparse()) { - return typify_invoke<1,MyTypify,CallSparseTensorBuilder>(type.cell_type(), type, spec); - } - return std::make_unique<WrappedSimpleValue>(simple_engine().from_spec(spec)); -} - -struct CellFunctionFunAdapter : tensor::CellFunction { - map_fun_t fun; - CellFunctionFunAdapter(map_fun_t fun_in) : fun(fun_in) {} - virtual double apply(double value) const override { return fun(value); } -}; - -struct CellFunctionBindLeftAdapter : tensor::CellFunction { - join_fun_t fun; - double a; - CellFunctionBindLeftAdapter(join_fun_t fun_in, double bound) : fun(fun_in), a(bound) {} - virtual double apply(double b) const override { return fun(a, b); } -}; - -struct CellFunctionBindRightAdapter : tensor::CellFunction { - join_fun_t fun; - double b; - CellFunctionBindRightAdapter(join_fun_t fun_in, double bound) : fun(fun_in), b(bound) {} - virtual double apply(double a) const override { return fun(a, b); } -}; - -//----------------------------------------------------------------------------- - -void -DefaultTensorEngine::encode(const Value &value, nbostream &output) const -{ - if (auto tensor = value.as_tensor()) { - TypedBinaryFormat::serialize(output, static_cast<const tensor::Tensor &>(*tensor)); - } else { - TypedBinaryFormat::serialize(output, DenseTensor<double>(ValueType::double_type(), {value.as_double()})); - } -} - -Value::UP -DefaultTensorEngine::decode(nbostream &input) const -{ - return to_value(TypedBinaryFormat::deserialize(input)); -} - -//----------------------------------------------------------------------------- - -const TensorFunction & -DefaultTensorEngine::optimize(const TensorFunction &expr, Stash &stash) const -{ - using Child = TensorFunction::Child; - Child root(expr); - { - std::vector<Child::CREF> nodes({root}); - for (size_t i = 0; i < nodes.size(); ++i) { - nodes[i].get().get().push_children(nodes); - } - while (!nodes.empty()) { - const Child &child = nodes.back().get(); - child.set(eval::DenseDotProductFunction::optimize(child.get(), stash)); - child.set(eval::DenseXWProductFunction::optimize(child.get(), stash)); - child.set(eval::DenseMatMulFunction::optimize(child.get(), stash)); - child.set(eval::DenseMultiMatMulFunction::optimize(child.get(), stash)); - nodes.pop_back(); - } - } - { - std::vector<Child::CREF> nodes({root}); - for (size_t i = 0; i < nodes.size(); ++i) { - nodes[i].get().get().push_children(nodes); - } - while (!nodes.empty()) { - const Child &child = nodes.back().get(); - child.set(eval::DenseSimpleExpandFunction::optimize(child.get(), stash)); - child.set(DenseAddDimensionOptimizer::optimize(child.get(), stash)); - child.set(DenseRemoveDimensionOptimizer::optimize(child.get(), stash)); - child.set(VectorFromDoublesFunction::optimize(child.get(), stash)); - child.set(DenseTensorCreateFunction::optimize(child.get(), stash)); - child.set(eval::DenseTensorPeekFunction::optimize(child.get(), stash)); - child.set(eval::DenseLambdaPeekOptimizer::optimize(child.get(), stash)); - child.set(DenseLambdaFunction::optimize(child.get(), stash)); - child.set(DenseFastRenameOptimizer::optimize(child.get(), stash)); - child.set(DensePowAsMapOptimizer::optimize(child.get(), stash)); - child.set(DenseSimpleMapFunction::optimize(child.get(), stash)); - child.set(DenseSimpleJoinFunction::optimize(child.get(), stash)); - child.set(DenseNumberJoinFunction::optimize(child.get(), stash)); - child.set(DenseSingleReduceFunction::optimize(child.get(), stash)); - nodes.pop_back(); - } - } - return root.get(); -} - -//----------------------------------------------------------------------------- - -const Value & -DefaultTensorEngine::map(const Value &a, map_fun_t function, Stash &stash) const -{ - if (auto tensor = a.as_tensor()) { - assert(&tensor->engine() == this); - const tensor::Tensor &my_a = static_cast<const tensor::Tensor &>(*tensor); - if (!tensor::Tensor::supported({my_a.type()})) { - return to_default(simple_engine().map(to_simple(a, stash), function, stash), stash); - } - CellFunctionFunAdapter cell_function(function); - return to_value(my_a.apply(cell_function), stash); - } else { - return stash.create<DoubleValue>(function(a.as_double())); - } -} - -const Value & -DefaultTensorEngine::join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const -{ - if (auto tensor_a = a.as_tensor()) { - assert(&tensor_a->engine() == this); - const tensor::Tensor &my_a = static_cast<const tensor::Tensor &>(*tensor_a); - if (auto tensor_b = b.as_tensor()) { - assert(&tensor_b->engine() == this); - const tensor::Tensor &my_b = static_cast<const tensor::Tensor &>(*tensor_b); - if (!tensor::Tensor::supported({my_a.type(), my_b.type()})) { - return fallback_join(a, b, function, stash); - } - return to_value(my_a.join(function, my_b), stash); - } else { - if (!tensor::Tensor::supported({my_a.type()})) { - return fallback_join(a, b, function, stash); - } - CellFunctionBindRightAdapter cell_function(function, b.as_double()); - return to_value(my_a.apply(cell_function), stash); - } - } else { - if (auto tensor_b = b.as_tensor()) { - assert(&tensor_b->engine() == this); - const tensor::Tensor &my_b = static_cast<const tensor::Tensor &>(*tensor_b); - if (!tensor::Tensor::supported({my_b.type()})) { - return fallback_join(a, b, function, stash); - } - CellFunctionBindLeftAdapter cell_function(function, a.as_double()); - return to_value(my_b.apply(cell_function), stash); - } else { - return stash.create<DoubleValue>(function(a.as_double(), b.as_double())); - } - } -} - -const Value & -DefaultTensorEngine::merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const -{ - if (auto tensor_a = a.as_tensor()) { - auto tensor_b = b.as_tensor(); - assert(tensor_b); - assert(&tensor_a->engine() == this); - assert(&tensor_b->engine() == this); - const tensor::Tensor &my_a = static_cast<const tensor::Tensor &>(*tensor_a); - const tensor::Tensor &my_b = static_cast<const tensor::Tensor &>(*tensor_b); - if (!tensor::Tensor::supported({my_a.type(), my_b.type()})) { - return fallback_merge(a, b, function, stash); - } - return to_value(my_a.merge(function, my_b), stash); - } else { - return stash.create<DoubleValue>(function(a.as_double(), b.as_double())); - } -} - -const Value & -DefaultTensorEngine::reduce(const Value &a, Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) const -{ - if (auto tensor = a.as_tensor()) { - assert(&tensor->engine() == this); - const tensor::Tensor &my_a = static_cast<const tensor::Tensor &>(*tensor); - if (!tensor::Tensor::supported({my_a.type()})) { - return fallback_reduce(a, aggr, dimensions, stash); - } - switch (aggr) { - case Aggr::PROD: return to_value(my_a.reduce(eval::operation::Mul::f, dimensions), stash); - case Aggr::SUM: - if (dimensions.empty()) { - return stash.create<eval::DoubleValue>(my_a.as_double()); - } else { - return to_value(my_a.reduce(eval::operation::Add::f, dimensions), stash); - } - case Aggr::MAX: return to_value(my_a.reduce(eval::operation::Max::f, dimensions), stash); - case Aggr::MIN: return to_value(my_a.reduce(eval::operation::Min::f, dimensions), stash); - default: - return fallback_reduce(a, aggr, dimensions, stash); - } - } else { - Aggregator &aggregator = Aggregator::create(aggr, stash); - aggregator.first(a.as_double()); - return stash.create<DoubleValue>(aggregator.result()); - } -} - -size_t vector_size(const ValueType &type, const vespalib::string &dimension) { - if (type.is_double()) { - return 1; - } else if ((type.dimensions().size() == 1) && - (type.dimensions()[0].is_indexed()) && - (type.dimensions()[0].name == dimension)) - { - return type.dimensions()[0].size; - } else { - return 0; - } -} - -template <typename OCT> -struct CallAppendVector { - template <typename CT> - static void call(const ConstArrayRef<CT> &arr, OCT *&pos) { - for (CT cell: arr) { *pos++ = cell; } - } -}; - -template <typename OCT> -void append_vector(OCT *&pos, const Value &value) { - if (auto tensor = value.as_tensor()) { - dispatch_1<CallAppendVector<OCT> >(tensor->cells(), pos); - } else { - *pos++ = value.as_double(); - } -} - -template <typename OCT> -const Value &concat_vectors(const Value &a, const Value &b, const vespalib::string &dimension, size_t vector_size, Stash &stash) { - ArrayRef<OCT> cells = stash.create_uninitialized_array<OCT>(vector_size); - OCT *pos = cells.begin(); - append_vector<OCT>(pos, a); - append_vector<OCT>(pos, b); - assert(pos == cells.end()); - const ValueType &type = stash.create<ValueType>(ValueType::tensor_type({ValueType::Dimension(dimension, vector_size)}, ValueType::unify_cell_types(a.type(), b.type()))); - return stash.create<DenseTensorView>(type, TypedCells(cells)); -} - -struct CallConcatVectors { - template <typename OCT> - static const Value &invoke(const Value &a, const Value &b, const vespalib::string &dimension, size_t vector_size, Stash &stash) { - return concat_vectors<OCT>(a, b, dimension, vector_size, stash); - } -}; - -const Value & -DefaultTensorEngine::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const -{ - size_t a_size = vector_size(a.type(), dimension); - size_t b_size = vector_size(b.type(), dimension); - if ((a_size > 0) && (b_size > 0)) { - CellType result_cell_type = ValueType::unify_cell_types(a.type(), b.type()); - return typify_invoke<1,MyTypify,CallConcatVectors>(result_cell_type, a, b, dimension, (a_size + b_size), stash); - } - return to_default(simple_engine().concat(to_simple(a, stash), to_simple(b, stash), dimension, stash), stash); -} - -const Value & -DefaultTensorEngine::rename(const Value &a, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const -{ - return to_default(simple_engine().rename(to_simple(a, stash), from, to, stash), stash); -} - -//----------------------------------------------------------------------------- - -} diff --git a/eval/src/vespa/eval/tensor/default_tensor_engine.h b/eval/src/vespa/eval/tensor/default_tensor_engine.h deleted file mode 100644 index 5c39706b326..00000000000 --- a/eval/src/vespa/eval/tensor/default_tensor_engine.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/eval/eval/tensor_engine.h> - -namespace vespalib::tensor { - -/** - * This is a tensor engine implementation wrapping the default tensor - * implementations (dense/sparse). - **/ -class DefaultTensorEngine : public eval::TensorEngine -{ -private: - DefaultTensorEngine() {} - static const DefaultTensorEngine _engine; -public: - static const TensorEngine &ref() { return _engine; }; - - TensorSpec to_spec(const Value &value) const override; - std::unique_ptr<Value> from_spec(const TensorSpec &spec) const override; - - void encode(const Value &value, nbostream &output) const override; - std::unique_ptr<Value> decode(nbostream &input) const override; - - const TensorFunction &optimize(const TensorFunction &expr, Stash &stash) const override; - - const Value &map(const Value &a, map_fun_t function, Stash &stash) const override; - const Value &join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; - const Value &merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; - const Value &reduce(const Value &a, Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) const override; - const Value &concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const override; - const Value &rename(const Value &a, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const override; -}; - -} diff --git a/eval/src/vespa/eval/tensor/dense/dense_number_join_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_number_join_function.cpp index d4b1ee4506e..e0e66aae01c 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_number_join_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_number_join_function.cpp @@ -15,7 +15,6 @@ using eval::CellType; using eval::Value; using eval::ValueType; using eval::TensorFunction; -using eval::TensorEngine; using eval::TypifyCellType; using eval::as; diff --git a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp index c12ad21c7fb..d7bc7dc860d 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp @@ -9,7 +9,6 @@ namespace vespalib::tensor { using eval::Value; using eval::ValueType; using eval::TensorFunction; -using eval::TensorEngine; using eval::as; using namespace eval::tensor_function; diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp index 02867f646b4..8e7bd72a0f6 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp @@ -18,7 +18,6 @@ using eval::CellType; using eval::Value; using eval::ValueType; using eval::TensorFunction; -using eval::TensorEngine; using eval::TypifyCellType; using eval::as; diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp index 4c7b1b3dee8..b6376326468 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp @@ -14,7 +14,6 @@ using vespalib::ArrayRef; using eval::Value; using eval::ValueType; using eval::TensorFunction; -using eval::TensorEngine; using eval::TypifyCellType; using eval::as; diff --git a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp index c692f7c4a0f..82d4505dc80 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp @@ -10,7 +10,6 @@ namespace vespalib::tensor { using eval::Aggr; using eval::InterpretedFunction; -using eval::TensorEngine; using eval::TensorFunction; using eval::Value; using eval::ValueType; diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp index f425ce4fd1c..4cdaa01eea8 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp @@ -12,7 +12,6 @@ using eval::DoubleValue; using eval::ValueType; using eval::TensorSpec; using eval::TensorFunction; -using eval::TensorEngine; using Child = eval::TensorFunction::Child; using eval::as; using namespace eval::tensor_function; diff --git a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp b/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp index a5e26665741..0d653acee4d 100644 --- a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp @@ -9,7 +9,6 @@ namespace vespalib::tensor { using eval::Value; using eval::ValueType; using eval::TensorFunction; -using eval::TensorEngine; using Child = eval::TensorFunction::Child; using eval::as; using namespace eval::tensor_function; diff --git a/eval/src/vespa/eval/tensor/partial_update.cpp b/eval/src/vespa/eval/tensor/partial_update.cpp index fa15b2a38ae..82cd5553741 100644 --- a/eval/src/vespa/eval/tensor/partial_update.cpp +++ b/eval/src/vespa/eval/tensor/partial_update.cpp @@ -8,8 +8,6 @@ #include <cassert> #include <set> #include "tensor.h" -#include "cell_values.h" -#include <vespa/eval/tensor/sparse/sparse_tensor.h> #include <vespa/log/log.h> LOG_SETUP(".eval.tensor.partial_update"); @@ -424,57 +422,37 @@ TensorPartialUpdate::modify(const Value &input, join_fun_t function, const Value &modifier, EngineOrFactory engine) { if (engine.is_engine()) { - auto inp_ptr = dynamic_cast<const tensor::Tensor *>(&input); - auto mod_ptr = dynamic_cast<const SparseTensor *>(&modifier); - if (inp_ptr && mod_ptr) { - vespalib::tensor::CellValues cellValues(*mod_ptr); - return inp_ptr->modify(function, cellValues); - } - return {}; - } else { - return modify(input, function, modifier, engine.factory()); + abort(); } + return modify(input, function, modifier, engine.factory()); + } Value::UP TensorPartialUpdate::add(const Value &input, const Value &add_cells, EngineOrFactory engine) { if (engine.is_engine()) { - auto inp_ptr = dynamic_cast<const tensor::Tensor *>(&input); - auto add_ptr = dynamic_cast<const tensor::Tensor *>(&add_cells); - if (inp_ptr && add_ptr) { - return inp_ptr->add(*add_ptr); - } - return {}; - } else { - return add(input, add_cells, engine.factory()); + abort(); } + return add(input, add_cells, engine.factory()); } Value::UP TensorPartialUpdate::remove(const Value &input, const Value &remove_spec, EngineOrFactory engine) { if (engine.is_engine()) { - auto inp_ptr = dynamic_cast<const tensor::Tensor *>(&input); - auto rem_ptr = dynamic_cast<const SparseTensor *>(&remove_spec); - if (inp_ptr && rem_ptr) { - vespalib::tensor::CellValues cellAddresses(*rem_ptr); - return inp_ptr->remove(cellAddresses); - } - return {}; - } else { - return remove(input, remove_spec, engine.factory()); + abort(); } + return remove(input, remove_spec, engine.factory()); } bool TensorPartialUpdate::check_suitably_sparse(const Value &modifier, const EngineOrFactory engine) { if (engine.is_engine()) { - return (dynamic_cast<const SparseTensor *>(&modifier) != nullptr); - } else { - return modifier.type().is_sparse(); + abort(); } + return modifier.type().is_sparse(); } } // namespace diff --git a/eval/src/vespa/eval/tensor/serialization/CMakeLists.txt b/eval/src/vespa/eval/tensor/serialization/CMakeLists.txt deleted file mode 100644 index fc9ac64ea68..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_library(eval_tensor_serialization OBJECT - SOURCES - sparse_binary_format.cpp - dense_binary_format.cpp - typed_binary_format.cpp -) diff --git a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp deleted file mode 100644 index 837b135c0aa..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "dense_binary_format.h" -#include <vespa/eval/tensor/dense/dense_tensor.h> -#include <vespa/vespalib/objects/nbostream.h> -#include <vespa/vespalib/util/exceptions.h> -#include <cassert> - -using vespalib::nbostream; -using vespalib::eval::ValueType; -using vespalib::eval::CellType; - -namespace vespalib::tensor { - -using Dimension = eval::ValueType::Dimension; - - -namespace { - -size_t encodeDimensions(nbostream &stream, const eval::ValueType & type) { - stream.putInt1_4Bytes(type.dimensions().size()); - size_t cellsSize = 1; - for (const auto &dimension : type.dimensions()) { - stream.writeSmallString(dimension.name); - stream.putInt1_4Bytes(dimension.size); - cellsSize *= dimension.size; - } - return cellsSize; -} - -template<typename T> -void encodeCells(nbostream &stream, TypedCells cells) { - auto arr = cells.typify<T>(); - for (const auto &value : arr) { - stream << value; - } -} - -size_t decodeDimensions(nbostream & stream, std::vector<Dimension> & dimensions) { - vespalib::string dimensionName; - size_t dimensionsSize = stream.getInt1_4Bytes(); - size_t dimensionSize; - size_t cellsSize = 1; - while (dimensions.size() < dimensionsSize) { - stream.readSmallString(dimensionName); - dimensionSize = stream.getInt1_4Bytes(); - dimensions.emplace_back(dimensionName, dimensionSize); - cellsSize *= dimensionSize; - } - return cellsSize; -} - -template<typename T, typename V> -void decodeCells(nbostream &stream, size_t cellsSize, V &cells) { - T cellValue = 0.0; - for (size_t i = 0; i < cellsSize; ++i) { - stream >> cellValue; - cells.emplace_back(cellValue); - } -} - -template <typename V> -void decodeCells(CellType cell_type, nbostream &stream, size_t cellsSize, V &cells) { - switch (cell_type) { - case CellType::DOUBLE: - decodeCells<double>(stream, cellsSize, cells); - break; - case CellType::FLOAT: - decodeCells<float>(stream, cellsSize, cells); - break; - } -} - -} - -void -DenseBinaryFormat::serialize(nbostream &stream, const DenseTensorView &tensor) -{ - size_t cellsSize = encodeDimensions(stream, tensor.fast_type()); - TypedCells cells = tensor.cells(); - assert(cells.size == cellsSize); - switch (tensor.fast_type().cell_type()) { - case CellType::DOUBLE: - encodeCells<double>(stream, cells); - break; - case CellType::FLOAT: - encodeCells<float>(stream, cells); - break; - } -} - -struct CallDecodeCells { - template <typename CT> - static std::unique_ptr<DenseTensorView> - invoke(nbostream &stream, size_t numCells, ValueType &&newType) { - std::vector<CT> newCells; - newCells.reserve(numCells); - decodeCells<CT>(stream, numCells, newCells); - return std::make_unique<DenseTensor<CT>>(std::move(newType), std::move(newCells)); - } -}; - -std::unique_ptr<DenseTensorView> -DenseBinaryFormat::deserialize(nbostream &stream, CellType cell_type) -{ - std::vector<Dimension> dimensions; - size_t numCells = decodeDimensions(stream, dimensions); - ValueType newType = ValueType::tensor_type(std::move(dimensions), cell_type); - using MyTypify = eval::TypifyCellType; - return typify_invoke<1,MyTypify,CallDecodeCells>(cell_type, stream, numCells, std::move(newType)); -} - -template <typename T> -void -DenseBinaryFormat::deserializeCellsOnly(nbostream &stream, std::vector<T> &cells, CellType cell_type) -{ - std::vector<Dimension> dimensions; - size_t cellsSize = decodeDimensions(stream, dimensions); - cells.clear(); - cells.reserve(cellsSize); - decodeCells(cell_type, stream, cellsSize, cells); -} - -template void DenseBinaryFormat::deserializeCellsOnly(nbostream &stream, std::vector<double> &cells, CellType cell_type); -template void DenseBinaryFormat::deserializeCellsOnly(nbostream &stream, std::vector<float> &cells, CellType cell_type); - -} diff --git a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h deleted file mode 100644 index f0516e9fcc9..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <memory> -#include <vector> -#include <vespa/eval/eval/value_type.h> - -namespace vespalib { class nbostream; } - -namespace vespalib::tensor { - -class DenseTensorView; - -/** - * Class for serializing a dense tensor. - */ -class DenseBinaryFormat -{ -public: - using CellType = vespalib::eval::CellType; - - static void serialize(nbostream &stream, const DenseTensorView &tensor); - static std::unique_ptr<DenseTensorView> deserialize(nbostream &stream, CellType cell_type); - - // This is a temporary method untill we get full support for typed tensors - template <typename T> - static void deserializeCellsOnly(nbostream &stream, std::vector<T> &cells, CellType cell_type); -}; - -} diff --git a/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.cpp b/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.cpp deleted file mode 100644 index a4022c4f60a..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "sparse_binary_format.h" -#include <vespa/eval/eval/value_type.h> -#include <vespa/eval/tensor/types.h> -#include <vespa/eval/tensor/tensor.h> -#include <vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h> -#include <vespa/eval/tensor/sparse/sparse_tensor_address_builder.h> -#include <vespa/eval/tensor/tensor_visitor.h> -#include <vespa/vespalib/objects/nbostream.h> -#include <sstream> -#include <cassert> - -using vespalib::nbostream; -using vespalib::eval::CellType; -using vespalib::eval::ValueType; - -namespace vespalib::tensor { - -namespace { - -vespalib::string undefinedLabel(""); - -void writeTensorAddress(nbostream &output, - const eval::ValueType &type, - const TensorAddress &value) -{ - auto elemItr = value.elements().cbegin(); - auto elemItrEnd = value.elements().cend(); - for (const auto &dimension : type.dimensions()) { - if (elemItr != elemItrEnd && dimension.name == elemItr->dimension()) { - output.writeSmallString(elemItr->label()); - ++elemItr; - } else { - output.writeSmallString(undefinedLabel); - } - } - assert(elemItr == elemItrEnd); -} - -template <typename T> -class SparseBinaryFormatSerializer : public TensorVisitor -{ -private: - uint32_t _num_cells; - nbostream &_cells; - const ValueType &_type; -public: - SparseBinaryFormatSerializer(nbostream &cells, const ValueType &type); - size_t num_cells() const { return _num_cells; } - virtual ~SparseBinaryFormatSerializer() override; - virtual void visit(const TensorAddress &address, double value) override; -}; - -template <typename T> -SparseBinaryFormatSerializer<T>::SparseBinaryFormatSerializer(nbostream &cells, const ValueType &type) - : _num_cells(0), - _cells(cells), - _type(type) -{ -} - -template <typename T> -SparseBinaryFormatSerializer<T>::~SparseBinaryFormatSerializer() = default; - -template <typename T> -void -SparseBinaryFormatSerializer<T>::visit(const TensorAddress &address, double value) -{ - ++_num_cells; - writeTensorAddress(_cells, _type, address); - _cells << static_cast<T>(value); -} - -void encodeDimensions(nbostream &stream, const eval::ValueType &type) { - stream.putInt1_4Bytes(type.dimensions().size()); - for (const auto &dimension : type.dimensions()) { - stream.writeSmallString(dimension.name); - } -} - -template <typename T> -size_t encodeCells(nbostream &stream, const Tensor &tensor) { - SparseBinaryFormatSerializer<T> serializer(stream, tensor.type()); - tensor.accept(serializer); - return serializer.num_cells(); -} - -size_t encodeCells(nbostream &stream, const Tensor &tensor, CellType cell_type) { - switch (cell_type) { - case CellType::DOUBLE: - return encodeCells<double>(stream, tensor); - break; - case CellType::FLOAT: - return encodeCells<float>(stream, tensor); - break; - } - return 0; -} - -template<typename T> -void decodeCells(nbostream &stream, size_t dimensionsSize, size_t cellsSize, DirectSparseTensorBuilder<T> &builder) { - T cellValue = 0.0; - vespalib::string str; - SparseTensorAddressBuilder address; - for (size_t cellIdx = 0; cellIdx < cellsSize; ++cellIdx) { - address.clear(); - for (size_t dimension = 0; dimension < dimensionsSize; ++dimension) { - stream.readSmallString(str); - if (!str.empty()) { - address.add(str); - } else { - address.addUndefined(); - } - } - stream >> cellValue; - builder.insertCell(address, cellValue, [](double, double v){ return v; }); - } -} - -} - -void -SparseBinaryFormat::serialize(nbostream &stream, const Tensor &tensor) -{ - const auto &type = tensor.type(); - encodeDimensions(stream, type); - nbostream cells; - size_t numCells = encodeCells(cells, tensor, type.cell_type()); - stream.putInt1_4Bytes(numCells); - stream.write(cells.peek(), cells.size()); -} - -struct BuildSparseCells { - template<typename CT> - static Tensor::UP invoke(ValueType type, nbostream &stream, - size_t dimensionsSize, - size_t cellsSize) - { - DirectSparseTensorBuilder<CT> builder(std::move(type)); - builder.reserve(cellsSize); - decodeCells<CT>(stream, dimensionsSize, cellsSize, builder); - auto retval = builder.build(); - if (retval->should_shrink()) { - return retval->shrink(); - } else { - return retval; - } - } -}; - -std::unique_ptr<Tensor> -SparseBinaryFormat::deserialize(nbostream &stream, CellType cell_type) -{ - vespalib::string str; - size_t dimensionsSize = stream.getInt1_4Bytes(); - std::vector<ValueType::Dimension> dimensions; - while (dimensions.size() < dimensionsSize) { - stream.readSmallString(str); - dimensions.emplace_back(str); - } - size_t cellsSize = stream.getInt1_4Bytes(); - ValueType type = ValueType::tensor_type(std::move(dimensions), cell_type); - return typify_invoke<1,eval::TypifyCellType,BuildSparseCells>(cell_type, - std::move(type), stream, dimensionsSize, cellsSize); -} - -} // namespace diff --git a/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.h b/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.h deleted file mode 100644 index d4c7fa4bf6f..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/sparse_binary_format.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <memory> -#include <vespa/eval/eval/value_type.h> - -namespace vespalib { class nbostream; } - -namespace vespalib::tensor { - -class Tensor; - -/** - * Class for serializing a sparse tensor. - */ -class SparseBinaryFormat -{ -public: - using CellType = eval::CellType; - - static void serialize(nbostream &stream, const Tensor &tensor); - static std::unique_ptr<Tensor> deserialize(nbostream &stream, CellType cell_type); -}; - -} diff --git a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp deleted file mode 100644 index 2d3d1f4a0ea..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "typed_binary_format.h" -#include "sparse_binary_format.h" -#include "dense_binary_format.h" -#include <vespa/vespalib/objects/nbostream.h> -#include <vespa/eval/tensor/tensor.h> -#include <vespa/eval/tensor/dense/dense_tensor.h> -#include <vespa/eval/eval/simple_value.h> -#include <vespa/eval/tensor/wrapped_simple_value.h> -#include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/eval/engine_or_factory.h> - -#include <vespa/log/log.h> -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/exceptions.h> - -LOG_SETUP(".eval.tensor.serialization.typed_binary_format"); - -using vespalib::nbostream; -using vespalib::eval::ValueType; -using vespalib::eval::CellType; - -namespace vespalib::tensor { - -namespace { - -const eval::EngineOrFactory &simple_engine() { - static eval::EngineOrFactory engine(eval::SimpleValueBuilderFactory::get()); - return engine; -} - -constexpr uint32_t SPARSE_BINARY_FORMAT_TYPE = 1u; -constexpr uint32_t DENSE_BINARY_FORMAT_TYPE = 2u; -constexpr uint32_t MIXED_BINARY_FORMAT_TYPE = 3u; -constexpr uint32_t SPARSE_BINARY_FORMAT_WITH_CELLTYPE = 5u; -constexpr uint32_t DENSE_BINARY_FORMAT_WITH_CELLTYPE = 6u; -constexpr uint32_t MIXED_BINARY_FORMAT_WITH_CELLTYPE = 7u; - -constexpr uint32_t DOUBLE_VALUE_TYPE = 0; -constexpr uint32_t FLOAT_VALUE_TYPE = 1; - -uint32_t cell_type_to_encoding(CellType cell_type) { - switch (cell_type) { - case CellType::DOUBLE: - return DOUBLE_VALUE_TYPE; - case CellType::FLOAT: - return FLOAT_VALUE_TYPE; - } - abort(); -} - -CellType -encoding_to_cell_type(uint32_t cell_encoding) { - switch (cell_encoding) { - case DOUBLE_VALUE_TYPE: - return CellType::DOUBLE; - case FLOAT_VALUE_TYPE: - return CellType::FLOAT; - default: - throw IllegalArgumentException(make_string("Received unknown tensor value type = %u. Only 0(double), or 1(float) are legal.", cell_encoding)); - } -} - -std::unique_ptr<Tensor> -wrap_simple_value(std::unique_ptr<eval::Value> simple) -{ - if (Tensor::supported({simple->type()})) { - nbostream data; - simple_engine().encode(*simple, data); - // note: some danger of infinite recursion here - return TypedBinaryFormat::deserialize(data); - } - return std::make_unique<WrappedSimpleValue>(std::move(simple)); -} - -} // namespace <unnamed> - -void -TypedBinaryFormat::serialize(nbostream &stream, const Tensor &tensor) -{ - auto cell_type = tensor.type().cell_type(); - bool default_cell_type = (cell_type == CellType::DOUBLE); - if (auto denseTensor = dynamic_cast<const DenseTensorView *>(&tensor)) { - if (default_cell_type) { - stream.putInt1_4Bytes(DENSE_BINARY_FORMAT_TYPE); - } else { - stream.putInt1_4Bytes(DENSE_BINARY_FORMAT_WITH_CELLTYPE); - stream.putInt1_4Bytes(cell_type_to_encoding(cell_type)); - } - DenseBinaryFormat::serialize(stream, *denseTensor); - } else if (dynamic_cast<const WrappedSimpleValue *>(&tensor)) { - eval::encode_value(tensor, stream); - } else { - if (default_cell_type) { - stream.putInt1_4Bytes(SPARSE_BINARY_FORMAT_TYPE); - } else { - stream.putInt1_4Bytes(SPARSE_BINARY_FORMAT_WITH_CELLTYPE); - stream.putInt1_4Bytes(cell_type_to_encoding(cell_type)); - } - SparseBinaryFormat::serialize(stream, tensor); - } -} - - -std::unique_ptr<Tensor> -TypedBinaryFormat::deserialize(nbostream &stream) -{ - auto cell_type = CellType::DOUBLE; - auto read_pos = stream.rp(); - auto formatId = stream.getInt1_4Bytes(); - switch (formatId) { - case SPARSE_BINARY_FORMAT_WITH_CELLTYPE: - cell_type = encoding_to_cell_type(stream.getInt1_4Bytes()); - [[fallthrough]]; - case SPARSE_BINARY_FORMAT_TYPE: - return SparseBinaryFormat::deserialize(stream, cell_type); - case DENSE_BINARY_FORMAT_WITH_CELLTYPE: - cell_type = encoding_to_cell_type(stream.getInt1_4Bytes()); - [[fallthrough]]; - case DENSE_BINARY_FORMAT_TYPE: - return DenseBinaryFormat::deserialize(stream, cell_type); - case MIXED_BINARY_FORMAT_TYPE: - case MIXED_BINARY_FORMAT_WITH_CELLTYPE: - stream.adjustReadPos(read_pos - stream.rp()); - return wrap_simple_value(simple_engine().decode(stream)); - default: - throw IllegalArgumentException(make_string("Received unknown tensor format type = %du.", formatId)); - } -} - -template <typename T> -void -TypedBinaryFormat::deserializeCellsOnlyFromDenseTensors(nbostream &stream, std::vector<T> &cells) -{ - auto cell_type = CellType::DOUBLE; - auto formatId = stream.getInt1_4Bytes(); - switch (formatId) { - case DENSE_BINARY_FORMAT_WITH_CELLTYPE: - cell_type = encoding_to_cell_type(stream.getInt1_4Bytes()); - [[fallthrough]]; - case DENSE_BINARY_FORMAT_TYPE: - return DenseBinaryFormat::deserializeCellsOnly(stream, cells, cell_type); - } - abort(); -} - -template void TypedBinaryFormat::deserializeCellsOnlyFromDenseTensors(nbostream &stream, std::vector<double> &cells); -template void TypedBinaryFormat::deserializeCellsOnlyFromDenseTensors(nbostream &stream, std::vector<float> &cells); - -} diff --git a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h deleted file mode 100644 index 198b09ae336..00000000000 --- a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <memory> -#include <vector> - -namespace vespalib { class nbostream; } - -namespace vespalib::tensor { - -class Tensor; - -/** - * Class for serializing a tensor. - */ -class TypedBinaryFormat -{ -public: - static void serialize(nbostream &stream, const Tensor &tensor); - static std::unique_ptr<Tensor> deserialize(nbostream &stream); - - // This is a temporary method until we get full support for typed tensors - template <typename T> - static void deserializeCellsOnlyFromDenseTensors(nbostream &stream, std::vector<T> &cells); -}; - -} diff --git a/eval/src/vespa/eval/tensor/tensor.cpp b/eval/src/vespa/eval/tensor/tensor.cpp index 51c94aab5b0..1b5671990a9 100644 --- a/eval/src/vespa/eval/tensor/tensor.cpp +++ b/eval/src/vespa/eval/tensor/tensor.cpp @@ -1,15 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "tensor.h" -#include "default_tensor_engine.h" #include <sstream> namespace vespalib::tensor { -Tensor::Tensor() - : eval::Tensor(DefaultTensorEngine::ref()) -{ -} +Tensor::Tensor() : eval::Tensor() {} bool Tensor::supported(TypeList types) diff --git a/eval/src/vespa/eval/tensor/test/test_utils.h b/eval/src/vespa/eval/tensor/test/test_utils.h deleted file mode 100644 index 5daae74284b..00000000000 --- a/eval/src/vespa/eval/tensor/test/test_utils.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/tensor/default_tensor_engine.h> -#include <vespa/vespalib/testkit/test_kit.h> - -namespace vespalib::tensor::test { - -template <typename T> -std::unique_ptr<T> -makeTensor(const vespalib::eval::TensorSpec &spec) -{ - auto value = DefaultTensorEngine::ref().from_spec(spec); - T *tensor = dynamic_cast<T *>(value.get()); - ASSERT_TRUE(tensor); - value.release(); - return std::unique_ptr<T>(tensor); -} - -} diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp b/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp deleted file mode 100644 index eb552c21aa0..00000000000 --- a/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "wrapped_simple_value.h" -#include "cell_values.h" -#include "tensor_address_builder.h" -#include "tensor_visitor.h" -#include <vespa/eval/eval/memory_usage_stuff.h> -#include <vespa/eval/eval/simple_value.h> -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/eval/value_codec.h> -#include <vespa/vespalib/util/stringfmt.h> - -#include <vespa/log/log.h> -LOG_SETUP(".eval.tensor.wrapped_simple_value"); - -using vespalib::eval::TensorSpec; -using vespalib::eval::SimpleValueBuilderFactory; - -namespace vespalib::tensor { - -namespace { - -TensorSpec::Address -sparsify_address(const TensorSpec::Address &address) -{ - TensorSpec::Address result; - for (const auto &elem : address) { - if (elem.second.is_indexed()) { - auto val = vespalib::make_string("%zu", elem.second.index); - result.emplace(elem.first, TensorSpec::Label(val)); - } else { - result.emplace(elem); - } - } - return result; -} - -TensorSpec::Address -extract_sparse_address(const TensorSpec::Address &address) -{ - TensorSpec::Address result; - for (const auto &elem : address) { - if (elem.second.is_mapped()) { - result.emplace(elem); - } - } - return result; -} - -Tensor::UP wrap(eval::Value::UP value) { - return std::make_unique<WrappedSimpleValue>(std::move(value)); -} - -} // namespace <unnamed> - - -eval::TensorSpec -WrappedSimpleValue::toSpec() const -{ - return spec_from_value(_tensor); -} - -void -WrappedSimpleValue::accept(TensorVisitor &visitor) const -{ - TensorSpec myspec = toSpec(); - TensorAddressBuilder addr; - for (const auto & cell : myspec.cells()) { - auto sparse_addr = sparsify_address(cell.first); - addr.clear(); - for (const auto & dim_and_label : sparse_addr) { - addr.add(dim_and_label.first, dim_and_label.second.name); - } - visitor.visit(addr.build(), cell.second); - } -} - -MemoryUsage -WrappedSimpleValue::get_memory_usage() const -{ - MemoryUsage rv = eval::self_memory_usage<WrappedSimpleValue>(); - if (_space) { - rv.merge(_space->get_memory_usage()); - } - return rv; -} - -//----------------------------------------------------------------------------- - -Tensor::UP -WrappedSimpleValue::apply(const CellFunction &) const -{ - LOG_ABORT("should not be reached"); -} - -Tensor::UP -WrappedSimpleValue::join(join_fun_t, const Tensor &) const -{ - LOG_ABORT("should not be reached"); -} - -Tensor::UP -WrappedSimpleValue::merge(join_fun_t, const Tensor &) const -{ - LOG_ABORT("should not be reached"); -} - -Tensor::UP -WrappedSimpleValue::reduce(join_fun_t, const std::vector<vespalib::string> &) const -{ - LOG_ABORT("should not be reached"); -} - -Tensor::UP -WrappedSimpleValue::modify(join_fun_t fun, const CellValues &cellValues) const -{ - TensorSpec a = toSpec(); - TensorSpec b = cellValues.toSpec(); - TensorSpec result(a.type()); - auto end_iter = b.cells().end(); - for (const auto &cell: a.cells()) { - double v = cell.second; - auto sparse_addr = sparsify_address(cell.first); - auto iter = b.cells().find(sparse_addr); - if (iter == end_iter) { - result.add(cell.first, v); - } else { - result.add(cell.first, fun(v, iter->second)); - } - } - return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); -} - -Tensor::UP -WrappedSimpleValue::add(const Tensor &rhs) const -{ - TensorSpec a = toSpec(); - TensorSpec b = rhs.toSpec(); - if (a.type() != b.type()) { - return {}; - } - TensorSpec result(a.type()); - for (const auto &cell: b.cells()) { - result.add(cell.first, cell.second); - } - auto end_iter = b.cells().end(); - for (const auto &cell: a.cells()) { - auto iter = b.cells().find(cell.first); - if (iter == end_iter) { - result.add(cell.first, cell.second); - } - } - return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); -} - - -Tensor::UP -WrappedSimpleValue::remove(const CellValues &rhs) const -{ - TensorSpec a = toSpec(); - TensorSpec b = rhs.toSpec(); - TensorSpec result(a.type()); - auto end_iter = b.cells().end(); - for (const auto &cell: a.cells()) { - TensorSpec::Address mappedAddress = extract_sparse_address(cell.first); - auto iter = b.cells().find(mappedAddress); - if (iter == end_iter) { - result.add(cell.first, cell.second); - } - } - return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); -} - -} diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.h b/eval/src/vespa/eval/tensor/wrapped_simple_value.h deleted file mode 100644 index 3d8c3e43757..00000000000 --- a/eval/src/vespa/eval/tensor/wrapped_simple_value.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include "tensor.h" -#include <vespa/eval/eval/value.h> -#include <vespa/eval/eval/aggr.h> - -namespace vespalib::tensor { - -/** - * A thin wrapper around a SimpleValue to be used as fallback for tensors with data - * layouts not supported by the default tensor implementation. - * - * Tensor implementation class is currently inferred from its value - * type. Consider adding explicit tagging to the tensor::Tensor - * default implementation top-level class in the future. - **/ -class WrappedSimpleValue : public Tensor -{ -private: - std::unique_ptr<eval::Value> _space; - const eval::Value &_tensor; -public: - explicit WrappedSimpleValue(const eval::Value &tensor) - : _space(), _tensor(tensor) {} - explicit WrappedSimpleValue(std::unique_ptr<eval::Value> tensor) - : _space(std::move(tensor)), _tensor(*_space) {} - ~WrappedSimpleValue() {} - const eval::Value &unwrap() const { return _tensor; } - - // Value API - const eval::ValueType &type() const override { return _tensor.type(); } - eval::TypedCells cells() const override { return _tensor.cells(); } - const Index &index() const override { return _tensor.index(); } - double as_double() const override { return _tensor.as_double(); } - - // tensor API - eval::TensorSpec toSpec() const override; - void accept(TensorVisitor &visitor) const override; - MemoryUsage get_memory_usage() const override; - - Tensor::UP join(join_fun_t fun, const Tensor &rhs) const override; - Tensor::UP merge(join_fun_t fun, const Tensor &rhs) const override; - Tensor::UP reduce(join_fun_t fun, const std::vector<vespalib::string> &dims) const override; - - Tensor::UP apply(const CellFunction & func) const override; - Tensor::UP modify(join_fun_t fun, const CellValues &cellValues) const override; - Tensor::UP add(const Tensor &rhs) const override; - Tensor::UP remove(const CellValues &rhs) const override; -}; - -} // namespace vespalib::tensor |