From b594edf34af42499f55a83d63ab87d0f58fa1f0a Mon Sep 17 00:00:00 2001 From: HÃ¥vard Pettersen Date: Tue, 13 Mar 2018 14:29:06 +0000 Subject: use ObjectVisitor to debug dump TensorFunction trees --- .../eval/tensor_function/tensor_function_test.cpp | 22 ++++ .../dense_inplace_join_function_test.cpp | 8 ++ .../dense_xw_product_function_test.cpp | 8 ++ eval/src/vespa/eval/eval/CMakeLists.txt | 1 + eval/src/vespa/eval/eval/tensor_function.cpp | 114 ++++++++++++++++++++- eval/src/vespa/eval/eval/tensor_function.h | 17 +++ eval/src/vespa/eval/eval/tensor_nodes.h | 28 ++--- eval/src/vespa/eval/eval/visit_stuff.cpp | 100 ++++++++++++++++++ eval/src/vespa/eval/eval/visit_stuff.h | 37 +++++++ .../vespa/eval/tensor/default_tensor_engine.cpp | 13 +-- .../tensor/dense/dense_inplace_join_function.cpp | 8 ++ .../tensor/dense/dense_inplace_join_function.h | 1 + .../eval/tensor/dense/dense_inplace_map_function.h | 3 - .../tensor/dense/dense_xw_product_function.cpp | 9 ++ .../eval/tensor/dense/dense_xw_product_function.h | 1 + 15 files changed, 341 insertions(+), 29 deletions(-) create mode 100644 eval/src/vespa/eval/eval/visit_stuff.cpp create mode 100644 eval/src/vespa/eval/eval/visit_stuff.h (limited to 'eval/src') diff --git a/eval/src/tests/eval/tensor_function/tensor_function_test.cpp b/eval/src/tests/eval/tensor_function/tensor_function_test.cpp index 41037fa06ef..23ea1e8c13a 100644 --- a/eval/src/tests/eval/tensor_function/tensor_function_test.cpp +++ b/eval/src/tests/eval/tensor_function/tensor_function_test.cpp @@ -336,4 +336,26 @@ TEST("require that push_children works") { //------------------------------------------------------------------------- } +TEST("require that tensor function can be dumped for debugging") { + Stash stash; + auto my_value_1 = stash.create(5.0); + auto my_value_2 = stash.create(1.0); + //------------------------------------------------------------------------- + const auto &x5 = inject(ValueType::from_spec("tensor(x[5])"), 0, stash); + const auto &mapped_x5 = map(x5, operation::Relu::f, stash); + const auto &const_1 = const_value(my_value_1, stash); + const auto &joined_x5 = join(mapped_x5, const_1, operation::Mul::f, stash); + //------------------------------------------------------------------------- + const auto &x2 = inject(ValueType::from_spec("tensor(x[2])"), 1, stash); + const auto &a3y10 = inject(ValueType::from_spec("tensor(a[3],y[10])"), 2, stash); + const auto &a3 = reduce(a3y10, Aggr::SUM, {"y"}, stash); + const auto &x3 = rename(a3, {"a"}, {"x"}, stash); + const auto &concat_x5 = concat(x3, x2, "x", stash); + //------------------------------------------------------------------------- + const auto &const_2 = const_value(my_value_2, stash); + const auto &root = if_node(const_2, joined_x5, concat_x5, stash); + EXPECT_EQUAL(root.result_type(), ValueType::from_spec("tensor(x[5])")); + fprintf(stderr, "function dump -->[[%s]]<-- function dump\n", root.as_string().c_str()); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp b/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp index c794b81f573..3a5b27965d0 100644 --- a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp +++ b/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp @@ -144,4 +144,12 @@ TEST("require that mapped tensors are not optimized") { TEST_DO(verify_not_optimized("mut_x_sparse+mut_x_sparse")); } +TEST("require that inplace join can be debug dumped") { + EvalFixture fixture(prod_engine, "con_x5_A-mut_x5_B", param_repo, true, true); + auto info = fixture.find_all(); + ASSERT_EQUAL(info.size(), 1u); + EXPECT_TRUE(info[0]->result_is_mutable()); + fprintf(stderr, "%s\n", info[0]->as_string().c_str()); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp index 536dd95de9c..f18e72b0d07 100644 --- a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp +++ b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp @@ -124,4 +124,12 @@ TEST("require that xw products with incompatible dimensions are not optimized") TEST_DO(verify_not_optimized("reduce(y3*x2z3,sum,z)")); } +TEST("require that xw product can be debug dumped") { + EvalFixture fixture(prod_engine, "reduce(y5*x8y5,sum,y)", param_repo, true); + auto info = fixture.find_all(); + ASSERT_EQUAL(info.size(), 1u); + EXPECT_TRUE(info[0]->result_is_mutable()); + fprintf(stderr, "%s\n", info[0]->as_string().c_str()); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/vespa/eval/eval/CMakeLists.txt b/eval/src/vespa/eval/eval/CMakeLists.txt index 6ff4b5447ce..760725ae375 100644 --- a/eval/src/vespa/eval/eval/CMakeLists.txt +++ b/eval/src/vespa/eval/eval/CMakeLists.txt @@ -27,5 +27,6 @@ vespa_add_library(eval_eval OBJECT value.cpp value_type.cpp value_type_spec.cpp + visit_stuff.cpp vm_forest.cpp ) diff --git a/eval/src/vespa/eval/eval/tensor_function.cpp b/eval/src/vespa/eval/eval/tensor_function.cpp index 53a9c851ed4..fab0c21b970 100644 --- a/eval/src/vespa/eval/eval/tensor_function.cpp +++ b/eval/src/vespa/eval/eval/tensor_function.cpp @@ -6,9 +6,46 @@ #include "tensor.h" #include "tensor_engine.h" #include "simple_tensor_engine.h" +#include "visit_stuff.h" +#include +#include +#include namespace vespalib { namespace eval { + +vespalib::string +TensorFunction::as_string() const +{ + ObjectDumper dumper; + ::visit(dumper, "", *this); + return dumper.toString(); +} + +vespalib::string +TensorFunction::class_name() const +{ + return vespalib::getClassName(*this); +} + +void +TensorFunction::visit_self(vespalib::ObjectVisitor &visitor) const +{ + visitor.visitString("result_type", result_type().to_spec()); + visitor.visitBool("result_is_mutable", result_is_mutable()); +} + +void +TensorFunction::visit_children(vespalib::ObjectVisitor &visitor) const +{ + std::vector children; + push_children(children); + for (size_t i = 0; i < children.size(); ++i) { + vespalib::string name = vespalib::make_string("children[%zu]", i); + ::visit(visitor, name, children[i].get().get()); + } +} + namespace tensor_function { namespace { @@ -94,12 +131,22 @@ Leaf::push_children(std::vector &) const { } +//----------------------------------------------------------------------------- + void Op1::push_children(std::vector &children) const { children.emplace_back(_child); } +void +Op1::visit_children(vespalib::ObjectVisitor &visitor) const +{ + ::visit(visitor, "child", _child.get()); +} + +//----------------------------------------------------------------------------- + void Op2::push_children(std::vector &children) const { @@ -107,6 +154,13 @@ Op2::push_children(std::vector &children) const children.emplace_back(_rhs); } +void +Op2::visit_children(vespalib::ObjectVisitor &visitor) const +{ + ::visit(visitor, "lhs", _lhs.get()); + ::visit(visitor, "rhs", _rhs.get()); +} + //----------------------------------------------------------------------------- Instruction @@ -121,6 +175,16 @@ ConstValue::dump_tree(DumpTarget &target) const target.node("ConstValue"); } +void +ConstValue::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Leaf::visit_self(visitor); + if (result_type().is_double()) { + visitor.visitFloat("value", _value.as_double()); + } else { + visitor.visitString("value", "..."); + } +} //----------------------------------------------------------------------------- @@ -136,6 +200,12 @@ Inject::dump_tree(DumpTarget &target) const target.node("Inject"); } +void +Inject::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Leaf::visit_self(visitor); + visitor.visitInt("param_idx", _param_idx); +} //----------------------------------------------------------------------------- @@ -155,6 +225,14 @@ Reduce::dump_tree(DumpTarget &target) const target.child("child", child()); } +void +Reduce::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op1::visit_self(visitor); + ::visit(visitor, "aggr", _aggr); + ::visit(visitor, "dimensions", visit::DimList(_dimensions)); +} + //----------------------------------------------------------------------------- Instruction @@ -174,6 +252,13 @@ Map::dump_tree(DumpTarget &target) const target.child("child", child()); } +void +Map::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op1::visit_self(visitor); + ::visit(visitor, "function", _function); +} + //----------------------------------------------------------------------------- Instruction @@ -200,6 +285,12 @@ Join::dump_tree(DumpTarget &target) const target.child("rhs", rhs()); } +void +Join::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op2::visit_self(visitor); + ::visit(visitor, "function", _function); +} //----------------------------------------------------------------------------- @@ -218,6 +309,13 @@ Concat::dump_tree(DumpTarget &target) const target.child("rhs", rhs()); } +void +Concat::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op2::visit_self(visitor); + visitor.visitString("dimension", _dimension); +} + //----------------------------------------------------------------------------- Instruction @@ -227,7 +325,6 @@ Rename::compile_self(Stash &stash) const return Instruction(op_tensor_rename, wrap_param(params)); } - void Rename::dump_tree(DumpTarget &target) const { @@ -237,6 +334,13 @@ Rename::dump_tree(DumpTarget &target) const target.child("child", child()); } +void +Rename::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op1::visit_self(visitor); + ::visit(visitor, "from_to", visit::FromTo(_from, _to)); +} + //----------------------------------------------------------------------------- void @@ -264,6 +368,14 @@ If::dump_tree(DumpTarget &target) const target.child("f_child", _false_child.get()); } +void +If::visit_children(vespalib::ObjectVisitor &visitor) const +{ + ::visit(visitor, "cond", _cond.get()); + ::visit(visitor, "true_child", _true_child.get()); + ::visit(visitor, "false_child", _false_child.get()); +} + //----------------------------------------------------------------------------- const Node &const_value(const Value &value, Stash &stash) { diff --git a/eval/src/vespa/eval/eval/tensor_function.h b/eval/src/vespa/eval/eval/tensor_function.h index 2fa8b3c15c2..0640ba87a7e 100644 --- a/eval/src/vespa/eval/eval/tensor_function.h +++ b/eval/src/vespa/eval/eval/tensor_function.h @@ -19,6 +19,7 @@ namespace vespalib { class Stash; +class ObjectVisitor; namespace eval { @@ -99,6 +100,12 @@ struct TensorFunction **/ virtual void dump_tree(DumpTarget &target) const = 0; + // for debug dumping + vespalib::string as_string() const; + virtual vespalib::string class_name() const; + virtual void visit_self(vespalib::ObjectVisitor &visitor) const; + virtual void visit_children(vespalib::ObjectVisitor &visitor) const; + virtual ~TensorFunction() {} }; @@ -144,6 +151,7 @@ public: : Node(result_type_in), _child(child_in) {} const TensorFunction &child() const { return _child.get(); } void push_children(std::vector &children) const final override; + void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; class Op2 : public Node @@ -159,6 +167,7 @@ public: const TensorFunction &lhs() const { return _lhs.get(); } const TensorFunction &rhs() const { return _rhs.get(); } void push_children(std::vector &children) const final override; + void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; //----------------------------------------------------------------------------- @@ -172,6 +181,7 @@ public: bool result_is_mutable() const override { return false; } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -187,6 +197,7 @@ public: bool result_is_mutable() const override { return false; } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -207,6 +218,7 @@ public: bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -224,6 +236,7 @@ public: bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(Stash &stash) const override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -242,6 +255,7 @@ public: bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(Stash &stash) const override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -260,6 +274,7 @@ public: bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -280,6 +295,7 @@ public: bool result_is_mutable() const override { return true; } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; }; //----------------------------------------------------------------------------- @@ -306,6 +322,7 @@ public: } InterpretedFunction::Instruction compile_self(Stash &stash) const final override; void dump_tree(DumpTarget &target) const override; + void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; //----------------------------------------------------------------------------- diff --git a/eval/src/vespa/eval/eval/tensor_nodes.h b/eval/src/vespa/eval/eval/tensor_nodes.h index bfa572f1d94..2a13f86f017 100644 --- a/eval/src/vespa/eval/eval/tensor_nodes.h +++ b/eval/src/vespa/eval/eval/tensor_nodes.h @@ -112,20 +112,6 @@ private: Node_UP _child; std::vector _from; std::vector _to; - static vespalib::string flatten(const std::vector &list) { - if (list.size() == 1) { - return list[0]; - } - vespalib::string str = "("; - for (size_t i = 0; i < list.size(); ++i) { - if (i > 0) { - str += ","; - } - str += list[i]; - } - str += ")"; - return str; - } public: TensorRename(Node_UP child, std::vector from_in, std::vector to_in) : _child(std::move(child)), _from(std::move(from_in)), _to(std::move(to_in)) {} @@ -151,6 +137,20 @@ public: void detach_children(NodeHandler &handler) override { handler.handle(std::move(_child)); } + static vespalib::string flatten(const std::vector &list) { + if (list.size() == 1) { + return list[0]; + } + vespalib::string str = "("; + for (size_t i = 0; i < list.size(); ++i) { + if (i > 0) { + str += ","; + } + str += list[i]; + } + str += ")"; + return str; + } }; class TensorLambda : public Leaf { diff --git a/eval/src/vespa/eval/eval/visit_stuff.cpp b/eval/src/vespa/eval/eval/visit_stuff.cpp new file mode 100644 index 00000000000..bc2be32bb5f --- /dev/null +++ b/eval/src/vespa/eval/eval/visit_stuff.cpp @@ -0,0 +1,100 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "visit_stuff.h" +#include "tensor_function.h" +#include "aggr.h" +#include "operation.h" +#include "tensor_nodes.h" +#include +#include + +namespace vespalib::eval::visit { +namespace { + +vespalib::string name_of(map_fun_t fun) { + if (fun == operation::Neg::f) return "-"; + if (fun == operation::Not::f) return "!"; + if (fun == operation::Cos::f) return "cos"; + if (fun == operation::Sin::f) return "sin"; + if (fun == operation::Tan::f) return "tan"; + if (fun == operation::Cosh::f) return "cosh"; + if (fun == operation::Sinh::f) return "sinh"; + if (fun == operation::Tanh::f) return "tanh"; + if (fun == operation::Acos::f) return "acos"; + if (fun == operation::Asin::f) return "asin"; + if (fun == operation::Atan::f) return "atan"; + if (fun == operation::Exp::f) return "exp"; + if (fun == operation::Log10::f) return "log10"; + if (fun == operation::Log::f) return "log"; + if (fun == operation::Sqrt::f) return "sqrt"; + if (fun == operation::Ceil::f) return "ceil"; + if (fun == operation::Fabs::f) return "fabs"; + if (fun == operation::Floor::f) return "floor"; + if (fun == operation::IsNan::f) return "isnan"; + if (fun == operation::Relu::f) return "relu"; + if (fun == operation::Sigmoid::f) return "sigmoid"; + if (fun == operation::Elu::f) return "elu"; + return "[other map function]"; +} + +vespalib::string name_of(join_fun_t fun) { + if (fun == operation::Add::f) return "+"; + if (fun == operation::Sub::f) return "-"; + if (fun == operation::Mul::f) return "*"; + if (fun == operation::Div::f) return "/"; + if (fun == operation::Mod::f) return "%"; + if (fun == operation::Pow::f) return "^"; + if (fun == operation::Equal::f) return "=="; + if (fun == operation::NotEqual::f) return "!="; + if (fun == operation::Approx::f) return "~"; + if (fun == operation::Less::f) return "<"; + if (fun == operation::LessEqual::f) return "<="; + if (fun == operation::Greater::f) return ">"; + if (fun == operation::GreaterEqual::f) return ">="; + if (fun == operation::And::f) return "&&"; + if (fun == operation::Or::f) return "||"; + if (fun == operation::Atan2::f) return "atan2"; + if (fun == operation::Ldexp::f) return "ldexp"; + if (fun == operation::Min::f) return "min"; + if (fun == operation::Max::f) return "max"; + return "[other join function]"; +} + +} // namespace vespalib::eval::visit:: +} // namespace vespalib::eval::visit + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::TensorFunction &value) { + visitor.openStruct(name, value.class_name()); + { + value.visit_self(visitor); + value.visit_children(visitor); + } + visitor.closeStruct(); +} + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, vespalib::eval::visit::map_fun_t value) { + visitor.visitString(name, vespalib::eval::visit::name_of(value)); +} + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, vespalib::eval::visit::join_fun_t value) { + visitor.visitString(name, vespalib::eval::visit::name_of(value)); +} + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::Aggr &value) { + if (const vespalib::string *str_ptr = vespalib::eval::AggrNames::name_of(value)) { + visitor.visitString(name, *str_ptr); + } else { + visitor.visitNull(name); + } +} + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::visit::DimList &value) { + vespalib::string list = vespalib::eval::nodes::TensorRename::flatten(value.list); + visitor.visitString(name, list); +} + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::visit::FromTo &value) { + vespalib::string from = vespalib::eval::nodes::TensorRename::flatten(value.from); + vespalib::string to = vespalib::eval::nodes::TensorRename::flatten(value.to); + visitor.visitString(name, vespalib::make_string("%s -> %s", from.c_str(), to.c_str())); +} diff --git a/eval/src/vespa/eval/eval/visit_stuff.h b/eval/src/vespa/eval/eval/visit_stuff.h new file mode 100644 index 00000000000..cbbca9be056 --- /dev/null +++ b/eval/src/vespa/eval/eval/visit_stuff.h @@ -0,0 +1,37 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include +#include + +namespace vespalib { +class ObjectVisitor; +namespace eval { +enum class Aggr; +class TensorFunction; +namespace visit { +using map_fun_t = double (*)(double); +using join_fun_t = double (*)(double, double); +struct DimList { + const std::vector &list; + DimList(const std::vector &list_in) + : list(list_in) {} +}; +struct FromTo { + const std::vector &from; + const std::vector &to; + FromTo(const std::vector &from_in, + const std::vector &to_in) + : from(from_in), to(to_in) {} +}; +} // namespace vespalib::eval::visit +} // namespace vespalib::eval +} // namespace vespalib + +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::TensorFunction &value); +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, vespalib::eval::visit::map_fun_t value); +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, vespalib::eval::visit::join_fun_t value); +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::Aggr &value); +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::visit::DimList &value); +void visit(vespalib::ObjectVisitor &visitor, const vespalib::string &name, const vespalib::eval::visit::FromTo &value); diff --git a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp index 73648cc8dbd..82f30b4cb34 100644 --- a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp +++ b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp @@ -15,7 +15,6 @@ #include "dense/vector_from_doubles_function.h" #include #include -#include #include #include #include @@ -217,17 +216,13 @@ DefaultTensorEngine::decode(nbostream &input) const const TensorFunction & DefaultTensorEngine::optimize(const TensorFunction &expr, Stash &stash) const { - if (LOG_WOULD_LOG(debug)) { - vespalib::string dump = eval::DumpTarget::dump(expr); - LOG(debug, "Optimizing tensor function:\n%s\n", - dump.c_str()); - } using Child = TensorFunction::Child; Child root(expr); std::vector nodes({root}); for (size_t i = 0; i < nodes.size(); ++i) { nodes[i].get().get().push_children(nodes); } + LOG(debug, "tensor function before optimization:\n%s\n", root.get().as_string().c_str()); while (!nodes.empty()) { const Child &child = nodes.back(); child.set(VectorFromDoublesFunction::optimize(child.get(), stash)); @@ -238,11 +233,7 @@ DefaultTensorEngine::optimize(const TensorFunction &expr, Stash &stash) const child.set(DenseInplaceJoinFunction::optimize(child.get(), stash)); nodes.pop_back(); } - if (LOG_WOULD_LOG(debug)) { - vespalib::string dump = eval::DumpTarget::dump(root.get()); - LOG(debug, "Optimized tensor function:\n%s\n", - dump.c_str()); - } + LOG(debug, "tensor function after optimization:\n%s\n", root.get().as_string().c_str()); return root.get(); } diff --git a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp index be4befcc5bf..b02685f4765 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp @@ -3,6 +3,7 @@ #include "dense_inplace_join_function.h" #include "dense_tensor.h" #include "dense_tensor_view.h" +#include #include #include @@ -74,6 +75,13 @@ DenseInplaceJoinFunction::dump_tree(eval::DumpTarget &target) const Join::dump_tree(target); } +void +DenseInplaceJoinFunction::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Join::visit_self(visitor); + visitor.visitBool("write_left", _write_left); +} + const TensorFunction & DenseInplaceJoinFunction::optimize(const eval::TensorFunction &expr, Stash &stash) { diff --git a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.h b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.h index ceae1a258bc..382b9a1561f 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.h @@ -26,6 +26,7 @@ public: bool result_is_mutable() const override { return true; } eval::InterpretedFunction::Instruction compile_self(Stash &stash) const override; void dump_tree(eval::DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.h b/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.h index 1634fc23e50..958261899b4 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.h @@ -13,9 +13,6 @@ class DenseInplaceMapFunction : public eval::tensor_function::Map { public: using map_fun_t = ::vespalib::eval::tensor_function::map_fun_t; -private: - map_fun_t _function; -public: DenseInplaceMapFunction(const eval::ValueType &result_type, const eval::TensorFunction &child, map_fun_t function_in); diff --git a/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp index 4788dae5dc4..77685b7a748 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp @@ -3,6 +3,7 @@ #include "dense_xw_product_function.h" #include "dense_tensor.h" #include "dense_tensor_view.h" +#include #include #include #include @@ -144,6 +145,14 @@ DenseXWProductFunction::dump_tree(eval::DumpTarget &target) const target.child("rhs", rhs()); } +void +DenseXWProductFunction::visit_self(vespalib::ObjectVisitor &visitor) const +{ + Op2::visit_self(visitor); + visitor.visitInt("vector_size", _vectorSize); + visitor.visitInt("result_size", _resultSize); + visitor.visitBool("common_dimension_innermost", _commonDimensionInnermost); +} const TensorFunction & DenseXWProductFunction::optimize(const eval::TensorFunction &expr, Stash &stash) diff --git a/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.h b/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.h index ae74863200f..652652df3fb 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_xw_product_function.h @@ -52,6 +52,7 @@ public: eval::InterpretedFunction::Instruction compile_self(Stash &stash) const override; void dump_tree(eval::DumpTarget &target) const override; + void visit_self(vespalib::ObjectVisitor &visitor) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; -- cgit v1.2.3