diff options
author | Håvard Pettersen <havardpe@oath.com> | 2020-10-12 12:29:21 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2020-10-12 19:05:54 +0000 |
commit | e72235763076cad111f53043578b25d88c585255 (patch) | |
tree | 0f41fc53578aa258c29607ad8910fbbcb09ad5f5 /eval | |
parent | 9886120a1bddd1016466cec317a445cd37650bff (diff) |
allow interpreted function to use new generic operations
update conformance test to also test with SimpleValue and FastValue
Diffstat (limited to 'eval')
66 files changed, 405 insertions, 213 deletions
diff --git a/eval/src/apps/tensor_conformance/tensor_conformance.cpp b/eval/src/apps/tensor_conformance/tensor_conformance.cpp index 6099e543922..1f8069db06d 100644 --- a/eval/src/apps/tensor_conformance/tensor_conformance.cpp +++ b/eval/src/apps/tensor_conformance/tensor_conformance.cpp @@ -88,7 +88,7 @@ std::vector<ValueType> get_types(const std::vector<Value::UP> ¶m_values) { return param_types; } -TensorSpec eval_expr(const Inspector &test, const TensorEngine &engine, bool typed) { +TensorSpec eval_expr(const Inspector &test, EngineOrFactory engine, bool typed) { auto fun = Function::parse(test["expression"].asString().make_string()); std::vector<Value::UP> param_values; std::vector<Value::CREF> param_refs; diff --git a/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp b/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp index 60700817266..ee595606c14 100644 --- a/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp +++ b/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp @@ -72,7 +72,7 @@ struct MyEvalTest : test::EvalSpec::EvalTest { } } - void verify_result(const TensorEngine &engine, + void verify_result(EngineOrFactory engine, const Function &function, bool typed, const vespalib::string &description, diff --git a/eval/src/tests/eval/simple_value/simple_value_test.cpp b/eval/src/tests/eval/simple_value/simple_value_test.cpp index e989b567e20..cac1a93dbf9 100644 --- a/eval/src/tests/eval/simple_value/simple_value_test.cpp +++ b/eval/src/tests/eval/simple_value/simple_value_test.cpp @@ -74,7 +74,7 @@ TensorSpec simple_value_new_join(const TensorSpec &a, const TensorSpec &b, join_ auto lhs = value_from_spec(a, factory); auto rhs = value_from_spec(b, factory); auto my_op = GenericJoin::make_instruction(lhs->type(), rhs->type(), function, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs,*rhs}))); } 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 b205205f52e..ca446c6162f 100644 --- a/eval/src/tests/eval/tensor_function/tensor_function_test.cpp +++ b/eval/src/tests/eval/tensor_function/tensor_function_test.cpp @@ -14,13 +14,13 @@ using namespace vespalib::eval; using namespace vespalib::eval::tensor_function; struct EvalCtx { - const TensorEngine &engine; + EngineOrFactory engine; Stash stash; std::vector<Value::UP> tensors; std::vector<Value::CREF> params; InterpretedFunction::UP ifun; std::unique_ptr<InterpretedFunction::Context> ictx; - EvalCtx(const TensorEngine &engine_in) + EvalCtx(EngineOrFactory engine_in) : engine(engine_in), stash(), tensors(), params(), ifun(), ictx() {} ~EvalCtx() {} size_t add_tensor(Value::UP tensor) { 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 dc69bce30f6..b48c1e2253c 100644 --- a/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp +++ b/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp @@ -126,7 +126,7 @@ TensorSpec perform_generic_concat(const TensorSpec &a, const TensorSpec &b, cons auto lhs = value_from_spec(a, factory); auto rhs = value_from_spec(b, factory); auto my_op = GenericConcat::make_instruction(lhs->type(), rhs->type(), concat_dim, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs,*rhs}))); } 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 25715f07bea..82696bbbd5e 100644 --- a/eval/src/tests/instruction/generic_join/generic_join_test.cpp +++ b/eval/src/tests/instruction/generic_join/generic_join_test.cpp @@ -76,7 +76,7 @@ TensorSpec perform_generic_join(const TensorSpec &a, const TensorSpec &b, join_f auto lhs = value_from_spec(a, factory); auto rhs = value_from_spec(b, factory); auto my_op = GenericJoin::make_instruction(lhs->type(), rhs->type(), function, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs,*rhs}))); } @@ -86,7 +86,7 @@ TensorSpec perform_generic_join_fast(const TensorSpec &a, const TensorSpec &b, j auto lhs = value_from_spec(a, factory); auto rhs = value_from_spec(b, factory); auto my_op = GenericJoin::make_instruction(lhs->type(), rhs->type(), function, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs,*rhs}))); } 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 501d5410b87..ae2e100176b 100644 --- a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp +++ b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp @@ -61,7 +61,7 @@ TensorSpec perform_generic_merge(const TensorSpec &a, const TensorSpec &b, join_ auto lhs = value_from_spec(a, factory); auto rhs = value_from_spec(b, factory); auto my_op = GenericMerge::make_instruction(lhs->type(), rhs->type(), fun, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs, *rhs}))); } 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 7e9a059967a..335e4e46642 100644 --- a/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp +++ b/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp @@ -63,7 +63,7 @@ TensorSpec perform_generic_reduce(const TensorSpec &a, const std::vector<vespali const auto &factory = SimpleValueBuilderFactory::get(); auto lhs = value_from_spec(a, factory); auto my_op = GenericReduce::make_instruction(lhs->type(), aggr, dims, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs}))); } 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 d5c7f58fc1f..3f151af1fd6 100644 --- a/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp +++ b/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp @@ -117,7 +117,7 @@ TensorSpec perform_generic_rename(const TensorSpec &a, Stash stash; auto lhs = value_from_spec(a, factory); auto my_op = GenericRename::make_instruction(lhs->type(), ft.from, ft.to, factory, stash); - InterpretedFunction::EvalSingle single(my_op); + InterpretedFunction::EvalSingle single(factory, my_op); return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs}))); } diff --git a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp b/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp index 9ebcb0ec77c..84e79ff85e8 100644 --- a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp +++ b/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp @@ -23,7 +23,7 @@ struct ChildMock : Leaf { bool is_mutable; ChildMock(const ValueType &type) : Leaf(type), is_mutable(true) {} bool result_is_mutable() const override { return is_mutable; } - InterpretedFunction::Instruction compile_self(const TensorEngine &, Stash &) const override { abort(); } + InterpretedFunction::Instruction compile_self(EngineOrFactory, Stash &) const override { abort(); } }; struct Fixture { diff --git a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp index 953415f9f71..e340b5d75b3 100644 --- a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp +++ b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp @@ -60,93 +60,55 @@ struct Impl { size_t order; vespalib::string name; vespalib::string short_name; - Impl(size_t order_in, const vespalib::string &name_in, const vespalib::string &short_name_in) - : order(order_in), name(name_in), short_name(short_name_in) {} - virtual Value::UP create_value(const TensorSpec &spec) const = 0; - virtual TensorSpec create_spec(const Value &value) const = 0; - virtual Instruction create_join(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const = 0; - virtual Instruction create_reduce(const ValueType &lhs, Aggr aggr, const std::vector<vespalib::string> &dims, Stash &stash) const = 0; - virtual Instruction create_rename(const ValueType &lhs, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const = 0; - virtual Instruction create_merge(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const = 0; - virtual Instruction create_concat(const ValueType &lhs, const ValueType &rhs, const std::string &dimension, Stash &stash) const = 0; - virtual const TensorEngine &engine() const { return SimpleTensorEngine::ref(); } // engine used by EvalSingle - virtual ~Impl() {} -}; - -struct ValueImpl : Impl { - const ValueBuilderFactory &my_factory; - ValueImpl(size_t order_in, const vespalib::string &name_in, const vespalib::string &short_name_in, const ValueBuilderFactory &factory) - : Impl(order_in, name_in, short_name_in), my_factory(factory) {} - Value::UP create_value(const TensorSpec &spec) const override { return value_from_spec(spec, my_factory); } - TensorSpec create_spec(const Value &value) const override { return spec_from_value(value); } - Instruction create_join(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const override { - return GenericJoin::make_instruction(lhs, rhs, function, my_factory, stash); - } - Instruction create_reduce(const ValueType &lhs, Aggr aggr, const std::vector<vespalib::string> &dims, Stash &stash) const override { - return GenericReduce::make_instruction(lhs, aggr, dims, my_factory, stash); - } - Instruction create_rename(const ValueType &lhs, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const override { - return GenericRename::make_instruction(lhs, from, to, my_factory, stash); - } - Instruction create_merge(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const override { - return GenericMerge::make_instruction(lhs, rhs, function, my_factory, stash); - } - Instruction create_concat(const ValueType &lhs, const ValueType &rhs, const std::string &dimension, Stash &stash) const override { - return GenericConcat::make_instruction(lhs, rhs, dimension, my_factory, stash); - } -}; - -struct EngineImpl : Impl { - const TensorEngine &my_engine; - EngineImpl(size_t order_in, const vespalib::string &name_in, const vespalib::string &short_name_in, const TensorEngine &engine_in) - : Impl(order_in, name_in, short_name_in), my_engine(engine_in) {} - Value::UP create_value(const TensorSpec &spec) const override { return my_engine.from_spec(spec); } - TensorSpec create_spec(const Value &value) const override { return my_engine.to_spec(value); } - Instruction create_join(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const override { + EngineOrFactory engine; + Impl(size_t order_in, const vespalib::string &name_in, const vespalib::string &short_name_in, EngineOrFactory engine_in) + : order(order_in), name(name_in), short_name(short_name_in), engine(engine_in) {} + Value::UP create_value(const TensorSpec &spec) const { return engine.from_spec(spec); } + TensorSpec create_spec(const Value &value) const { return engine.to_spec(value); } + Instruction create_join(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const { // create a complete tensor function, but only compile the relevant instruction const auto &lhs_node = tensor_function::inject(lhs, 0, stash); const auto &rhs_node = tensor_function::inject(rhs, 1, stash); const auto &join_node = tensor_function::join(lhs_node, rhs_node, function, stash); - return join_node.compile_self(my_engine, stash); + return join_node.compile_self(engine, stash); } - Instruction create_reduce(const ValueType &lhs, Aggr aggr, const std::vector<vespalib::string> &dims, Stash &stash) const override { + Instruction create_reduce(const ValueType &lhs, Aggr aggr, const std::vector<vespalib::string> &dims, Stash &stash) const { // create a complete tensor function, but only compile the relevant instruction const auto &lhs_node = tensor_function::inject(lhs, 0, stash); const auto &reduce_node = tensor_function::reduce(lhs_node, aggr, dims, stash); - return reduce_node.compile_self(my_engine, stash); + return reduce_node.compile_self(engine, stash); } - Instruction create_rename(const ValueType &lhs, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const override { + Instruction create_rename(const ValueType &lhs, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const { // create a complete tensor function, but only compile the relevant instruction const auto &lhs_node = tensor_function::inject(lhs, 0, stash); const auto &rename_node = tensor_function::rename(lhs_node, from, to, stash); - return rename_node.compile_self(my_engine, stash); + return rename_node.compile_self(engine, stash); } - Instruction create_merge(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const override { + Instruction create_merge(const ValueType &lhs, const ValueType &rhs, operation::op2_t function, Stash &stash) const { // create a complete tensor function, but only compile the relevant instruction const auto &lhs_node = tensor_function::inject(lhs, 0, stash); const auto &rhs_node = tensor_function::inject(rhs, 1, stash); const auto &merge_node = tensor_function::merge(lhs_node, rhs_node, function, stash); - return merge_node.compile_self(my_engine, stash); + return merge_node.compile_self(engine, stash); } - Instruction create_concat(const ValueType &lhs, const ValueType &rhs, const std::string &dimension, Stash &stash) const override { + Instruction create_concat(const ValueType &lhs, const ValueType &rhs, const std::string &dimension, Stash &stash) const { // create a complete tensor function, but only compile the relevant instruction const auto &lhs_node = tensor_function::inject(lhs, 0, stash); const auto &rhs_node = tensor_function::inject(rhs, 1, stash); const auto &concat_node = tensor_function::concat(lhs_node, rhs_node, dimension, stash); - return concat_node.compile_self(my_engine, stash); + return concat_node.compile_self(engine, stash); } - const TensorEngine &engine() const override { return my_engine; } }; //----------------------------------------------------------------------------- -EngineImpl simple_tensor_engine_impl(5, " SimpleTensorEngine", " SimpleT", SimpleTensorEngine::ref()); -EngineImpl default_tensor_engine_impl(1, "DefaultTensorEngine", "OLD PROD", DefaultTensorEngine::ref()); -ValueImpl simple_value_impl(2, " SimpleValue", " SimpleV", SimpleValueBuilderFactory::get()); -ValueImpl fast_value_impl(0, " FastValue", "NEW PROD", FastValueBuilderFactory::get()); -ValueImpl packed_mixed_tensor_impl(4, " PackedMixedTensor", " Packed", PackedMixedTensorBuilderFactory::get()); -ValueImpl default_tensor_value_impl(3, " DefaultValue", "DefaultV", DefaultValueBuilderFactory::get()); -vespalib::string short_header("--------"); +Impl simple_tensor_engine_impl(5, " SimpleTensorEngine", " SimpleT", SimpleTensorEngine::ref()); +Impl default_tensor_engine_impl(1, "DefaultTensorEngine", "OLD PROD", DefaultTensorEngine::ref()); +Impl simple_value_impl(2, " SimpleValue", " SimpleV", SimpleValueBuilderFactory::get()); +Impl fast_value_impl(0, " FastValue", "NEW PROD", FastValueBuilderFactory::get()); +Impl packed_mixed_tensor_impl(4, " PackedMixedTensor", " Packed", PackedMixedTensorBuilderFactory::get()); +Impl default_tensor_value_impl(3, " DefaultValue", "DefaultV", DefaultValueBuilderFactory::get()); +vespalib::string short_header("--------"); constexpr double budget = 5.0; constexpr double best_limit = 0.95; // everything within 95% of best performance gets a star @@ -236,7 +198,7 @@ struct EvalOp { EvalOp(const EvalOp &) = delete; EvalOp &operator=(const EvalOp &) = delete; EvalOp(Instruction op, const std::vector<CREF<TensorSpec>> &stack_spec, const Impl &impl_in) - : impl(impl_in), values(), stack(), single(impl.engine(), op) + : impl(impl_in), values(), stack(), single(impl.engine, op) { for (const TensorSpec &spec: stack_spec) { values.push_back(impl.create_value(spec)); diff --git a/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp b/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp index df415e39134..a9681cd85c9 100644 --- a/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp +++ b/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp @@ -2,9 +2,13 @@ #include <vespa/vespalib/testkit/test_kit.h> #include <vespa/eval/eval/test/tensor_conformance.h> #include <vespa/eval/eval/simple_tensor_engine.h> +#include <vespa/eval/eval/simple_value.h> +#include <vespa/eval/eval/fast_value.h> #include <vespa/eval/tensor/default_tensor_engine.h> #include <vespa/vespalib/util/stringfmt.h> +using vespalib::eval::SimpleValueBuilderFactory; +using vespalib::eval::FastValueBuilderFactory; using vespalib::eval::SimpleTensorEngine; using vespalib::eval::test::TensorConformance; using vespalib::tensor::DefaultTensorEngine; @@ -21,6 +25,14 @@ TEST("require that production tensor implementation passes all conformance tests TEST_DO(TensorConformance::run_tests(module_src_path, DefaultTensorEngine::ref())); } +TEST("require that SimpleValue implementation passes all conformance tests (except ImmediateAPI tests)") { + TEST_DO(TensorConformance::run_tests(module_src_path, SimpleValueBuilderFactory::get())); +} + +TEST("require that FastValue implementation passes all conformance tests (except ImmediateAPI tests)") { + TEST_DO(TensorConformance::run_tests(module_src_path, FastValueBuilderFactory::get())); +} + TEST("require that tensor serialization test spec can be generated") { vespalib::string spec = module_src_path + "src/apps/make_tensor_binary_format_test_spec/test_spec.json"; vespalib::string binary = module_build_path + "src/apps/make_tensor_binary_format_test_spec/eval_make_tensor_binary_format_test_spec_app"; diff --git a/eval/src/vespa/eval/eval/CMakeLists.txt b/eval/src/vespa/eval/eval/CMakeLists.txt index 244966fc992..5a60adfb58b 100644 --- a/eval/src/vespa/eval/eval/CMakeLists.txt +++ b/eval/src/vespa/eval/eval/CMakeLists.txt @@ -7,6 +7,7 @@ vespa_add_library(eval_eval OBJECT compile_tensor_function.cpp delete_node.cpp double_value_builder.cpp + engine_or_factory.cpp fast_forest.cpp fast_sparse_map.cpp fast_value.cpp diff --git a/eval/src/vespa/eval/eval/compile_tensor_function.cpp b/eval/src/vespa/eval/eval/compile_tensor_function.cpp index 18ef59507d8..6fd754b9cc8 100644 --- a/eval/src/vespa/eval/eval/compile_tensor_function.cpp +++ b/eval/src/vespa/eval/eval/compile_tensor_function.cpp @@ -32,11 +32,11 @@ struct Frame { }; struct ProgramCompiler { - const TensorEngine &engine; + EngineOrFactory engine; Stash &stash; std::vector<Frame> stack; std::vector<Instruction> prog; - ProgramCompiler(const TensorEngine &engine_in, Stash &stash_in) : engine(engine_in), stash(stash_in), stack(), prog() {} + ProgramCompiler(EngineOrFactory engine_in, Stash &stash_in) : engine(engine_in), stash(stash_in), stack(), prog() {} void append(const std::vector<Instruction> &other_prog) { prog.insert(prog.end(), other_prog.begin(), other_prog.end()); @@ -76,7 +76,7 @@ struct ProgramCompiler { } // namespace vespalib::eval::<unnamed> -std::vector<Instruction> compile_tensor_function(const TensorEngine &engine, const TensorFunction &function, Stash &stash) { +std::vector<Instruction> compile_tensor_function(EngineOrFactory engine, const TensorFunction &function, Stash &stash) { ProgramCompiler compiler(engine, stash); return compiler.compile(function); } diff --git a/eval/src/vespa/eval/eval/compile_tensor_function.h b/eval/src/vespa/eval/eval/compile_tensor_function.h index 63f00fde053..b12705e8bb5 100644 --- a/eval/src/vespa/eval/eval/compile_tensor_function.h +++ b/eval/src/vespa/eval/eval/compile_tensor_function.h @@ -2,6 +2,7 @@ #pragma once +#include "engine_or_factory.h" #include "interpreted_function.h" #include <vector> @@ -10,8 +11,7 @@ namespace vespalib { class Stash; } namespace vespalib::eval { struct TensorFunction; -struct TensorEngine; -std::vector<InterpretedFunction::Instruction> compile_tensor_function(const TensorEngine &engine, const TensorFunction &function, Stash &stash); +std::vector<InterpretedFunction::Instruction> compile_tensor_function(EngineOrFactory engine, const TensorFunction &function, Stash &stash); } // namespace vespalib::eval diff --git a/eval/src/vespa/eval/eval/engine_or_factory.cpp b/eval/src/vespa/eval/eval/engine_or_factory.cpp new file mode 100644 index 00000000000..d297cc91f6f --- /dev/null +++ b/eval/src/vespa/eval/eval/engine_or_factory.cpp @@ -0,0 +1,91 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "engine_or_factory.h" +#include "fast_value.h" +#include <vespa/eval/tensor/default_tensor_engine.h> +#include "value_codec.h" + +namespace vespalib::eval { + +const TensorFunction & +EngineOrFactory::optimize(const TensorFunction &expr, Stash &stash) const { + if (is_engine()) { + return engine().optimize(expr, stash); + } else if (&factory() == &FastValueBuilderFactory::get()) { + return tensor::DefaultTensorEngine::ref().optimize(expr, stash); + } else { + return expr; + } +} + +TensorSpec +EngineOrFactory::to_spec(const Value &value) const +{ + if (is_engine()) { + return engine().to_spec(value); + } else { + return factory(), spec_from_value(value); + } +} + +std::unique_ptr<Value> +EngineOrFactory::from_spec(const TensorSpec &spec) const +{ + if (is_engine()) { + return engine().from_spec(spec); + } else { + return value_from_spec(spec, factory()); + } +} + +void +EngineOrFactory::encode(const Value &value, nbostream &output) const +{ + if (is_engine()) { + return engine().encode(value, output); + } else { + return factory(), encode_value(value, output); + } +} + +std::unique_ptr<Value> +EngineOrFactory::decode(nbostream &input) const +{ + if (is_engine()) { + return engine().decode(input); + } else { + return decode_value(input, factory()); + } +} + +const Value & +EngineOrFactory::map(const Value &a, operation::op1_t function, Stash &stash) const { + return engine().map(a, function, stash); +} + +const Value & +EngineOrFactory::join(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { + return engine().join(a, b, function, stash); +} + +const Value & +EngineOrFactory::merge(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { + return engine().merge(a, b, function, stash); +} + +const Value & +EngineOrFactory::reduce(const Value &a, Aggr aggr, const std::vector<vespalib::string> &dimensions, Stash &stash) const { + return engine().reduce(a, aggr, dimensions, stash); +} + +const Value & +EngineOrFactory::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const { + return engine().concat(a, b, dimension, stash); +} + +const Value & +EngineOrFactory::rename(const Value &a, const std::vector<vespalib::string> &from, const std::vector<vespalib::string> &to, Stash &stash) const { + return engine().rename(a, from, to, stash); +} + +} diff --git a/eval/src/vespa/eval/eval/engine_or_factory.h b/eval/src/vespa/eval/eval/engine_or_factory.h new file mode 100644 index 00000000000..a95bfda6bd5 --- /dev/null +++ b/eval/src/vespa/eval/eval/engine_or_factory.h @@ -0,0 +1,57 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "aggr.h" +#include "tensor_spec.h" +#include "operation.h" +#include <variant> + +namespace vespalib { +class Stash; +class nbostream; +} + +namespace vespalib::eval { + +class TensorEngine; +class ValueBuilderFactory; +class TensorFunction; + +/** + * This utility class contains a reference to either a TensorEngine or + * a ValueBuilderFactory. This is needed during a transition period to + * support both evaluation models. We want to get rid of the + * TensorEngine concept since using the Value API directly removes the + * need to constrain operations to only calculate on tensors belonging + * to the same tensor engine. The factory is a hint to the preferred + * Value implementation. + **/ +class EngineOrFactory { +private: + using engine_t = const TensorEngine *; + using factory_t = const ValueBuilderFactory *; + std::variant<engine_t,factory_t> _value; +public: + EngineOrFactory(const TensorEngine &engine_in) : _value(&engine_in) {} + EngineOrFactory(const ValueBuilderFactory &factory_in) : _value(&factory_in) {} + bool is_engine() const { return std::holds_alternative<engine_t>(_value); } + bool is_factory() const { return std::holds_alternative<factory_t>(_value); } + const TensorEngine &engine() const { return *std::get<engine_t>(_value); } + const ValueBuilderFactory &factory() const { return *std::get<factory_t>(_value); } + // functions that can be called with either engine or factory + const TensorFunction &optimize(const TensorFunction &expr, Stash &stash) const; + TensorSpec to_spec(const Value &value) const; + std::unique_ptr<Value> from_spec(const TensorSpec &spec) const; + void encode(const Value &value, nbostream &output) const; + std::unique_ptr<Value> decode(nbostream &input) const; + // 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; +}; + +} diff --git a/eval/src/vespa/eval/eval/fast_value.hpp b/eval/src/vespa/eval/eval/fast_value.hpp index 4efb56ee0c4..e0b401b800c 100644 --- a/eval/src/vespa/eval/eval/fast_value.hpp +++ b/eval/src/vespa/eval/eval/fast_value.hpp @@ -182,6 +182,10 @@ struct FastValue final : Value, ValueBuilder<T> { return ArrayRef<T>(&my_cells[old_size], my_subspace_size); } std::unique_ptr<Value> build(std::unique_ptr<ValueBuilder<T>> self) override { + if (my_index.map.num_dims() == 0) { + assert(my_index.map.size() == 1); + } + assert(my_cells.size() == (my_index.map.size() * my_subspace_size)); ValueBuilder<T>* me = this; assert(me == self.get()); self.release(); diff --git a/eval/src/vespa/eval/eval/interpreted_function.cpp b/eval/src/vespa/eval/eval/interpreted_function.cpp index e9c82789991..3460bc5923b 100644 --- a/eval/src/vespa/eval/eval/interpreted_function.cpp +++ b/eval/src/vespa/eval/eval/interpreted_function.cpp @@ -33,7 +33,7 @@ const Function *get_lambda(const nodes::Node &node) { } // namespace vespalib::<unnamed> -InterpretedFunction::State::State(const TensorEngine &engine_in) +InterpretedFunction::State::State(EngineOrFactory engine_in) : engine(engine_in), params(nullptr), stash(), @@ -59,7 +59,7 @@ InterpretedFunction::Context::Context(const InterpretedFunction &ifun) { } -InterpretedFunction::InterpretedFunction(const TensorEngine &engine, const TensorFunction &function) +InterpretedFunction::InterpretedFunction(EngineOrFactory engine, const TensorFunction &function) : _program(), _stash(), _tensor_engine(engine) @@ -67,7 +67,7 @@ InterpretedFunction::InterpretedFunction(const TensorEngine &engine, const Tenso _program = compile_tensor_function(engine, function, _stash); } -InterpretedFunction::InterpretedFunction(const TensorEngine &engine, const nodes::Node &root, const NodeTypes &types) +InterpretedFunction::InterpretedFunction(EngineOrFactory engine, const nodes::Node &root, const NodeTypes &types) : _program(), _stash(), _tensor_engine(engine) @@ -118,13 +118,7 @@ InterpretedFunction::detect_issues(const Function &function) return Function::Issues(std::move(checker.issues)); } -InterpretedFunction::EvalSingle::EvalSingle(Instruction op) - : _state(SimpleTensorEngine::ref()), - _op(op) -{ -} - -InterpretedFunction::EvalSingle::EvalSingle(const TensorEngine &engine, Instruction op) +InterpretedFunction::EvalSingle::EvalSingle(EngineOrFactory engine, Instruction op) : _state(engine), _op(op) { diff --git a/eval/src/vespa/eval/eval/interpreted_function.h b/eval/src/vespa/eval/eval/interpreted_function.h index e5ec86d8a91..c1b86649606 100644 --- a/eval/src/vespa/eval/eval/interpreted_function.h +++ b/eval/src/vespa/eval/eval/interpreted_function.h @@ -2,6 +2,7 @@ #pragma once +#include "engine_or_factory.h" #include "function.h" #include "node_types.h" #include "lazy_params.h" @@ -10,7 +11,6 @@ namespace vespalib::eval { namespace nodes { struct Node; } -struct TensorEngine; struct TensorFunction; class TensorSpec; @@ -28,14 +28,14 @@ class InterpretedFunction { public: struct State { - const TensorEngine &engine; + EngineOrFactory engine; const LazyParams *params; Stash stash; std::vector<Value::CREF> stack; uint32_t program_offset; uint32_t if_cnt; - State(const TensorEngine &engine_in); + State(EngineOrFactory engine_in); ~State(); void init(const LazyParams ¶ms_in); @@ -87,14 +87,14 @@ public: private: std::vector<Instruction> _program; Stash _stash; - const TensorEngine &_tensor_engine; + EngineOrFactory _tensor_engine; public: typedef std::unique_ptr<InterpretedFunction> UP; // for testing; use with care; the tensor function must be kept alive - InterpretedFunction(const TensorEngine &engine, const TensorFunction &function); - InterpretedFunction(const TensorEngine &engine, const nodes::Node &root, const NodeTypes &types); - InterpretedFunction(const TensorEngine &engine, const Function &function, const NodeTypes &types) + InterpretedFunction(EngineOrFactory engine, const TensorFunction &function); + InterpretedFunction(EngineOrFactory engine, const nodes::Node &root, const NodeTypes &types); + InterpretedFunction(EngineOrFactory engine, const Function &function, const NodeTypes &types) : InterpretedFunction(engine, function.root(), types) {} InterpretedFunction(InterpretedFunction &&rhs) = default; ~InterpretedFunction(); @@ -109,16 +109,14 @@ public: * instructions manipulating the program counter or resolving * parameters may not be run in this way. Also note that the stack * must contain exactly one value after the instruction is - * executed. If no tensor engine is specified, SimpleTensorEngine - * is used (typically for instructions ignoring the engine). + * executed. **/ class EvalSingle { private: State _state; Instruction _op; public: - EvalSingle(Instruction op); - EvalSingle(const TensorEngine &engine, Instruction op); + EvalSingle(EngineOrFactory engine, Instruction op); const Value &eval(const std::vector<Value::CREF> &stack); }; }; diff --git a/eval/src/vespa/eval/eval/make_tensor_function.cpp b/eval/src/vespa/eval/eval/make_tensor_function.cpp index c5b5ca59401..dc76c914c06 100644 --- a/eval/src/vespa/eval/eval/make_tensor_function.cpp +++ b/eval/src/vespa/eval/eval/make_tensor_function.cpp @@ -20,11 +20,11 @@ using namespace nodes; struct TensorFunctionBuilder : public NodeVisitor, public NodeTraverser { Stash &stash; - const TensorEngine &tensor_engine; + EngineOrFactory tensor_engine; const NodeTypes &types; std::vector<TensorFunction::CREF> stack; - TensorFunctionBuilder(Stash &stash_in, const TensorEngine &tensor_engine_in, const NodeTypes &types_in) + TensorFunctionBuilder(Stash &stash_in, EngineOrFactory tensor_engine_in, const NodeTypes &types_in) : stash(stash_in), tensor_engine(tensor_engine_in), types(types_in), stack() {} //------------------------------------------------------------------------- @@ -356,7 +356,7 @@ struct TensorFunctionBuilder : public NodeVisitor, public NodeTraverser { } // namespace vespalib::eval::<unnamed> -const TensorFunction &make_tensor_function(const TensorEngine &engine, const nodes::Node &root, const NodeTypes &types, Stash &stash) { +const TensorFunction &make_tensor_function(EngineOrFactory engine, const nodes::Node &root, const NodeTypes &types, Stash &stash) { TensorFunctionBuilder builder(stash, engine, types); root.traverse(builder); assert(builder.stack.size() == 1); diff --git a/eval/src/vespa/eval/eval/make_tensor_function.h b/eval/src/vespa/eval/eval/make_tensor_function.h index bf6a9a44f4a..7cf9515e243 100644 --- a/eval/src/vespa/eval/eval/make_tensor_function.h +++ b/eval/src/vespa/eval/eval/make_tensor_function.h @@ -2,16 +2,17 @@ #pragma once +#include "engine_or_factory.h" + namespace vespalib { class Stash; } namespace vespalib::eval { -struct TensorEngine; class NodeTypes; struct TensorFunction; namespace nodes { struct Node; } -const TensorFunction &make_tensor_function(const TensorEngine &engine, const nodes::Node &root, const NodeTypes &types, Stash &stash); +const TensorFunction &make_tensor_function(EngineOrFactory engine, const nodes::Node &root, const NodeTypes &types, Stash &stash); } // namespace vespalib::eval diff --git a/eval/src/vespa/eval/eval/simple_value.cpp b/eval/src/vespa/eval/eval/simple_value.cpp index cca4c6c7d51..2c0d08e9e86 100644 --- a/eval/src/vespa/eval/eval/simple_value.cpp +++ b/eval/src/vespa/eval/eval/simple_value.cpp @@ -214,7 +214,6 @@ SimpleValueT<T>::add_subspace(ConstArrayRef<vespalib::stringref> addr) size_t old_size = _cells.size(); add_mapping(addr); _cells.resize(old_size + subspace_size()); - assert(_cells.size() == (size() * subspace_size())); return ArrayRef<T>(&_cells[old_size], subspace_size()); } diff --git a/eval/src/vespa/eval/eval/simple_value.h b/eval/src/vespa/eval/eval/simple_value.h index 81f65eee061..c838161bbde 100644 --- a/eval/src/vespa/eval/eval/simple_value.h +++ b/eval/src/vespa/eval/eval/simple_value.h @@ -28,6 +28,7 @@ private: size_t _subspace_size; std::map<Labels,size_t> _index; protected: + size_t num_mapped_dims() const { return _num_mapped_dims; } size_t subspace_size() const { return _subspace_size; } void add_mapping(ConstArrayRef<vespalib::stringref> addr); public: @@ -53,6 +54,10 @@ public: TypedCells cells() const override { return TypedCells(ConstArrayRef<T>(_cells)); } ArrayRef<T> add_subspace(ConstArrayRef<vespalib::stringref> addr) override; std::unique_ptr<Value> build(std::unique_ptr<ValueBuilder<T>> self) override { + if (num_mapped_dims() == 0) { + assert(size() == 1); + } + assert(_cells.size() == (size() * subspace_size())); ValueBuilder<T>* me = this; assert(me == self.get()); self.release(); diff --git a/eval/src/vespa/eval/eval/tensor_function.cpp b/eval/src/vespa/eval/eval/tensor_function.cpp index ed7e173a400..33bf2ce9c0e 100644 --- a/eval/src/vespa/eval/eval/tensor_function.cpp +++ b/eval/src/vespa/eval/eval/tensor_function.cpp @@ -8,6 +8,11 @@ #include "simple_tensor_engine.h" #include "visit_stuff.h" #include "string_stuff.h" +#include <vespa/eval/instruction/generic_concat.h> +#include <vespa/eval/instruction/generic_join.h> +#include <vespa/eval/instruction/generic_merge.h> +#include <vespa/eval/instruction/generic_reduce.h> +#include <vespa/eval/instruction/generic_rename.h> #include <vespa/vespalib/objects/objectdumper.h> #include <vespa/vespalib/objects/visit.hpp> @@ -87,6 +92,18 @@ void op_tensor_map(State &state, uint64_t param) { state.pop_push(state.engine.map(state.peek(0), to_map_fun(param), state.stash)); } +// replace with GenericMap when ready +void op_tensor_spec_map(State &state, uint64_t param) { + auto fun = to_map_fun(param); + auto old_spec = state.engine.to_spec(state.peek(0)); + TensorSpec new_spec(old_spec.type()); + for (auto &cell: old_spec.cells()) { + new_spec.add(cell.first, fun(cell.second)); + } + const Value &result = *state.stash.create<Value::UP>(state.engine.from_spec(new_spec)); + state.pop_push(result); +} + void op_tensor_join(State &state, uint64_t param) { state.pop_pop_push(state.engine.join(state.peek(1), state.peek(0), to_join_fun(param), state.stash)); } @@ -239,7 +256,7 @@ Op2::visit_children(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -ConstValue::compile_self(const TensorEngine &, Stash &) const +ConstValue::compile_self(EngineOrFactory, Stash &) const { return Instruction(op_load_const, wrap_param<Value>(_value)); } @@ -258,7 +275,7 @@ ConstValue::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Inject::compile_self(const TensorEngine &, Stash &) const +Inject::compile_self(EngineOrFactory, Stash &) const { return Instruction::fetch_param(_param_idx); } @@ -273,8 +290,11 @@ Inject::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Reduce::compile_self(const TensorEngine &, Stash &stash) const +Reduce::compile_self(EngineOrFactory engine, Stash &stash) const { + if (engine.is_factory()) { + return instruction::GenericReduce::make_instruction(child().result_type(), aggr(), dimensions(), engine.factory(), stash); + } ReduceParams ¶ms = stash.create<ReduceParams>(_aggr, _dimensions); return Instruction(op_tensor_reduce, wrap_param<ReduceParams>(params)); } @@ -290,8 +310,12 @@ Reduce::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Map::compile_self(const TensorEngine &, Stash &) const +Map::compile_self(EngineOrFactory engine, Stash &) const { + if (engine.is_factory()) { + // replace with GenericMap when ready + return Instruction(op_tensor_spec_map, to_param(_function)); + } if (result_type().is_double()) { return Instruction(op_double_map, to_param(_function)); } @@ -308,8 +332,11 @@ Map::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Join::compile_self(const TensorEngine &, Stash &) const +Join::compile_self(EngineOrFactory engine, Stash &stash) const { + if (engine.is_factory()) { + return instruction::GenericJoin::make_instruction(lhs().result_type(), rhs().result_type(), function(), engine.factory(), stash); + } if (result_type().is_double()) { if (_function == operation::Mul::f) { return Instruction(op_double_mul); @@ -332,8 +359,11 @@ Join::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Merge::compile_self(const TensorEngine &, Stash &) const +Merge::compile_self(EngineOrFactory engine, Stash &stash) const { + if (engine.is_factory()) { + return instruction::GenericMerge::make_instruction(lhs().result_type(), rhs().result_type(), function(), engine.factory(), stash); + } return Instruction(op_tensor_merge, to_param(_function)); } @@ -347,8 +377,11 @@ Merge::visit_self(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Concat::compile_self(const TensorEngine &, Stash &) const +Concat::compile_self(EngineOrFactory engine, Stash &stash) const { + if (engine.is_factory()) { + return instruction::GenericConcat::make_instruction(lhs().result_type(), rhs().result_type(), dimension(), engine.factory(), stash); + } return Instruction(op_tensor_concat, wrap_param<vespalib::string>(_dimension)); } @@ -370,7 +403,7 @@ Create::push_children(std::vector<Child::CREF> &children) const } Instruction -Create::compile_self(const TensorEngine &, Stash &) const +Create::compile_self(EngineOrFactory, Stash &) const { return Instruction(op_tensor_create, wrap_param<Create>(*this)); } @@ -432,7 +465,7 @@ Lambda::create_spec_impl(const ValueType &type, const LazyParams ¶ms, const } InterpretedFunction::Instruction -Lambda::compile_self(const TensorEngine &engine, Stash &stash) const +Lambda::compile_self(EngineOrFactory engine, Stash &stash) const { InterpretedFunction fun(engine, _lambda->root(), _lambda_types); LambdaParams ¶ms = stash.create<LambdaParams>(*this, std::move(fun)); @@ -464,7 +497,7 @@ Peek::push_children(std::vector<Child::CREF> &children) const } Instruction -Peek::compile_self(const TensorEngine &, Stash &) const +Peek::compile_self(EngineOrFactory, Stash &) const { return Instruction(op_tensor_peek, wrap_param<Peek>(*this)); } @@ -493,8 +526,11 @@ Peek::visit_children(vespalib::ObjectVisitor &visitor) const //----------------------------------------------------------------------------- Instruction -Rename::compile_self(const TensorEngine &, Stash &stash) const +Rename::compile_self(EngineOrFactory engine, Stash &stash) const { + if (engine.is_factory()) { + return instruction::GenericRename::make_instruction(child().result_type(), from(), to(), engine.factory(), stash); + } RenameParams ¶ms = stash.create<RenameParams>(_from, _to); return Instruction(op_tensor_rename, wrap_param<RenameParams>(params)); } @@ -517,7 +553,7 @@ If::push_children(std::vector<Child::CREF> &children) const } Instruction -If::compile_self(const TensorEngine &, Stash &) const +If::compile_self(EngineOrFactory, Stash &) const { // 'if' is handled directly by compile_tensor_function to enable // lazy-evaluation of true/false sub-expressions. diff --git a/eval/src/vespa/eval/eval/tensor_function.h b/eval/src/vespa/eval/eval/tensor_function.h index c7733147e48..d6158f8eb4a 100644 --- a/eval/src/vespa/eval/eval/tensor_function.h +++ b/eval/src/vespa/eval/eval/tensor_function.h @@ -107,7 +107,7 @@ struct TensorFunction * @param engine the tensor engine used for evaluation * @param stash heterogeneous object store **/ - virtual InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const = 0; + virtual InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const = 0; // for debug dumping vespalib::string as_string() const; @@ -188,7 +188,7 @@ public: ConstValue(const Value &value_in) : Super(value_in.type()), _value(value_in) {} const Value &value() const { return _value; } bool result_is_mutable() const override { return false; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -204,7 +204,7 @@ public: : Super(result_type_in), _param_idx(param_idx_in) {} size_t param_idx() const { return _param_idx; } bool result_is_mutable() const override { return false; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -225,7 +225,7 @@ public: Aggr aggr() const { return _aggr; } const std::vector<vespalib::string> &dimensions() const { return _dimensions; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -243,7 +243,7 @@ public: : Super(result_type_in, child_in), _function(function_in) {} map_fun_t function() const { return _function; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -262,7 +262,7 @@ public: : Super(result_type_in, lhs_in, rhs_in), _function(function_in) {} join_fun_t function() const { return _function; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -281,7 +281,7 @@ public: : Super(result_type_in, lhs_in, rhs_in), _function(function_in) {} join_fun_t function() const { return _function; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -300,7 +300,7 @@ public: : Super(result_type_in, lhs_in, rhs_in), _dimension(dimension_in) {} const vespalib::string &dimension() const { return _dimension; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -321,7 +321,7 @@ public: } const std::map<TensorSpec::Address, Child> &spec() const { return _spec; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void push_children(std::vector<Child::CREF> &children) const final override; void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; @@ -346,7 +346,7 @@ public: return create_spec_impl(result_type(), params, _bindings, fun); } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -380,7 +380,7 @@ public: const std::map<vespalib::string, MyLabel> &spec() const { return _spec; } const ValueType ¶m_type() const { return _param.get().result_type(); } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void push_children(std::vector<Child::CREF> &children) const final override; void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; @@ -402,7 +402,7 @@ public: const std::vector<vespalib::string> &from() const { return _from; } const std::vector<vespalib::string> &to() const { return _to; } bool result_is_mutable() const override { return true; } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_self(vespalib::ObjectVisitor &visitor) const override; }; @@ -428,7 +428,7 @@ public: return (true_child().result_is_mutable() && false_child().result_is_mutable()); } - InterpretedFunction::Instruction compile_self(const TensorEngine &engine, Stash &stash) const final override; + InterpretedFunction::Instruction compile_self(EngineOrFactory engine, Stash &stash) const final override; void visit_children(vespalib::ObjectVisitor &visitor) const final override; }; diff --git a/eval/src/vespa/eval/eval/test/eval_fixture.cpp b/eval/src/vespa/eval/eval/test/eval_fixture.cpp index 0b27ba1f2df..a353f3a9ae2 100644 --- a/eval/src/vespa/eval/eval/test/eval_fixture.cpp +++ b/eval/src/vespa/eval/eval/test/eval_fixture.cpp @@ -79,7 +79,7 @@ const TensorFunction &maybe_patch(bool allow_mutable, const TensorFunction &plai return root.get(); } -std::vector<Value::UP> make_params(const TensorEngine &engine, const Function &function, +std::vector<Value::UP> make_params(EngineOrFactory engine, const Function &function, const ParamRepo ¶m_repo) { std::vector<Value::UP> result; @@ -191,7 +191,7 @@ EvalFixture::detect_param_tampering(const ParamRepo ¶m_repo, bool allow_muta } } -EvalFixture::EvalFixture(const TensorEngine &engine, +EvalFixture::EvalFixture(EngineOrFactory engine, const vespalib::string &expr, const ParamRepo ¶m_repo, bool optimized, diff --git a/eval/src/vespa/eval/eval/test/eval_fixture.h b/eval/src/vespa/eval/eval/test/eval_fixture.h index 31fcee49782..54693cbc1bb 100644 --- a/eval/src/vespa/eval/eval/test/eval_fixture.h +++ b/eval/src/vespa/eval/eval/test/eval_fixture.h @@ -45,7 +45,7 @@ public: }; private: - const TensorEngine &_engine; + EngineOrFactory _engine; Stash _stash; std::shared_ptr<Function const> _function; NodeTypes _node_types; @@ -74,7 +74,7 @@ private: void detect_param_tampering(const ParamRepo ¶m_repo, bool allow_mutable) const; public: - EvalFixture(const TensorEngine &engine, const vespalib::string &expr, const ParamRepo ¶m_repo, + EvalFixture(EngineOrFactory engine, const vespalib::string &expr, const ParamRepo ¶m_repo, bool optimized = true, bool allow_mutable = false); ~EvalFixture() {} template <typename T> diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp index 95e720cd1a2..c6f73d611cc 100644 --- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp +++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp @@ -39,7 +39,7 @@ struct Eval { TensorSpec _tensor; public: Result() : _type(Type::ERROR), _number(0.0), _tensor("error") {} - Result(const TensorEngine &engine, const Value &value) : _type(Type::ERROR), _number(0.0), _tensor("error") { + Result(EngineOrFactory engine, const Value &value) : _type(Type::ERROR), _number(0.0), _tensor("error") { if (value.is_double()) { _type = Type::NUMBER; } @@ -62,15 +62,15 @@ struct Eval { return _tensor; } }; - virtual Result eval(const TensorEngine &) const { + virtual Result eval(EngineOrFactory) const { TEST_ERROR("wrong signature"); return Result(); } - virtual Result eval(const TensorEngine &, const TensorSpec &) const { + virtual Result eval(EngineOrFactory, const TensorSpec &) const { TEST_ERROR("wrong signature"); return Result(); } - virtual Result eval(const TensorEngine &, const TensorSpec &, const TensorSpec &) const { + virtual Result eval(EngineOrFactory, const TensorSpec &, const TensorSpec &) const { TEST_ERROR("wrong signature"); return Result(); } @@ -81,7 +81,7 @@ struct Eval { struct SafeEval : Eval { const Eval &unsafe; SafeEval(const Eval &unsafe_in) : unsafe(unsafe_in) {} - Result eval(const TensorEngine &engine) const override { + Result eval(EngineOrFactory engine) const override { try { return unsafe.eval(engine); } catch (std::exception &e) { @@ -89,7 +89,7 @@ struct SafeEval : Eval { return Result(); } } - Result eval(const TensorEngine &engine, const TensorSpec &a) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a) const override { try { return unsafe.eval(engine, a); } catch (std::exception &e) { @@ -98,7 +98,7 @@ struct SafeEval : Eval { } } - Result eval(const TensorEngine &engine, const TensorSpec &a, const TensorSpec &b) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a, const TensorSpec &b) const override { try { return unsafe.eval(engine, a, b); } catch (std::exception &e) { @@ -118,7 +118,7 @@ const Value &check_type(const Value &value, const ValueType &expect_type) { struct Expr_V : Eval { const vespalib::string &expr; Expr_V(const vespalib::string &expr_in) : expr(expr_in) {} - Result eval(const TensorEngine &engine) const override { + Result eval(EngineOrFactory engine) const override { auto fun = Function::parse(expr); NodeTypes types(*fun, {}); InterpretedFunction ifun(engine, *fun, types); @@ -132,7 +132,7 @@ struct Expr_V : Eval { struct Expr_T : Eval { const vespalib::string &expr; Expr_T(const vespalib::string &expr_in) : expr(expr_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a) const override { auto fun = Function::parse(expr); auto a_type = ValueType::from_spec(a.type()); NodeTypes types(*fun, {a_type}); @@ -148,7 +148,7 @@ struct Expr_T : Eval { struct Expr_TT : Eval { vespalib::string expr; Expr_TT(const vespalib::string &expr_in) : expr(expr_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a, const TensorSpec &b) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a, const TensorSpec &b) const override { auto fun = Function::parse(expr); auto a_type = ValueType::from_spec(a.type()); auto b_type = ValueType::from_spec(b.type()); @@ -162,7 +162,7 @@ struct Expr_TT : Eval { } }; -const Value &make_value(const TensorEngine &engine, const TensorSpec &spec, Stash &stash) { +const Value &make_value(EngineOrFactory engine, const TensorSpec &spec, Stash &stash) { return *stash.create<Value::UP>(engine.from_spec(spec)); } @@ -175,7 +175,7 @@ struct ImmediateReduce : Eval { ImmediateReduce(Aggr aggr_in) : aggr(aggr_in), dimensions() {} ImmediateReduce(Aggr aggr_in, const vespalib::string &dimension) : aggr(aggr_in), dimensions({dimension}) {} - Result eval(const TensorEngine &engine, const TensorSpec &a) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a) const override { Stash stash; const auto &lhs = make_value(engine, a, stash); return Result(engine, engine.reduce(lhs, aggr, dimensions, stash)); @@ -187,7 +187,7 @@ struct ImmediateMap : Eval { using fun_t = double (*)(double); fun_t function; ImmediateMap(fun_t function_in) : function(function_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a) const override { Stash stash; const auto &lhs = make_value(engine, a, stash); return Result(engine, engine.map(lhs, function, stash)); @@ -199,7 +199,7 @@ struct ImmediateJoin : Eval { using fun_t = double (*)(double, double); fun_t function; ImmediateJoin(fun_t function_in) : function(function_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a, const TensorSpec &b) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a, const TensorSpec &b) const override { Stash stash; const auto &lhs = make_value(engine, a, stash); const auto &rhs = make_value(engine, b, stash); @@ -211,7 +211,7 @@ struct ImmediateJoin : Eval { struct ImmediateConcat : Eval { vespalib::string dimension; ImmediateConcat(const vespalib::string &dimension_in) : dimension(dimension_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a, const TensorSpec &b) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a, const TensorSpec &b) const override { Stash stash; const auto &lhs = make_value(engine, a, stash); const auto &rhs = make_value(engine, b, stash); @@ -225,7 +225,7 @@ struct ImmediateRename : Eval { std::vector<vespalib::string> to; ImmediateRename(const std::vector<vespalib::string> &from_in, const std::vector<vespalib::string> &to_in) : from(from_in), to(to_in) {} - Result eval(const TensorEngine &engine, const TensorSpec &a) const override { + Result eval(EngineOrFactory engine, const TensorSpec &a) const override { Stash stash; const auto &lhs = make_value(engine, a, stash); return Result(engine, engine.rename(lhs, from, to, stash)); @@ -284,10 +284,10 @@ bool is_same(const nbostream &a, const nbostream &b) { struct TestContext { vespalib::string module_path; - const TensorEngine &ref_engine; - const TensorEngine &engine; + EngineOrFactory ref_engine; + EngineOrFactory engine; - TestContext(const vespalib::string &module_path_in, const TensorEngine &engine_in) + TestContext(const vespalib::string &module_path_in, EngineOrFactory engine_in) : module_path(module_path_in), ref_engine(SimpleTensorEngine::ref()), engine(engine_in) {} //------------------------------------------------------------------------- @@ -339,7 +339,9 @@ struct TestContext { vespalib::string expr = make_string("reduce(a,%s,%s)", AggrNames::name_of(aggr)->c_str(), domain.dimension.c_str()); TEST_DO(verify_reduce_result(Expr_T(expr), input, expect)); - TEST_DO(verify_reduce_result(ImmediateReduce(aggr, domain.dimension), input, expect)); + if (engine.is_engine()) { + TEST_DO(verify_reduce_result(ImmediateReduce(aggr, domain.dimension), input, expect)); + } } { Eval::Result expect = ImmediateReduce(aggr).eval(ref_engine, input); @@ -347,7 +349,9 @@ struct TestContext { infer_type(layout).c_str()).c_str()); vespalib::string expr = make_string("reduce(a,%s)", AggrNames::name_of(aggr)->c_str()); TEST_DO(verify_reduce_result(Expr_T(expr), input, expect)); - TEST_DO(verify_reduce_result(ImmediateReduce(aggr), input, expect)); + if (engine.is_engine()) { + TEST_DO(verify_reduce_result(ImmediateReduce(aggr), input, expect)); + } } } } @@ -384,7 +388,9 @@ struct TestContext { } void test_map_op(const vespalib::string &expr, map_fun_t op, const Sequence &seq) { - TEST_DO(test_map_op(ImmediateMap(op), op, seq)); + if (engine.is_engine()) { + TEST_DO(test_map_op(ImmediateMap(op), op, seq)); + } TEST_DO(test_map_op(Expr_T(expr), op, seq)); TEST_DO(test_map_op(Expr_T(make_string("map(x,f(a)(%s))", expr.c_str())), op, seq)); } @@ -661,7 +667,9 @@ struct TestContext { } void test_apply_op(const vespalib::string &expr, join_fun_t op, const Sequence &seq) { - TEST_DO(test_apply_op(ImmediateJoin(op), op, seq)); + if (engine.is_engine()) { + TEST_DO(test_apply_op(ImmediateJoin(op), op, seq)); + } TEST_DO(test_apply_op(Expr_TT(expr), op, seq)); TEST_DO(test_apply_op(Expr_TT(make_string("join(x,y,f(a,b)(%s))", expr.c_str())), op, seq)); } @@ -723,9 +731,11 @@ struct TestContext { const vespalib::string &dimension, const TensorSpec &expect) { - ImmediateConcat eval(dimension); vespalib::string expr = make_string("concat(a,b,%s)", dimension.c_str()); - TEST_DO(verify_result(eval.eval(engine, a, b), expect)); + if (engine.is_engine()) { + ImmediateConcat eval(dimension); + TEST_DO(verify_result(eval.eval(engine, a, b), expect)); + } TEST_DO(verify_result(Expr_TT(expr).eval(engine, a, b), expect)); } @@ -763,8 +773,10 @@ struct TestContext { const std::vector<vespalib::string> &to, const TensorSpec &expect) { - ImmediateRename eval(from, to); - TEST_DO(verify_result(eval.eval(engine, input), expect)); + if (engine.is_engine()) { + ImmediateRename eval(from, to); + TEST_DO(verify_result(eval.eval(engine, input), expect)); + } TEST_DO(verify_result(Expr_T(expr).eval(engine, input), expect)); } @@ -857,8 +869,8 @@ struct TestContext { //------------------------------------------------------------------------- void verify_encode_decode(const TensorSpec &spec, - const TensorEngine &encode_engine, - const TensorEngine &decode_engine) + EngineOrFactory encode_engine, + EngineOrFactory decode_engine) { Stash stash; nbostream data; @@ -948,7 +960,7 @@ struct TestContext { } // namespace vespalib::eval::test::<unnamed> void -TensorConformance::run_tests(const vespalib::string &module_path, const TensorEngine &engine) +TensorConformance::run_tests(const vespalib::string &module_path, EngineOrFactory engine) { TestContext ctx(module_path, engine); fprintf(stderr, "module path: '%s'\n", ctx.module_path.c_str()); diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.h b/eval/src/vespa/eval/eval/test/tensor_conformance.h index e7f0560c71f..9aed3840191 100644 --- a/eval/src/vespa/eval/eval/test/tensor_conformance.h +++ b/eval/src/vespa/eval/eval/test/tensor_conformance.h @@ -2,7 +2,7 @@ #pragma once -#include <vespa/eval/eval/tensor_engine.h> +#include <vespa/eval/eval/engine_or_factory.h> #include <vespa/vespalib/stllike/string.h> namespace vespalib { @@ -14,7 +14,7 @@ namespace test { * implementations of the TensorEngine interface. **/ struct TensorConformance { - static void run_tests(const vespalib::string &module_path, const TensorEngine &engine); + static void run_tests(const vespalib::string &module_path, EngineOrFactory engine); }; } // namespace vespalib::eval::test diff --git a/eval/src/vespa/eval/eval/value.cpp b/eval/src/vespa/eval/eval/value.cpp index 7bf2d587904..1e9aca9e079 100644 --- a/eval/src/vespa/eval/eval/value.cpp +++ b/eval/src/vespa/eval/eval/value.cpp @@ -2,6 +2,7 @@ #include "value.h" #include "tensor_engine.h" +#include <vespa/vespalib/util/typify.h> namespace vespalib { namespace eval { @@ -22,6 +23,16 @@ struct TrivialView : Value::Index::View { } }; +struct MySum { + template <typename CT> static double invoke(TypedCells cells) { + double res = 0.0; + for (CT cell: cells.typify<CT>()) { + res += cell; + } + return res; + } +}; + } // <unnamed> @@ -40,6 +51,12 @@ TrivialIndex::create_view(const std::vector<size_t> &) const return std::make_unique<TrivialView>(); } +double +Value::as_double() const +{ + return typify_invoke<1,TypifyCellType,MySum>(type().cell_type(), cells()); +} + ValueType DoubleValue::_type = ValueType::double_type(); } // namespace vespalib::eval diff --git a/eval/src/vespa/eval/eval/value.h b/eval/src/vespa/eval/eval/value.h index da4fc47f29b..daa6678dab2 100644 --- a/eval/src/vespa/eval/eval/value.h +++ b/eval/src/vespa/eval/eval/value.h @@ -62,9 +62,9 @@ struct Value { // --- end of new interface // --- old interface that may be (partially) removed in the future - virtual bool is_double() const { return false; } - virtual bool is_tensor() const { return false; } - virtual double as_double() const { return 0.0; } + virtual bool is_double() const { return type().is_double(); } + virtual bool is_tensor() const { return type().is_tensor(); } + virtual double as_double() const; bool as_bool() const { return (as_double() != 0.0); } virtual const Tensor *as_tensor() const { return nullptr; } // --- end of old interface diff --git a/eval/src/vespa/eval/eval/value_cache/constant_tensor_loader.h b/eval/src/vespa/eval/eval/value_cache/constant_tensor_loader.h index 6f998232488..8fb6460efcf 100644 --- a/eval/src/vespa/eval/eval/value_cache/constant_tensor_loader.h +++ b/eval/src/vespa/eval/eval/value_cache/constant_tensor_loader.h @@ -3,7 +3,7 @@ #pragma once #include "constant_value.h" -#include <vespa/eval/eval/tensor_engine.h> +#include <vespa/eval/eval/engine_or_factory.h> #include <vespa/vespalib/stllike/string.h> namespace vespalib { @@ -19,9 +19,9 @@ namespace eval { class ConstantTensorLoader : public ConstantValueFactory { private: - const TensorEngine &_engine; + EngineOrFactory _engine; public: - ConstantTensorLoader(const TensorEngine &engine) : _engine(engine) {} + ConstantTensorLoader(EngineOrFactory engine) : _engine(engine) {} ConstantValue::UP create(const vespalib::string &path, const vespalib::string &type) const override; }; diff --git a/eval/src/vespa/eval/eval/value_codec.cpp b/eval/src/vespa/eval/eval/value_codec.cpp index 762cecea1c3..c6456a7b723 100644 --- a/eval/src/vespa/eval/eval/value_codec.cpp +++ b/eval/src/vespa/eval/eval/value_codec.cpp @@ -111,6 +111,9 @@ ValueType decode_type(nbostream &input, const Format &format) { dim_list.emplace_back(name, input.getInt1_4Bytes()); } } + if (dim_list.empty()) { + assert(cell_type == ValueType::CellType::DOUBLE); + } return ValueType::tensor_type(std::move(dim_list), cell_type); } @@ -138,10 +141,9 @@ void decode_mapped_labels(nbostream &input, size_t num_mapped_dims, std::vector< template<typename T> void decode_cells(nbostream &input, size_t num_cells, ArrayRef<T> dst) { - T value; + assert(num_cells == dst.size()); for (size_t i = 0; i < num_cells; ++i) { - input >> value; - dst[i] = value; + dst[i] = input.readValue<T>(); } } @@ -167,6 +169,10 @@ struct ContentDecoder { auto block_cells = builder->add_subspace(address); decode_cells(input, state.subspace_size, block_cells); } + // add implicit empty subspace + if ((state.num_mapped_dims == 0) && (state.num_blocks == 0)) { + builder->add_subspace({}); + } return builder->build(std::move(builder)); } }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.cpp index cdeca1653a6..a9ef5a89a1c 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.cpp @@ -42,7 +42,7 @@ DenseCellRangeFunction::DenseCellRangeFunction(const eval::ValueType &result_typ DenseCellRangeFunction::~DenseCellRangeFunction() = default; eval::InterpretedFunction::Instruction -DenseCellRangeFunction::compile_self(const TensorEngine &, Stash &) const +DenseCellRangeFunction::compile_self(eval::EngineOrFactory, Stash &) const { assert(result_type().cell_type() == child().result_type().cell_type()); diff --git a/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.h b/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.h index 3f220826324..adc1047f8f3 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_cell_range_function.h @@ -24,7 +24,7 @@ public: ~DenseCellRangeFunction() override; size_t offset() const { return _offset; } size_t length() const { return _length; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return child().result_is_mutable(); } }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.cpp index 09530beb0b1..7b68bb52e3a 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.cpp @@ -73,7 +73,7 @@ DenseDotProductFunction::DenseDotProductFunction(const eval::TensorFunction &lhs } eval::InterpretedFunction::Instruction -DenseDotProductFunction::compile_self(const TensorEngine &, Stash &) const +DenseDotProductFunction::compile_self(eval::EngineOrFactory, Stash &) const { auto op = my_select(lhs().result_type().cell_type(), rhs().result_type().cell_type()); return eval::InterpretedFunction::Instruction(op); diff --git a/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.h b/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.h index 1ee6baff2a5..28f49035860 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_dot_product_function.h @@ -16,7 +16,7 @@ private: public: DenseDotProductFunction(const eval::TensorFunction &lhs_in, const eval::TensorFunction &rhs_in); - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return true; } static bool compatible_types(const ValueType &res, const ValueType &lhs, const ValueType &rhs); static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); diff --git a/eval/src/vespa/eval/tensor/dense/dense_lambda_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_lambda_function.cpp index 81c91c8377e..0005a56736d 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_lambda_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_lambda_function.cpp @@ -28,8 +28,6 @@ using State = InterpretedFunction::State; using namespace eval::tensor_function; -const TensorEngine &prod_engine = DefaultTensorEngine::ref(); - namespace { //----------------------------------------------------------------------------- @@ -105,11 +103,11 @@ struct InterpretedParams { const std::vector<size_t> &bindings; size_t num_cells; InterpretedFunction fun; - InterpretedParams(const Lambda &lambda) + InterpretedParams(const Lambda &lambda, eval::EngineOrFactory engine) : result_type(lambda.result_type()), bindings(lambda.bindings()), num_cells(result_type.dense_subspace_size()), - fun(prod_engine, lambda.lambda().root(), lambda.types()) + fun(engine, lambda.lambda().root(), lambda.types()) { assert(lambda.lambda().num_params() == (result_type.dimensions().size() + bindings.size())); } @@ -159,9 +157,8 @@ DenseLambdaFunction::eval_mode() const } Instruction -DenseLambdaFunction::compile_self(const TensorEngine &engine, Stash &stash) const +DenseLambdaFunction::compile_self(eval::EngineOrFactory engine, Stash &stash) const { - assert(&engine == &prod_engine); auto mode = eval_mode(); using MyTypify = eval::TypifyCellType; if (mode == EvalMode::COMPILED) { @@ -170,7 +167,7 @@ DenseLambdaFunction::compile_self(const TensorEngine &engine, Stash &stash) cons return Instruction(op, wrap_param<CompiledParams>(params)); } else { assert(mode == EvalMode::INTERPRETED); - InterpretedParams ¶ms = stash.create<InterpretedParams>(_lambda); + InterpretedParams ¶ms = stash.create<InterpretedParams>(_lambda, engine); auto op = typify_invoke<1,MyTypify,MyInterpretedLambdaOp>(result_type().cell_type()); return Instruction(op, wrap_param<InterpretedParams>(params)); } diff --git a/eval/src/vespa/eval/tensor/dense/dense_lambda_function.h b/eval/src/vespa/eval/tensor/dense/dense_lambda_function.h index a1b6e5a1551..e82c022d781 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_lambda_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_lambda_function.h @@ -23,7 +23,7 @@ public: ~DenseLambdaFunction() override; bool result_is_mutable() const override { return true; } EvalMode eval_mode() const; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.cpp index 50f58526f7c..cae17e5ebe2 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.cpp @@ -61,7 +61,7 @@ DenseLambdaPeekFunction::DenseLambdaPeekFunction(const ValueType &result_type, DenseLambdaPeekFunction::~DenseLambdaPeekFunction() = default; InterpretedFunction::Instruction -DenseLambdaPeekFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseLambdaPeekFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { const Self &self = stash.create<Self>(result_type(), *_idx_fun); using MyTypify = eval::TypifyCellType; diff --git a/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.h b/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.h index a4146787bfa..7358ef1427c 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_lambda_peek_function.h @@ -23,7 +23,7 @@ public: const eval::TensorFunction &child, std::shared_ptr<eval::Function const> idx_fun); ~DenseLambdaPeekFunction() override; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; vespalib::string idx_fun_dump() const; bool result_is_mutable() const override { return true; } }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_matmul_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_matmul_function.cpp index 36010fb30ca..23bddc36bb1 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_matmul_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_matmul_function.cpp @@ -166,7 +166,7 @@ DenseMatMulFunction::DenseMatMulFunction(const eval::ValueType &result_type, DenseMatMulFunction::~DenseMatMulFunction() = default; eval::InterpretedFunction::Instruction -DenseMatMulFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseMatMulFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { using MyTypify = TypifyValue<eval::TypifyCellType,TypifyBool>; Self &self = stash.create<Self>(result_type(), _lhs_size, _common_size, _rhs_size); diff --git a/eval/src/vespa/eval/tensor/dense/dense_matmul_function.h b/eval/src/vespa/eval/tensor/dense/dense_matmul_function.h index 88d7b9f37e0..bf9779177bb 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_matmul_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_matmul_function.h @@ -50,7 +50,7 @@ public: bool lhs_common_inner() const { return _lhs_common_inner; } bool rhs_common_inner() const { return _rhs_common_inner; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) 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_multi_matmul_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.cpp index 4f228947624..8788d621693 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.cpp @@ -184,7 +184,7 @@ DenseMultiMatMulFunction::DenseMultiMatMulFunction(const ValueType &result_type, DenseMultiMatMulFunction::~DenseMultiMatMulFunction() = default; InterpretedFunction::Instruction -DenseMultiMatMulFunction::compile_self(const TensorEngine &, Stash &) const +DenseMultiMatMulFunction::compile_self(eval::EngineOrFactory, Stash &) const { auto op = my_select(lhs().result_type().cell_type()); return InterpretedFunction::Instruction(op, wrap_param<DenseMultiMatMulFunction>(*this)); diff --git a/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.h b/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.h index 6df323d6358..17ad6438593 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_multi_matmul_function.h @@ -44,7 +44,7 @@ public: bool lhs_common_inner() const { return _lhs_common_inner; } bool rhs_common_inner() const { return _rhs_common_inner; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) 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_number_join_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_number_join_function.cpp index c6636a6a583..d6995256411 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 @@ -95,7 +95,7 @@ DenseNumberJoinFunction::inplace() const } Instruction -DenseNumberJoinFunction::compile_self(const TensorEngine &, Stash &) const +DenseNumberJoinFunction::compile_self(eval::EngineOrFactory, Stash &) const { auto op = typify_invoke<4,MyTypify,MyGetFun>(result_type().cell_type(), function(), inplace(), (_primary == Primary::RHS)); diff --git a/eval/src/vespa/eval/tensor/dense/dense_number_join_function.h b/eval/src/vespa/eval/tensor/dense/dense_number_join_function.h index a4036a7ec34..c4478ce43b6 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_number_join_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_number_join_function.h @@ -27,7 +27,7 @@ public: ~DenseNumberJoinFunction() override; Primary primary() const { return _primary; } bool inplace() const; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 8880a78529d..004edf06d92 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 @@ -34,7 +34,7 @@ DenseReplaceTypeFunction::~DenseReplaceTypeFunction() } eval::InterpretedFunction::Instruction -DenseReplaceTypeFunction::compile_self(const TensorEngine &, Stash &) const +DenseReplaceTypeFunction::compile_self(eval::EngineOrFactory, Stash &) const { return eval::InterpretedFunction::Instruction(my_replace_type_op, wrap_param<ValueType>(result_type())); } diff --git a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h b/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h index 22c3886022d..504d3f1649b 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h @@ -16,7 +16,7 @@ public: DenseReplaceTypeFunction(const eval::ValueType &result_type, const eval::TensorFunction &child); ~DenseReplaceTypeFunction(); - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return child().result_is_mutable(); } static const DenseReplaceTypeFunction &create_compact(const eval::ValueType &result_type, const eval::TensorFunction &child, diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.cpp index e61e843e801..b2cf390dc11 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.cpp @@ -102,7 +102,7 @@ DenseSimpleExpandFunction::DenseSimpleExpandFunction(const ValueType &result_typ DenseSimpleExpandFunction::~DenseSimpleExpandFunction() = default; Instruction -DenseSimpleExpandFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseSimpleExpandFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { size_t result_size = result_type().dense_subspace_size(); const ExpandParams ¶ms = stash.create<ExpandParams>(result_type(), result_size, function()); diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.h b/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.h index 4d7c639e3d1..c5c40559c1b 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_expand_function.h @@ -32,7 +32,7 @@ public: Inner inner_in); ~DenseSimpleExpandFunction() override; Inner inner() const { return _inner; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 7ba043f6510..5aca3799258 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 @@ -190,7 +190,7 @@ DenseSimpleJoinFunction::factor() const } Instruction -DenseSimpleJoinFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseSimpleJoinFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { const JoinParams ¶ms = stash.create<JoinParams>(result_type(), factor(), function()); auto op = typify_invoke<6,MyTypify,MyGetFun>(lhs().result_type().cell_type(), diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h b/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h index ef09b2a4880..2cd918e1b06 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h @@ -32,7 +32,7 @@ public: Overlap overlap() const { return _overlap; } bool primary_is_mutable() const; size_t factor() const; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 da9b681019e..1086af91ec4 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 @@ -72,7 +72,7 @@ DenseSimpleMapFunction::DenseSimpleMapFunction(const ValueType &result_type, DenseSimpleMapFunction::~DenseSimpleMapFunction() = default; Instruction -DenseSimpleMapFunction::compile_self(const TensorEngine &, Stash &) const +DenseSimpleMapFunction::compile_self(eval::EngineOrFactory, Stash &) const { auto op = typify_invoke<3,MyTypify,MyGetFun>(result_type().cell_type(), function(), inplace()); static_assert(sizeof(uint64_t) == sizeof(function())); diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h b/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h index 6497e5aa445..ce0498c9ab7 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h @@ -18,7 +18,7 @@ public: map_fun_t function_in); ~DenseSimpleMapFunction() override; bool inplace() const { return child().result_is_mutable(); } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 d18d8035e0a..c0bc3f26fe9 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 @@ -95,7 +95,7 @@ DenseSingleReduceFunction::DenseSingleReduceFunction(const ValueType &result_typ DenseSingleReduceFunction::~DenseSingleReduceFunction() = default; InterpretedFunction::Instruction -DenseSingleReduceFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseSingleReduceFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { auto op = typify_invoke<2,MyTypify,MyGetFun>(result_type().cell_type(), _aggr); auto ¶ms = stash.create<Params>(result_type(), child().result_type(), _dim_idx); diff --git a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h b/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h index 037994727fc..7f9313df600 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h @@ -24,7 +24,7 @@ public: size_t dim_idx() const { return _dim_idx; } eval::Aggr aggr() const { return _aggr; } bool result_is_mutable() const override { return true; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 57eb1fe4a74..1ad6e00f279 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 @@ -69,7 +69,7 @@ DenseTensorCreateFunction::push_children(std::vector<Child::CREF> &target) const } eval::InterpretedFunction::Instruction -DenseTensorCreateFunction::compile_self(const TensorEngine &, Stash &) const +DenseTensorCreateFunction::compile_self(eval::EngineOrFactory, Stash &) const { using MyTypify = eval::TypifyCellType; auto op = typify_invoke<1,MyTypify,MyTensorCreateOp>(result_type().cell_type()); diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h b/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h index d471658fba0..a2ca71ce894 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h @@ -25,7 +25,7 @@ public: ~DenseTensorCreateFunction(); const eval::ValueType &result_type() const override { return _self.result_type; } void push_children(std::vector<Child::CREF> &children) const override; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return true; } static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.cpp index bea95a1207d..f4725cae803 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.cpp @@ -70,7 +70,7 @@ DenseTensorPeekFunction::push_children(std::vector<Child::CREF> &target) const } eval::InterpretedFunction::Instruction -DenseTensorPeekFunction::compile_self(const TensorEngine &, Stash &) const +DenseTensorPeekFunction::compile_self(eval::EngineOrFactory, Stash &) const { using MyTypify = eval::TypifyCellType; auto op = typify_invoke<1,MyTypify,MyTensorPeekOp>(_children[0].get().result_type().cell_type()); diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.h b/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.h index 8ed672f95b0..1d834c3901a 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.h +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_peek_function.h @@ -26,7 +26,7 @@ public: ~DenseTensorPeekFunction(); const eval::ValueType &result_type() const override { return eval::DoubleValue::double_type(); } void push_children(std::vector<Child::CREF> &children) const override; - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return true; } static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; 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 1b0068f7824..3e60109bbe6 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 @@ -142,7 +142,7 @@ DenseXWProductFunction::DenseXWProductFunction(const eval::ValueType &result_typ } eval::InterpretedFunction::Instruction -DenseXWProductFunction::compile_self(const TensorEngine &, Stash &stash) const +DenseXWProductFunction::compile_self(eval::EngineOrFactory, Stash &stash) const { Self &self = stash.create<Self>(result_type(), _vector_size, _result_size); using MyTypify = TypifyValue<eval::TypifyCellType,vespalib::TypifyBool>; 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 9f05222fff6..fa0f8724aeb 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 @@ -44,7 +44,7 @@ public: size_t result_size() const { return _result_size; } bool common_inner() const { return _common_inner; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) 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/vector_from_doubles_function.cpp b/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp index 9e4a0e3d61b..3c006fe64a0 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 @@ -92,7 +92,7 @@ VectorFromDoublesFunction::push_children(std::vector<Child::CREF> &target) const } eval::InterpretedFunction::Instruction -VectorFromDoublesFunction::compile_self(const TensorEngine &, Stash &) const +VectorFromDoublesFunction::compile_self(eval::EngineOrFactory, Stash &) const { return eval::InterpretedFunction::Instruction(my_vector_from_doubles_op, wrap_param<VectorFromDoublesFunction::Self>(_self)); } diff --git a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h b/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h index 28346c4cb3b..e2bd0386331 100644 --- a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h +++ b/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h @@ -30,7 +30,7 @@ public: return _self.resultType.dimensions()[0].name; } size_t size() const { return _self.resultSize; } - eval::InterpretedFunction::Instruction compile_self(const eval::TensorEngine &engine, Stash &stash) const override; + eval::InterpretedFunction::Instruction compile_self(eval::EngineOrFactory engine, Stash &stash) const override; bool result_is_mutable() const override { return true; } static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash); }; |