diff options
author | Håvard Pettersen <havardpe@oath.com> | 2018-01-16 10:53:41 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2018-01-16 10:53:41 +0000 |
commit | 8852988ac1f0c391d9a3b603bd9f0e5af6c5e310 (patch) | |
tree | 3decf47e4e4971e8570dd51900d2c0cabcdd199b /eval | |
parent | 772fc30ac5acc00dd8122969ceb0dff0770e23f5 (diff) |
Use lazy parameters in tensor functions.
Diffstat (limited to 'eval')
17 files changed, 67 insertions, 79 deletions
diff --git a/eval/src/apps/tensor_conformance/tensor_conformance.cpp b/eval/src/apps/tensor_conformance/tensor_conformance.cpp index 616b98f0809..72fe61d7107 100644 --- a/eval/src/apps/tensor_conformance/tensor_conformance.cpp +++ b/eval/src/apps/tensor_conformance/tensor_conformance.cpp @@ -94,7 +94,7 @@ TensorSpec eval_expr(const Inspector &test, const TensorEngine &engine, bool typ NodeTypes types = typed ? NodeTypes(fun, get_types(param_values)) : NodeTypes(); InterpretedFunction ifun(engine, fun, types); InterpretedFunction::Context ctx(ifun); - InterpretedFunction::SimpleObjectParams params(param_refs); + SimpleObjectParams params(param_refs); return engine.to_spec(ifun.eval(ctx, params)); } 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 29bff7fbd69..5b7fb9af910 100644 --- a/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp +++ b/eval/src/tests/eval/interpreted_function/interpreted_function_test.cpp @@ -180,7 +180,7 @@ struct InnerProduct { InterpretedFunction::Context ctx(interpreted); Value::UP va = engine.from_spec(a); Value::UP vb = engine.from_spec(b); - InterpretedFunction::SimpleObjectParams params({*va,*vb}); + SimpleObjectParams params({*va,*vb}); const Value &result = interpreted.eval(ctx, params); EXPECT_EQUAL(engine.to_spec(result), expect); } 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 641ebddfec2..9f4889ee5be 100644 --- a/eval/src/tests/eval/tensor_function/tensor_function_test.cpp +++ b/eval/src/tests/eval/tensor_function/tensor_function_test.cpp @@ -28,7 +28,7 @@ struct EvalCtx { return id; } const Value &eval(const TensorFunction &fun) { - return fun.eval(params, stash); + return fun.eval(SimpleObjectParams(params), stash); } const TensorFunction &compile(const tensor_function::Node &expr) { return engine.compile(expr, stash); diff --git a/eval/src/tests/tensor/dense_dot_product_function/dense_dot_product_function_test.cpp b/eval/src/tests/tensor/dense_dot_product_function/dense_dot_product_function_test.cpp index 0b8b98fc617..3463bee3447 100644 --- a/eval/src/tests/tensor/dense_dot_product_function/dense_dot_product_function_test.cpp +++ b/eval/src/tests/tensor/dense_dot_product_function/dense_dot_product_function_test.cpp @@ -63,7 +63,8 @@ public: _params.emplace_back(_lhsDenseTensor); _params.emplace_back(_rhsDenseTensor); } - ConstArrayRef<Value::CREF> get() const { return _params; } + SimpleObjectParams get() const { return SimpleObjectParams(_params); } + const Value ¶m(size_t idx) const { return _params[idx]; } double expectedDotProduct() const { return calcDotProduct(_lhsDenseTensor, _rhsDenseTensor); } @@ -80,8 +81,8 @@ struct Fixture const Value &result = function.eval(input.get(), stash); ASSERT_TRUE(result.is_double()); LOG(info, "eval(): (%s) * (%s) = %f", - input.get()[0].get().type().to_spec().c_str(), - input.get()[1].get().type().to_spec().c_str(), + input.param(0).type().to_spec().c_str(), + input.param(1).type().to_spec().c_str(), result.as_double()); return result.as_double(); } diff --git a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp index 5c62d319dc3..f27a2073159 100644 --- a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp +++ b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp @@ -34,8 +34,8 @@ void verify_equal(const Value &expect, const Value &value) { EXPECT_EQUAL(expect_spec, value_spec); } -std::vector<eval::Value::CREF> wrap(std::vector<eval::Value::CREF> params) { - return std::move(params); +SimpleObjectParams wrap(std::vector<eval::Value::CREF> params) { + return SimpleObjectParams(params); } void verify_result(const TensorSpec &v, const TensorSpec &m, bool happy) { diff --git a/eval/src/tests/tensor/tensor_performance/tensor_performance_test.cpp b/eval/src/tests/tensor/tensor_performance/tensor_performance_test.cpp index 2ed0021b5c7..1472fd3497c 100644 --- a/eval/src/tests/tensor/tensor_performance/tensor_performance_test.cpp +++ b/eval/src/tests/tensor/tensor_performance/tensor_performance_test.cpp @@ -33,9 +33,9 @@ struct Params { } }; -InterpretedFunction::SimpleObjectParams make_params(const Function &function, const Params ¶ms) +SimpleObjectParams make_params(const Function &function, const Params ¶ms) { - InterpretedFunction::SimpleObjectParams fun_params({}); + SimpleObjectParams fun_params({}); EXPECT_EQUAL(params.map.size(), function.num_params()); for (size_t i = 0; i < function.num_params(); ++i) { auto param = params.map.find(function.param_name(i)); diff --git a/eval/src/vespa/eval/eval/interpreted_function.cpp b/eval/src/vespa/eval/eval/interpreted_function.cpp index 81309956e58..89d850c2dd3 100644 --- a/eval/src/vespa/eval/eval/interpreted_function.cpp +++ b/eval/src/vespa/eval/eval/interpreted_function.cpp @@ -111,27 +111,9 @@ void op_tensor_concat(State &state, uint64_t param) { //----------------------------------------------------------------------------- -template <typename T> -const T &undef_cref() { - const T *undef = nullptr; - assert(undef); - return *undef; -} - -struct TensorFunctionArgArgMeta { - const TensorFunction &function; - size_t param1; - size_t param2; - TensorFunctionArgArgMeta(const TensorFunction &function_in, size_t param1_in, size_t param2_in) - : function(function_in), param1(param1_in), param2(param2_in) {} -}; - -void op_tensor_function_arg_arg(State &state, uint64_t param) { - const TensorFunctionArgArgMeta &meta = unwrap_param<TensorFunctionArgArgMeta>(param); - Value::CREF params[2] = - {state.params->resolve(meta.param1, state.stash), - state.params->resolve(meta.param2, state.stash)}; - state.stack.push_back(meta.function.eval(ConstArrayRef<Value::CREF>(params, 2), state.stash)); +void op_tensor_function(State &state, uint64_t param) { + const TensorFunction &fun = unwrap_param<TensorFunction>(param); + state.stack.push_back(fun.eval(*state.params, state.stash)); } //----------------------------------------------------------------------------- @@ -279,12 +261,11 @@ struct ProgramBuilder : public NodeVisitor, public NodeTraverser { auto a = as<Symbol>(node.get_child(0).get_child(0)); auto b = as<Symbol>(node.get_child(0).get_child(1)); const auto &ir = tensor_function::reduce(tensor_function::join( - tensor_function::inject(types.get_type(*a), 0, stash), - tensor_function::inject(types.get_type(*b), 1, stash), + tensor_function::inject(types.get_type(*a), a->id(), stash), + tensor_function::inject(types.get_type(*b), b->id(), stash), operation::Mul::f, stash), node.aggr(), node.dimensions(), stash); const auto &fun = tensor_engine.compile(ir, stash); - const auto &meta = stash.create<TensorFunctionArgArgMeta>(fun, a->id(), b->id()); - program.emplace_back(op_tensor_function_arg_arg, wrap_param<TensorFunctionArgArgMeta>(meta)); + program.emplace_back(op_tensor_function, wrap_param<TensorFunction>(fun)); } else { ReduceParams ¶ms = stash.create<ReduceParams>(node.aggr(), node.dimensions()); program.emplace_back(op_tensor_reduce, wrap_param<ReduceParams>(params)); @@ -475,8 +456,6 @@ InterpretedFunction::SimpleParams::SimpleParams(const std::vector<double> ¶m InterpretedFunction::SimpleParams::~SimpleParams() { } -InterpretedFunction::SimpleObjectParams::~SimpleObjectParams() {} - const Value & InterpretedFunction::SimpleParams::resolve(size_t idx, Stash &stash) const { @@ -484,13 +463,6 @@ InterpretedFunction::SimpleParams::resolve(size_t idx, Stash &stash) const return stash.create<DoubleValue>(params[idx]); } -const Value & -InterpretedFunction::SimpleObjectParams::resolve(size_t idx, Stash &) const -{ - assert(idx < params.size()); - return params[idx]; -} - InterpretedFunction::State::State(const TensorEngine &engine_in) : engine(engine_in), params(nullptr), diff --git a/eval/src/vespa/eval/eval/interpreted_function.h b/eval/src/vespa/eval/eval/interpreted_function.h index 0741e7e4191..ea8fcbc3a42 100644 --- a/eval/src/vespa/eval/eval/interpreted_function.h +++ b/eval/src/vespa/eval/eval/interpreted_function.h @@ -39,16 +39,6 @@ public: ~SimpleParams(); const Value &resolve(size_t idx, Stash &stash) const override; }; - /** - * Simple wrapper for object parameters that are known up - * front. Intended for convenience (testing), not performance. - **/ - struct SimpleObjectParams : LazyParams { - std::vector<Value::CREF> params; - explicit SimpleObjectParams(const std::vector<Value::CREF> ¶ms_in) : params(params_in) {} - ~SimpleObjectParams(); - const Value &resolve(size_t idx, Stash &stash) const override; - }; struct State { const TensorEngine &engine; const LazyParams *params; diff --git a/eval/src/vespa/eval/eval/lazy_params.cpp b/eval/src/vespa/eval/eval/lazy_params.cpp index ba8f8a2a002..1aea00eb592 100644 --- a/eval/src/vespa/eval/eval/lazy_params.cpp +++ b/eval/src/vespa/eval/eval/lazy_params.cpp @@ -1,6 +1,7 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "lazy_params.h" +#include <assert.h> namespace vespalib::eval { @@ -8,4 +9,15 @@ LazyParams::~LazyParams() { } +SimpleObjectParams::~SimpleObjectParams() +{ +} + +const Value & +SimpleObjectParams::resolve(size_t idx, Stash &) const +{ + assert(idx < params.size()); + return params[idx]; +} + } // namespace vespalib::eval diff --git a/eval/src/vespa/eval/eval/lazy_params.h b/eval/src/vespa/eval/eval/lazy_params.h index 40436fc2c92..d2c7b066162 100644 --- a/eval/src/vespa/eval/eval/lazy_params.h +++ b/eval/src/vespa/eval/eval/lazy_params.h @@ -2,7 +2,8 @@ #pragma once -#include <stddef.h> +#include <vector> +#include "value.h" namespace vespalib { @@ -10,8 +11,6 @@ class Stash; namespace eval { -class Value; - /** * Interface used to lazy-resolve parameters. **/ @@ -23,5 +22,16 @@ struct LazyParams { virtual ~LazyParams(); }; +/** + * Simple wrapper for object parameters that are known up + * front. Intended for convenience (testing), not performance. + **/ +struct SimpleObjectParams : LazyParams { + std::vector<Value::CREF> params; + explicit SimpleObjectParams(const std::vector<Value::CREF> ¶ms_in) : params(params_in) {} + ~SimpleObjectParams(); + const Value &resolve(size_t idx, Stash &stash) const override; +}; + } // namespace vespalib::eval } // namespace vespalib diff --git a/eval/src/vespa/eval/eval/tensor_function.cpp b/eval/src/vespa/eval/eval/tensor_function.cpp index 763f1cc39ff..83ac51bdc09 100644 --- a/eval/src/vespa/eval/eval/tensor_function.cpp +++ b/eval/src/vespa/eval/eval/tensor_function.cpp @@ -23,9 +23,9 @@ const TensorEngine &infer_engine(const std::initializer_list<Value::CREF> &value //----------------------------------------------------------------------------- const Value & -Inject::eval(ConstArrayRef<Value::CREF> params, Stash &) const +Inject::eval(const LazyParams ¶ms, Stash &stash) const { - return params[tensor_id]; + return params.resolve(tensor_id, stash); } void @@ -36,7 +36,7 @@ Inject::push_children(std::vector<Child::CREF> &) const //----------------------------------------------------------------------------- const Value & -Reduce::eval(ConstArrayRef<Value::CREF> params, Stash &stash) const +Reduce::eval(const LazyParams ¶ms, Stash &stash) const { const Value &a = tensor.get().eval(params, stash); const TensorEngine &engine = infer_engine({a}); @@ -52,7 +52,7 @@ Reduce::push_children(std::vector<Child::CREF> &children) const //----------------------------------------------------------------------------- const Value & -Map::eval(ConstArrayRef<Value::CREF> params, Stash &stash) const +Map::eval(const LazyParams ¶ms, Stash &stash) const { const Value &a = tensor.get().eval(params, stash); const TensorEngine &engine = infer_engine({a}); @@ -68,7 +68,7 @@ Map::push_children(std::vector<Child::CREF> &children) const //----------------------------------------------------------------------------- const Value & -Join::eval(ConstArrayRef<Value::CREF> params, Stash &stash) const +Join::eval(const LazyParams ¶ms, Stash &stash) const { const Value &a = lhs_tensor.get().eval(params, stash); const Value &b = rhs_tensor.get().eval(params, stash); diff --git a/eval/src/vespa/eval/eval/tensor_function.h b/eval/src/vespa/eval/eval/tensor_function.h index 4b0db486971..f2075e5d4ea 100644 --- a/eval/src/vespa/eval/eval/tensor_function.h +++ b/eval/src/vespa/eval/eval/tensor_function.h @@ -6,6 +6,7 @@ #include <vector> #include <vespa/vespalib/stllike/string.h> #include <vespa/vespalib/util/arrayref.h> +#include "lazy_params.h" #include "value_type.h" #include "value.h" #include "aggr.h" @@ -41,7 +42,7 @@ struct TensorFunction * @param params external values needed to evaluate this function * @param stash heterogeneous object store **/ - virtual const Value &eval(ConstArrayRef<Value::CREF> params, Stash &stash) const = 0; + virtual const Value &eval(const LazyParams ¶ms, Stash &stash) const = 0; virtual ~TensorFunction() {} }; @@ -107,7 +108,7 @@ struct Inject : Node { Inject(const ValueType &result_type_in, size_t tensor_id_in) : Node(result_type_in), tensor_id(tensor_id_in) {} - const Value &eval(ConstArrayRef<Value::CREF> params, Stash &) const override; + const Value &eval(const LazyParams ¶ms, Stash &) const override; void push_children(std::vector<Child::CREF> &children) const override; }; @@ -120,7 +121,7 @@ struct Reduce : Node { Aggr aggr_in, const std::vector<vespalib::string> &dimensions_in) : Node(result_type_in), tensor(tensor_in), aggr(aggr_in), dimensions(dimensions_in) {} - const Value &eval(ConstArrayRef<Value::CREF> params, Stash &stash) const override; + const Value &eval(const LazyParams ¶ms, Stash &stash) const override; void push_children(std::vector<Child::CREF> &children) const override; }; @@ -131,7 +132,7 @@ struct Map : Node { const TensorFunction &tensor_in, map_fun_t function_in) : Node(result_type_in), tensor(tensor_in), function(function_in) {} - const Value &eval(ConstArrayRef<Value::CREF> params, Stash &stash) const override; + const Value &eval(const LazyParams ¶ms, Stash &stash) const override; void push_children(std::vector<Child::CREF> &children) const override; }; @@ -145,7 +146,7 @@ struct Join : Node { join_fun_t function_in) : Node(result_type_in), lhs_tensor(lhs_tensor_in), rhs_tensor(rhs_tensor_in), function(function_in) {} - const Value &eval(ConstArrayRef<Value::CREF> params, Stash &stash) const override; + const Value &eval(const LazyParams ¶ms, Stash &stash) const override; void push_children(std::vector<Child::CREF> &children) const override; }; diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp index 23562f4a186..05acc0912ef 100644 --- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp +++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp @@ -123,7 +123,7 @@ struct Expr_V : Eval { NodeTypes types(fun, {}); InterpretedFunction ifun(engine, fun, types); InterpretedFunction::Context ctx(ifun); - InterpretedFunction::SimpleObjectParams params({}); + SimpleObjectParams params({}); return Result(engine, check_type(ifun.eval(ctx, params), types.get_type(fun.root()))); } }; @@ -139,7 +139,7 @@ struct Expr_T : Eval { InterpretedFunction ifun(engine, fun, types); InterpretedFunction::Context ctx(ifun); Value::UP va = engine.from_spec(a); - InterpretedFunction::SimpleObjectParams params({*va}); + SimpleObjectParams params({*va}); return Result(engine, check_type(ifun.eval(ctx, params), types.get_type(fun.root()))); } }; @@ -157,7 +157,7 @@ struct Expr_TT : Eval { InterpretedFunction::Context ctx(ifun); Value::UP va = engine.from_spec(a); Value::UP vb = engine.from_spec(b); - InterpretedFunction::SimpleObjectParams params({*va,*vb}); + SimpleObjectParams params({*va,*vb}); return Result(engine, check_type(ifun.eval(ctx, params), types.get_type(fun.root()))); } }; @@ -259,7 +259,9 @@ struct Input { tensors.push_back(std::move(b)); params.emplace_back(*tensors.back()); } - ConstArrayRef<Value::CREF> get() const { return params; } + SimpleObjectParams get() const { + return SimpleObjectParams(params); + } }; // evaluate tensor reduce operation using tensor engine retained api 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 fdd0cd6638f..de9963a0c9a 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 @@ -29,10 +29,10 @@ getCellsRef(const eval::Value &value) } const eval::Value & -DenseDotProductFunction::eval(ConstArrayRef<eval::Value::CREF> params, Stash &stash) const +DenseDotProductFunction::eval(const eval::LazyParams ¶ms, Stash &stash) const { - DenseTensorView::CellsRef lhsCells = getCellsRef(params[_lhsTensorId]); - DenseTensorView::CellsRef rhsCells = getCellsRef(params[_rhsTensorId]); + DenseTensorView::CellsRef lhsCells = getCellsRef(params.resolve(_lhsTensorId, stash)); + DenseTensorView::CellsRef rhsCells = getCellsRef(params.resolve(_rhsTensorId, stash)); size_t numCells = std::min(lhsCells.size(), rhsCells.size()); double result = _hwAccelerator->dotProduct(lhsCells.cbegin(), rhsCells.cbegin(), numCells); return stash.create<eval::DoubleValue>(result); 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 288f2afd084..20c293444f3 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 @@ -23,7 +23,7 @@ public: DenseDotProductFunction(size_t lhsTensorId_, size_t rhsTensorId_); size_t lhsTensorId() const { return _lhsTensorId; } size_t rhsTensorId() const { return _rhsTensorId; } - const eval::Value &eval(ConstArrayRef<eval::Value::CREF> params, Stash &stash) const override; + const eval::Value &eval(const eval::LazyParams ¶ms, Stash &stash) const override; }; } 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 1ab78b8ee30..caf8f0de1d7 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 @@ -72,10 +72,10 @@ getCellsRef(const eval::Value &value) } // namespace <unnamed> const eval::Value & -DenseXWProductFunction::eval(ConstArrayRef<eval::Value::CREF> params, Stash &stash) const +DenseXWProductFunction::eval(const eval::LazyParams ¶ms, Stash &stash) const { - DenseTensorView::CellsRef vectorCells = getCellsRef(params[_vectorId]); - DenseTensorView::CellsRef matrixCells = getCellsRef(params[_matrixId]); + DenseTensorView::CellsRef vectorCells = getCellsRef(params.resolve(_vectorId, stash)); + DenseTensorView::CellsRef matrixCells = getCellsRef(params.resolve(_matrixId, stash)); ArrayRef<double> outputCells = stash.create_array<double>(_resultSize); if (_commonDimensionInnermost) { 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 151f1f13800..6e8104fff44 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 @@ -45,7 +45,7 @@ public: bool matrixHasCommonDimensionInnermost() const { return _commonDimensionInnermost; } - const eval::Value &eval(ConstArrayRef<eval::Value::CREF> params, Stash &stash) const override; + const eval::Value &eval(const eval::LazyParams ¶ms, Stash &stash) const override; }; } |