summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2018-03-13 14:29:06 +0000
committerHåvard Pettersen <havardpe@oath.com>2018-03-13 14:37:42 +0000
commitb594edf34af42499f55a83d63ab87d0f58fa1f0a (patch)
treefd2f7da548785fb7b18d9ab0292366a21ded942d /eval
parent838e41a332f7d227cc22ccaa4b23f9276dea274e (diff)
use ObjectVisitor to debug dump TensorFunction trees
Diffstat (limited to 'eval')
-rw-r--r--eval/CMakeLists.txt1
-rw-r--r--eval/src/tests/eval/tensor_function/tensor_function_test.cpp22
-rw-r--r--eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp8
-rw-r--r--eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp8
-rw-r--r--eval/src/vespa/eval/eval/CMakeLists.txt1
-rw-r--r--eval/src/vespa/eval/eval/tensor_function.cpp114
-rw-r--r--eval/src/vespa/eval/eval/tensor_function.h17
-rw-r--r--eval/src/vespa/eval/eval/tensor_nodes.h28
-rw-r--r--eval/src/vespa/eval/eval/visit_stuff.cpp100
-rw-r--r--eval/src/vespa/eval/eval/visit_stuff.h37
-rw-r--r--eval/src/vespa/eval/tensor/default_tensor_engine.cpp13
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp8
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.h1
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.h3
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp9
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_xw_product_function.h1
16 files changed, 342 insertions, 29 deletions
diff --git a/eval/CMakeLists.txt b/eval/CMakeLists.txt
index a733b73d9d1..80156d51fcc 100644
--- a/eval/CMakeLists.txt
+++ b/eval/CMakeLists.txt
@@ -2,6 +2,7 @@
vespa_define_module(
DEPENDS
vespalib
+ staging_vespalib
APPS
src/apps/eval_expr
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<DoubleValue>(5.0);
+ auto my_value_2 = stash.create<DoubleValue>(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<DenseInplaceJoinFunction>();
+ 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<DenseXWProductFunction>();
+ 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 <vespa/vespalib/objects/visit.hpp>
+#include <vespa/vespalib/objects/objectdumper.h>
+#include <vespa/vespalib/util/classname.h>
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<vespalib::eval::TensorFunction::Child::CREF> 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,6 +131,8 @@ Leaf::push_children(std::vector<Child::CREF> &) const
{
}
+//-----------------------------------------------------------------------------
+
void
Op1::push_children(std::vector<Child::CREF> &children) const
{
@@ -101,12 +140,27 @@ Op1::push_children(std::vector<Child::CREF> &children) const
}
void
+Op1::visit_children(vespalib::ObjectVisitor &visitor) const
+{
+ ::visit(visitor, "child", _child.get());
+}
+
+//-----------------------------------------------------------------------------
+
+void
Op2::push_children(std::vector<Child::CREF> &children) const
{
children.emplace_back(_lhs);
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<RenameParams>(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<Child::CREF> &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<Child::CREF> &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<vespalib::string> _from;
std::vector<vespalib::string> _to;
- static vespalib::string flatten(const std::vector<vespalib::string> &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<vespalib::string> from_in, std::vector<vespalib::string> 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<vespalib::string> &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 <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/objects/objectvisitor.h>
+
+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::<unnamed>
+} // 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 <vespa/vespalib/stllike/string.h>
+#include <vector>
+
+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<vespalib::string> &list;
+ DimList(const std::vector<vespalib::string> &list_in)
+ : list(list_in) {}
+};
+struct FromTo {
+ const std::vector<vespalib::string> &from;
+ const std::vector<vespalib::string> &to;
+ FromTo(const std::vector<vespalib::string> &from_in,
+ const std::vector<vespalib::string> &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 <vespa/eval/eval/value.h>
#include <vespa/eval/eval/tensor_spec.h>
-#include <vespa/eval/eval/dump_target.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/simple_tensor_engine.h>
#include <vespa/eval/eval/operation.h>
@@ -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<Child::CREF> 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 <vespa/vespalib/objects/objectvisitor.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/tensor/tensor.h>
@@ -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 <vespa/vespalib/objects/objectvisitor.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/operation.h>
#include <vespa/eval/tensor/tensor.h>
@@ -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);
};