From 926970025dd7c5cd8c2a4cf7ae642653d7bb9440 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 07:05:09 +0000 Subject: add WrappedSimpleValue --- eval/src/vespa/eval/tensor/CMakeLists.txt | 1 + .../src/vespa/eval/tensor/wrapped_simple_value.cpp | 173 +++++++++++++++++++++ eval/src/vespa/eval/tensor/wrapped_simple_value.h | 53 +++++++ 3 files changed, 227 insertions(+) create mode 100644 eval/src/vespa/eval/tensor/wrapped_simple_value.cpp create mode 100644 eval/src/vespa/eval/tensor/wrapped_simple_value.h diff --git a/eval/src/vespa/eval/tensor/CMakeLists.txt b/eval/src/vespa/eval/tensor/CMakeLists.txt index b75b34098f5..77ae1daec88 100644 --- a/eval/src/vespa/eval/tensor/CMakeLists.txt +++ b/eval/src/vespa/eval/tensor/CMakeLists.txt @@ -7,4 +7,5 @@ vespa_add_library(eval_tensor OBJECT tensor.cpp tensor_address.cpp wrapped_simple_tensor.cpp + wrapped_simple_value.cpp ) diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp b/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp new file mode 100644 index 00000000000..ca386ee9611 --- /dev/null +++ b/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp @@ -0,0 +1,173 @@ + +#include "wrapped_simple_value.h" +#include "cell_values.h" +#include "tensor_address_builder.h" +#include "tensor_visitor.h" +#include +#include +#include +#include +#include + +#include +LOG_SETUP(".eval.tensor.wrapped_simple_value"); + +using vespalib::eval::TensorSpec; +using vespalib::eval::SimpleValueBuilderFactory; + +namespace vespalib::tensor { + +namespace { + +TensorSpec::Address +sparsify_address(const TensorSpec::Address &address) +{ + TensorSpec::Address result; + for (const auto &elem : address) { + if (elem.second.is_indexed()) { + auto val = vespalib::make_string("%zu", elem.second.index); + result.emplace(elem.first, TensorSpec::Label(val)); + } else { + result.emplace(elem); + } + } + return result; +} + +TensorSpec::Address +extract_sparse_address(const TensorSpec::Address &address) +{ + TensorSpec::Address result; + for (const auto &elem : address) { + if (elem.second.is_mapped()) { + result.emplace(elem); + } + } + return result; +} + +Tensor::UP wrap(eval::Value::UP value) { + return std::make_unique(std::move(value)); +} + +} // namespace + + +eval::TensorSpec +WrappedSimpleValue::toSpec() const +{ + return spec_from_value(_tensor); +} + +void +WrappedSimpleValue::accept(TensorVisitor &visitor) const +{ + TensorSpec myspec = toSpec(); + TensorAddressBuilder addr; + for (const auto & cell : myspec.cells()) { + auto sparse_addr = sparsify_address(cell.first); + addr.clear(); + for (const auto & dim_and_label : sparse_addr) { + addr.add(dim_and_label.first, dim_and_label.second.name); + } + visitor.visit(addr.build(), cell.second); + } +} + +MemoryUsage +WrappedSimpleValue::get_memory_usage() const +{ + MemoryUsage rv = eval::self_memory_usage(); + if (_space) { + rv.merge(_space->get_memory_usage()); + } + return rv; +} + +//----------------------------------------------------------------------------- + +Tensor::UP +WrappedSimpleValue::apply(const CellFunction &) const +{ + LOG_ABORT("should not be reached"); +} + +Tensor::UP +WrappedSimpleValue::join(join_fun_t, const Tensor &) const +{ + LOG_ABORT("should not be reached"); +} + +Tensor::UP +WrappedSimpleValue::merge(join_fun_t, const Tensor &) const +{ + LOG_ABORT("should not be reached"); +} + +Tensor::UP +WrappedSimpleValue::reduce(join_fun_t, const std::vector &) const +{ + LOG_ABORT("should not be reached"); +} + +Tensor::UP +WrappedSimpleValue::modify(join_fun_t fun, const CellValues &cellValues) const +{ + TensorSpec a = toSpec(); + TensorSpec b = cellValues.toSpec(); + TensorSpec result(a.type()); + auto end_iter = b.cells().end(); + for (const auto &cell: a.cells()) { + double v = cell.second; + auto sparse_addr = sparsify_address(cell.first); + auto iter = b.cells().find(sparse_addr); + if (iter == end_iter) { + result.add(cell.first, v); + } else { + result.add(cell.first, fun(v, iter->second)); + } + } + return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); +} + +Tensor::UP +WrappedSimpleValue::add(const Tensor &rhs) const +{ + TensorSpec a = toSpec(); + TensorSpec b = rhs.toSpec(); + if (a.type() != b.type()) { + return {}; + } + TensorSpec result(a.type()); + for (const auto &cell: b.cells()) { + result.add(cell.first, cell.second); + } + auto end_iter = b.cells().end(); + for (const auto &cell: a.cells()) { + auto iter = b.cells().find(cell.first); + if (iter == end_iter) { + result.add(cell.first, cell.second); + } + } + return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); +} + + +Tensor::UP +WrappedSimpleValue::remove(const CellValues &rhs) const +{ + TensorSpec a = toSpec(); + TensorSpec b = rhs.toSpec(); + TensorSpec result(a.type()); + auto end_iter = b.cells().end(); + for (const auto &cell: a.cells()) { + TensorSpec::Address mappedAddress = extract_sparse_address(cell.first); + auto iter = b.cells().find(mappedAddress); + if (iter == end_iter) { + result.add(cell.first, cell.second); + } + } + return wrap(value_from_spec(result, SimpleValueBuilderFactory::get())); +} + +} diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.h b/eval/src/vespa/eval/tensor/wrapped_simple_value.h new file mode 100644 index 00000000000..68339790436 --- /dev/null +++ b/eval/src/vespa/eval/tensor/wrapped_simple_value.h @@ -0,0 +1,53 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "tensor.h" +#include +#include + +namespace vespalib::tensor { + +/** + * A thin wrapper around a SimpleValue to be used as fallback for tensors with data + * layouts not supported by the default tensor implementation. + * + * Tensor implementation class is currently inferred from its value + * type. Consider adding explicit tagging to the tensor::Tensor + * default implementation top-level class in the future. + **/ +class WrappedSimpleValue : public Tensor +{ +private: + std::unique_ptr _space; + const eval::Value &_tensor; +public: + explicit WrappedSimpleValue(const eval::Value &tensor) + : _space(), _tensor(tensor) {} + explicit WrappedSimpleValue(std::unique_ptr tensor) + : _space(std::move(tensor)), _tensor(*_space) {} + ~WrappedSimpleValue() {} + const eval::Value &unwrap() const { return _tensor; } + + // Value API + const eval::ValueType &type() const override { return _tensor.type(); } + eval::TypedCells cells() const override { return _tensor.cells(); } + const Index &index() const override { return _tensor.index(); } + double as_double() const override { return _tensor.as_double(); } + + // tensor API + eval::TensorSpec toSpec() const override; + void accept(TensorVisitor &visitor) const override; + MemoryUsage get_memory_usage() const override; + + Tensor::UP join(join_fun_t fun, const Tensor &rhs) const override; + Tensor::UP merge(join_fun_t fun, const Tensor &rhs) const override; + Tensor::UP reduce(join_fun_t fun, const std::vector &dims) const override; + + Tensor::UP apply(const CellFunction & func) const override; + Tensor::UP modify(join_fun_t fun, const CellValues &cellValues) const override; + Tensor::UP add(const Tensor &rhs) const override; + Tensor::UP remove(const CellValues &rhs) const override; +}; + +} // namespace vespalib::tensor -- cgit v1.2.3 From 0391088a6ae0b0d3e11a634088141a4bdd3fe660 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 07:06:39 +0000 Subject: add "immediate" forms for generic operations (temporary fallback) --- eval/src/vespa/eval/instruction/generic_concat.cpp | 43 ++++++++++++++++------ eval/src/vespa/eval/instruction/generic_concat.h | 5 +++ eval/src/vespa/eval/instruction/generic_join.cpp | 39 +++++++++++++++++--- eval/src/vespa/eval/instruction/generic_join.h | 7 +++- eval/src/vespa/eval/instruction/generic_map.cpp | 38 +++++++++++++++++++ eval/src/vespa/eval/instruction/generic_map.h | 4 ++ eval/src/vespa/eval/instruction/generic_merge.cpp | 21 +++++++++++ eval/src/vespa/eval/instruction/generic_merge.h | 7 +++- eval/src/vespa/eval/instruction/generic_reduce.cpp | 34 +++++++++++++++-- eval/src/vespa/eval/instruction/generic_reduce.h | 22 +++++++---- eval/src/vespa/eval/instruction/generic_rename.cpp | 22 +++++++++++ eval/src/vespa/eval/instruction/generic_rename.h | 6 +++ 12 files changed, 218 insertions(+), 30 deletions(-) diff --git a/eval/src/vespa/eval/instruction/generic_concat.cpp b/eval/src/vespa/eval/instruction/generic_concat.cpp index cb8b5ee3b2f..eaa2dbf95ae 100644 --- a/eval/src/vespa/eval/instruction/generic_concat.cpp +++ b/eval/src/vespa/eval/instruction/generic_concat.cpp @@ -121,6 +121,15 @@ struct SelectGenericConcatOp { } }; +struct PerformGenericConcat { + template + static auto invoke(const Value &a, const Value &b, const ConcatParam ¶m) { + return generic_concat(a, b, + param.sparse_plan, param.dense_plan, + param.res_type, param.factory); + } +}; + enum class Case { NONE, OUT, CONCAT, BOTH }; } // namespace @@ -183,6 +192,21 @@ DenseConcatPlan::InOutLoop::fill_from(const ValueType &in_type, return std::make_pair(offset_for_concat, output_size_for_concat); } +DenseConcatPlan::DenseConcatPlan(const ValueType &lhs_type, + const ValueType &rhs_type, + std::string concat_dimension, + const ValueType &out_type) +{ + std::tie(right_offset, output_size) = left.fill_from(lhs_type, concat_dimension, out_type); + auto [ other_offset, other_size ] = right.fill_from(rhs_type, concat_dimension, out_type); + assert(other_offset > 0); + assert(output_size == other_size); +} + +DenseConcatPlan::~DenseConcatPlan() = default; +DenseConcatPlan::InOutLoop::~InOutLoop() = default; + + InterpretedFunction::Instruction GenericConcat::make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, const vespalib::string &dimension, @@ -195,18 +219,15 @@ GenericConcat::make_instruction(const ValueType &lhs_type, const ValueType &rhs_ return Instruction(fun, wrap_param(param)); } -DenseConcatPlan::DenseConcatPlan(const ValueType &lhs_type, - const ValueType &rhs_type, - std::string concat_dimension, - const ValueType &out_type) +Value::UP +GenericConcat::perform_concat(const Value &a, const Value &b, + const vespalib::string &dimension, + const ValueBuilderFactory &factory) { - std::tie(right_offset, output_size) = left.fill_from(lhs_type, concat_dimension, out_type); - auto [ other_offset, other_size ] = right.fill_from(rhs_type, concat_dimension, out_type); - assert(other_offset > 0); - assert(output_size == other_size); + ConcatParam param(a.type(), b.type(), dimension, factory); + return typify_invoke<3,TypifyCellType,PerformGenericConcat>( + a.type().cell_type(), b.type().cell_type(), param.res_type.cell_type(), + a, b, param); } -DenseConcatPlan::~DenseConcatPlan() = default; -DenseConcatPlan::InOutLoop::~InOutLoop() = default; - } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_concat.h b/eval/src/vespa/eval/instruction/generic_concat.h index 5578c5a0dca..d41d161900a 100644 --- a/eval/src/vespa/eval/instruction/generic_concat.h +++ b/eval/src/vespa/eval/instruction/generic_concat.h @@ -17,6 +17,11 @@ struct GenericConcat { make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, const vespalib::string &dimension, const ValueBuilderFactory &factory, Stash &stash); + + static Value::UP + perform_concat(const Value &a, const Value &b, + const vespalib::string &dimension, + const ValueBuilderFactory &factory); }; struct DenseConcatPlan { diff --git a/eval/src/vespa/eval/instruction/generic_join.cpp b/eval/src/vespa/eval/instruction/generic_join.cpp index 83c50fdc0a2..c7bb17a808e 100644 --- a/eval/src/vespa/eval/instruction/generic_join.cpp +++ b/eval/src/vespa/eval/instruction/generic_join.cpp @@ -24,8 +24,9 @@ namespace { //----------------------------------------------------------------------------- template -void my_mixed_join_op(State &state, uint64_t param_in) { - const auto ¶m = unwrap_param(param_in); +Value::UP +generic_mixed_join(const Value &lhs, const Value &rhs, const JoinParam ¶m) +{ Fun fun(param.function); auto dense_join = [&](const LCT *my_lhs, const RCT *my_rhs, OCT *my_res) { @@ -33,8 +34,6 @@ void my_mixed_join_op(State &state, uint64_t param_in) { *my_res++ = fun(my_lhs[lhs_idx], my_rhs[rhs_idx]); }); }; - const Value &lhs = state.peek(1); - const Value &rhs = state.peek(0); auto lhs_cells = lhs.cells().typify(); auto rhs_cells = rhs.cells().typify(); SparseJoinState sparse(param.sparse_plan, lhs.index(), rhs.index()); @@ -50,7 +49,16 @@ void my_mixed_join_op(State &state, uint64_t param_in) { builder->add_subspace(sparse.full_address).begin()); } } - auto &result = state.stash.create>(builder->build(std::move(builder))); + return builder->build(std::move(builder)); +}; + +template +void my_mixed_join_op(State &state, uint64_t param_in) { + const auto ¶m = unwrap_param(param_in); + const Value &lhs = state.peek(1); + const Value &rhs = state.peek(0); + auto up = generic_mixed_join(lhs, rhs, param); + auto &result = state.stash.create>(std::move(up)); const Value &result_ref = *(result.get()); state.pop_pop_push(result_ref); }; @@ -141,6 +149,16 @@ struct SelectGenericJoinOp { } }; +struct PerformGenericJoin { + template + static auto invoke(const Value &a, const Value &b, const JoinParam ¶m) + { + return generic_mixed_join(a, b, param); + } +}; + + + //----------------------------------------------------------------------------- } // namespace @@ -263,4 +281,15 @@ GenericJoin::make_instruction(const ValueType &lhs_type, const ValueType &rhs_ty return Instruction(fun, wrap_param(param)); } + +Value::UP +GenericJoin::perform_join(const Value &a, const Value &b, join_fun_t function, + const ValueBuilderFactory &factory) +{ + JoinParam param(a.type(), b.type(), function, factory); + return typify_invoke<4,JoinTypify,PerformGenericJoin>( + a.type().cell_type(), b.type().cell_type(), param.res_type.cell_type(), function, + a, b, param); +} + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_join.h b/eval/src/vespa/eval/instruction/generic_join.h index 3b1b4433032..49cdb3499a9 100644 --- a/eval/src/vespa/eval/instruction/generic_join.h +++ b/eval/src/vespa/eval/instruction/generic_join.h @@ -18,8 +18,13 @@ using join_fun_t = vespalib::eval::operation::op2_t; struct GenericJoin { static InterpretedFunction::Instruction - make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, join_fun_t function, + make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, + join_fun_t function, const ValueBuilderFactory &factory, Stash &stash); + + static Value::UP + perform_join(const Value &a, const Value &b, join_fun_t function, + const ValueBuilderFactory &factory); }; //----------------------------------------------------------------------------- diff --git a/eval/src/vespa/eval/instruction/generic_map.cpp b/eval/src/vespa/eval/instruction/generic_map.cpp index 7ead705328a..689339af5b3 100644 --- a/eval/src/vespa/eval/instruction/generic_map.cpp +++ b/eval/src/vespa/eval/instruction/generic_map.cpp @@ -38,6 +38,36 @@ struct SelectGenericMapOp { } }; +struct PerformGenericMap { + template + static auto invoke(const Value &input, map_fun_t function_in, + const ValueBuilderFactory &factory) + { + Func fun(function_in); + const auto &type = input.type(); + size_t subspace_size = type.dense_subspace_size(); + size_t num_mapped = type.count_mapped_dimensions(); + auto builder = factory.create_value_builder(type, num_mapped, subspace_size, input.index().size()); + auto input_cells = input.cells().typify(); + auto view = input.index().create_view({}); + std::vector output_address(num_mapped); + std::vector input_address; + for (auto & label : output_address) { + input_address.push_back(&label); + } + view->lookup({}); + size_t subspace; + while (view->next_result(input_address, subspace)) { + auto dst = builder->add_subspace(output_address); + size_t input_offset = subspace_size * subspace; + for (size_t i = 0; i < subspace_size; ++i) { + dst[i] = fun(input_cells[input_offset + i]); + } + } + return builder->build(std::move(builder)); + } +}; + } // namespace using MapTypify = TypifyValue; @@ -49,4 +79,12 @@ GenericMap::make_instruction(const ValueType &lhs_type, map_fun_t function) return Instruction(op, to_param(function)); } +Value::UP +GenericMap::perform_map(const Value &a, map_fun_t function, + const ValueBuilderFactory &factory) +{ + return typify_invoke<2,MapTypify,PerformGenericMap>(a.type().cell_type(), function, + a, function, factory); +} + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_map.h b/eval/src/vespa/eval/instruction/generic_map.h index ad29d2c1073..9c8fb17c153 100644 --- a/eval/src/vespa/eval/instruction/generic_map.h +++ b/eval/src/vespa/eval/instruction/generic_map.h @@ -15,6 +15,10 @@ using map_fun_t = vespalib::eval::operation::op1_t; struct GenericMap { static InterpretedFunction::Instruction make_instruction(const ValueType &input_type, map_fun_t function); + + static Value::UP + perform_map(const Value &a, map_fun_t function, + const ValueBuilderFactory &factory); }; } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_merge.cpp b/eval/src/vespa/eval/instruction/generic_merge.cpp index f54ae651374..51c9dcdbb15 100644 --- a/eval/src/vespa/eval/instruction/generic_merge.cpp +++ b/eval/src/vespa/eval/instruction/generic_merge.cpp @@ -122,6 +122,13 @@ struct SelectGenericMergeOp { } }; +struct PerformGenericMerge { + template + static auto invoke(const Value &a, const Value &b, const MergeParam ¶m) { + return generic_mixed_merge(a, b, param); + } +}; + //----------------------------------------------------------------------------- } // namespace @@ -137,4 +144,18 @@ GenericMerge::make_instruction(const ValueType &lhs_type, const ValueType &rhs_t return Instruction(fun, wrap_param(param)); } + +Value::UP +GenericMerge::perform_merge(const Value &a, const Value &b, join_fun_t function, + const ValueBuilderFactory &factory) +{ + MergeParam param(a.type(), b.type(), function, factory); + return typify_invoke<4,MergeTypify,PerformGenericMerge>( + a.type().cell_type(), + b.type().cell_type(), + param.res_type.cell_type(), function, + a, b, param); +} + + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_merge.h b/eval/src/vespa/eval/instruction/generic_merge.h index 02e2d18715a..e9ffcc87997 100644 --- a/eval/src/vespa/eval/instruction/generic_merge.h +++ b/eval/src/vespa/eval/instruction/generic_merge.h @@ -8,8 +8,13 @@ namespace vespalib::eval::instruction { struct GenericMerge { static InterpretedFunction::Instruction - make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, join_fun_t function, + make_instruction(const ValueType &lhs_type, const ValueType &rhs_type, + join_fun_t function, const ValueBuilderFactory &factory, Stash &stash); + + static Value::UP + perform_merge(const Value &a, const Value &b, join_fun_t function, + const ValueBuilderFactory &factory); }; } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_reduce.cpp b/eval/src/vespa/eval/instruction/generic_reduce.cpp index a76ee322759..305f51ea445 100644 --- a/eval/src/vespa/eval/instruction/generic_reduce.cpp +++ b/eval/src/vespa/eval/instruction/generic_reduce.cpp @@ -94,10 +94,9 @@ struct SparseReduceState { SparseReduceState::~SparseReduceState() = default; template -void my_generic_reduce_op(State &state, uint64_t param_in) { - const auto ¶m = unwrap_param(param_in); +Value::UP +generic_reduce(const Value &value, const ReduceParam ¶m) { SparseReduceState sparse(param.sparse_plan); - const Value &value = state.peek(0); sparse.populate_map(value.index().create_view({})); auto cells = value.cells().typify(); AGGR aggr; @@ -123,7 +122,15 @@ void my_generic_reduce_op(State &state, uint64_t param_in) { zero[i] = OCT{}; } } - auto &result = state.stash.create>(builder->build(std::move(builder))); + return builder->build(std::move(builder)); +} + +template +void my_generic_reduce_op(State &state, uint64_t param_in) { + const auto ¶m = unwrap_param(param_in); + const Value &value = state.peek(0); + auto up = generic_reduce(value, param); + auto &result = state.stash.create>(std::move(up)); const Value &result_ref = *(result.get()); state.pop_push(result_ref); }; @@ -134,6 +141,13 @@ struct SelectGenericReduceOp { } }; +struct PerformGenericReduce { + template + static auto invoke(const Value &input, const ReduceParam ¶m) { + return generic_reduce>(input, param); + } +}; + //----------------------------------------------------------------------------- } // namespace @@ -213,4 +227,16 @@ GenericReduce::make_instruction(const ValueType &type, Aggr aggr, const std::vec return Instruction(fun, wrap_param(param)); } + +Value::UP +GenericReduce::perform_reduce(const Value &a, Aggr aggr, + const std::vector &dimensions, + const ValueBuilderFactory &factory) +{ + ReduceParam param(a.type(), dimensions, factory); + return typify_invoke<3,ReduceTypify,PerformGenericReduce>( + a.type().cell_type(), param.res_type.cell_type(), aggr, + a, param); +} + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_reduce.h b/eval/src/vespa/eval/instruction/generic_reduce.h index e412f8795ac..856cfe362ae 100644 --- a/eval/src/vespa/eval/instruction/generic_reduce.h +++ b/eval/src/vespa/eval/instruction/generic_reduce.h @@ -14,14 +14,6 @@ namespace vespalib::eval::instruction { //----------------------------------------------------------------------------- -struct GenericReduce { - static InterpretedFunction::Instruction - make_instruction(const ValueType &type, Aggr aggr, const std::vector &dimensions, - const ValueBuilderFactory &factory, Stash &stash); -}; - -//----------------------------------------------------------------------------- - struct DenseReducePlan { size_t in_size; size_t out_size; @@ -51,4 +43,18 @@ struct SparseReducePlan { //----------------------------------------------------------------------------- +struct GenericReduce { + static InterpretedFunction::Instruction + make_instruction(const ValueType &type, Aggr aggr, + const std::vector &dimensions, + const ValueBuilderFactory &factory, Stash &stash); + + static Value::UP + perform_reduce(const Value &a, Aggr aggr, + const std::vector &dimensions, + const ValueBuilderFactory &factory); +}; + +//----------------------------------------------------------------------------- + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_rename.cpp b/eval/src/vespa/eval/instruction/generic_rename.cpp index 1ce18597ec2..3d8de356001 100644 --- a/eval/src/vespa/eval/instruction/generic_rename.cpp +++ b/eval/src/vespa/eval/instruction/generic_rename.cpp @@ -107,6 +107,14 @@ struct SelectGenericRenameOp { } }; +struct PerformGenericRename { + template + static auto invoke(const Value &a, const RenameParam ¶m) { + return generic_rename(a, param.sparse_plan, param.dense_plan, + param.res_type, param.factory); + } +}; + } // namespace //----------------------------------------------------------------------------- @@ -186,5 +194,19 @@ GenericRename::make_instruction(const ValueType &lhs_type, return Instruction(fun, wrap_param(param)); } + +Value::UP +GenericRename::perform_rename(const Value &a, + const std::vector &rename_dimension_from, + const std::vector &rename_dimension_to, + const ValueBuilderFactory &factory) +{ + RenameParam param(a.type(), + rename_dimension_from, rename_dimension_to, + factory); + return typify_invoke<1,TypifyCellType,PerformGenericRename>(a.type().cell_type(), + a, param); +} + } // namespace diff --git a/eval/src/vespa/eval/instruction/generic_rename.h b/eval/src/vespa/eval/instruction/generic_rename.h index 6c94ff02b24..4088e817b90 100644 --- a/eval/src/vespa/eval/instruction/generic_rename.h +++ b/eval/src/vespa/eval/instruction/generic_rename.h @@ -44,6 +44,12 @@ struct GenericRename { const std::vector &rename_dimension_from, const std::vector &rename_dimension_to, const ValueBuilderFactory &factory, Stash &stash); + + static Value::UP + perform_rename(const Value &a, + const std::vector &rename_dimension_from, + const std::vector &rename_dimension_to, + const ValueBuilderFactory &factory); }; } // namespace -- cgit v1.2.3 From 0dd7e0c9bf218006465a4713f0d642f8575e53fd Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 10:55:54 +0000 Subject: test immediate map --- .../instruction/generic_map/generic_map_test.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/eval/src/tests/instruction/generic_map/generic_map_test.cpp b/eval/src/tests/instruction/generic_map/generic_map_test.cpp index 77f5ffc33db..69fb417e0ad 100644 --- a/eval/src/tests/instruction/generic_map/generic_map_test.cpp +++ b/eval/src/tests/instruction/generic_map/generic_map_test.cpp @@ -64,4 +64,24 @@ TEST(GenericMapTest, generic_map_works_for_simple_values) { test_generic_map(SimpleValueBuilderFactory::get()); } +TensorSpec immediate_generic_map(const TensorSpec &a, map_fun_t func, const ValueBuilderFactory &factory) +{ + auto lhs = value_from_spec(a, factory); + auto up = GenericMap::perform_map(*lhs, func, factory); + return spec_from_value(*up); +} + +TEST(GenericMapTest, immediate_generic_map_works) { + for (const auto & layout : map_layouts) { + TensorSpec lhs = spec(layout, Div16(N())); + ValueType lhs_type = ValueType::from_spec(lhs.type()); + for (auto func : {operation::Floor::f, operation::Fabs::f, operation::Square::f, operation::Inv::f}) { + SCOPED_TRACE(fmt("\n===\nLHS: %s\n===\n", lhs.to_string().c_str())); + auto expect = reference_map(lhs, func); + auto actual = immediate_generic_map(lhs, func, SimpleValueBuilderFactory::get()); + EXPECT_EQ(actual, expect); + } + } +} + GTEST_MAIN_RUN_ALL_TESTS() -- cgit v1.2.3 From 7904d8f406805c473b2bf2d324102d1ee4937232 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 10:55:59 +0000 Subject: test immediate forms --- .../generic_concat/generic_concat_test.cpp | 20 +++++++++++++++++ .../instruction/generic_join/generic_join_test.cpp | 22 +++++++++++++++++++ .../generic_merge/generic_merge_test.cpp | 22 +++++++++++++++++++ .../generic_reduce/generic_reduce_test.cpp | 24 +++++++++++++++++++++ .../generic_rename/generic_rename_test.cpp | 25 ++++++++++++++++++++++ 5 files changed, 113 insertions(+) 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 b48c1e2253c..675aa36d63a 100644 --- a/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp +++ b/eval/src/tests/instruction/generic_concat/generic_concat_test.cpp @@ -177,4 +177,24 @@ TEST(GenericConcatTest, dense_concat_plan_can_be_created) { EXPECT_EQ(plan.right.out_stride, expect_right_out_s); } +TensorSpec immediate_generic_concat(const TensorSpec &a, const TensorSpec &b, const std::string &concat_dim) { + const auto &factory = SimpleValueBuilderFactory::get(); + auto lhs = value_from_spec(a, factory); + auto rhs = value_from_spec(b, factory); + auto up = GenericConcat::perform_concat(*lhs, *rhs, concat_dim, factory); + return spec_from_value(*up); +} + +TEST(GenericConcatTest, immediate_generic_concat_works) { + ASSERT_TRUE((concat_layouts.size() % 2) == 0); + for (size_t i = 0; i < concat_layouts.size(); i += 2) { + const TensorSpec lhs = spec(concat_layouts[i], N()); + const TensorSpec rhs = spec(concat_layouts[i + 1], Div16(N())); + SCOPED_TRACE(fmt("\n===\nin LHS: %s\nin RHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); + auto actual = immediate_generic_concat(lhs, rhs, "y"); + auto expect = reference_concat(lhs, rhs, "y"); + EXPECT_EQ(actual, expect); + } +} + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_join/generic_join_test.cpp b/eval/src/tests/instruction/generic_join/generic_join_test.cpp index 82696bbbd5e..cf04b2ca990 100644 --- a/eval/src/tests/instruction/generic_join/generic_join_test.cpp +++ b/eval/src/tests/instruction/generic_join/generic_join_test.cpp @@ -148,4 +148,26 @@ TEST(GenericJoinTest, generic_join_works_for_simple_and_fast_values) { } } +TensorSpec immediate_generic_join(const TensorSpec &a, const TensorSpec &b, join_fun_t function) { + const auto &factory = SimpleValueBuilderFactory::get(); + auto lhs = value_from_spec(a, factory); + auto rhs = value_from_spec(b, factory); + auto up = GenericJoin::perform_join(*lhs, *rhs, function, factory); + return spec_from_value(*up); +} + +TEST(GenericJoinTest, immediate_generic_join_works) { + ASSERT_TRUE((join_layouts.size() % 2) == 0); + for (size_t i = 0; i < join_layouts.size(); i += 2) { + TensorSpec lhs = spec(join_layouts[i], Div16(N())); + TensorSpec rhs = spec(join_layouts[i + 1], Div16(N())); + for (auto fun: {operation::Add::f, operation::Sub::f, operation::Mul::f, operation::Div::f}) { + SCOPED_TRACE(fmt("\n===\nLHS: %s\nRHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); + auto expect = reference_join(lhs, rhs, fun); + auto actual = immediate_generic_join(lhs, rhs, fun); + EXPECT_EQ(actual, expect); + } + } +} + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp index ae2e100176b..fd9b8513acb 100644 --- a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp +++ b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp @@ -79,4 +79,26 @@ TEST(GenericMergeTest, generic_merge_works_for_simple_values) { } } +TensorSpec immediate_generic_merge(const TensorSpec &a, const TensorSpec &b, join_fun_t fun) { + const auto &factory = SimpleValueBuilderFactory::get(); + auto lhs = value_from_spec(a, factory); + auto rhs = value_from_spec(b, factory); + auto up = GenericMerge::perform_merge(*lhs, *rhs, fun, factory); + return spec_from_value(*up); +} + +TEST(GenericMergeTest, immediate_generic_merge_works) { + ASSERT_TRUE((merge_layouts.size() % 2) == 0); + for (size_t i = 0; i < merge_layouts.size(); i += 2) { + TensorSpec lhs = spec(merge_layouts[i], N()); + TensorSpec rhs = spec(merge_layouts[i + 1], Div16(N())); + SCOPED_TRACE(fmt("\n===\nLHS: %s\nRHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str())); + for (auto fun: {operation::Add::f, operation::Mul::f, operation::Sub::f, operation::Max::f}) { + auto expect = reference_merge(lhs, rhs, fun); + auto actual = immediate_generic_merge(lhs, rhs, fun); + EXPECT_EQ(actual, expect); + } + } +} + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp b/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp index 1329ad549c5..490055bf02f 100644 --- a/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp +++ b/eval/src/tests/instruction/generic_reduce/generic_reduce_test.cpp @@ -110,4 +110,28 @@ TEST(GenericReduceTest, generic_reduce_works_for_simple_values) { } } +TensorSpec immediate_generic_reduce(const TensorSpec &a, const std::vector &dims, Aggr aggr) { + const auto &factory = SimpleValueBuilderFactory::get(); + auto lhs = value_from_spec(a, factory); + auto up = GenericReduce::perform_reduce(*lhs, aggr, dims, factory); + return spec_from_value(*up); +} + +TEST(GenericReduceTest, immediate_generic_reduce_works) { + for (const Layout &layout: layouts) { + TensorSpec input = spec(layout, Div16(N())); + for (Aggr aggr: {Aggr::SUM, Aggr::AVG, Aggr::MIN, Aggr::MAX}) { + for (const Domain &domain: layout) { + auto expect = reference_reduce(input, {domain.dimension}, aggr); + auto actual = immediate_generic_reduce(input, {domain.dimension}, aggr); + EXPECT_EQ(actual, expect); + } + auto expect = reference_reduce(input, {}, aggr); + auto actual = immediate_generic_reduce(input, {}, aggr); + EXPECT_EQ(actual, expect); + } + } +} + + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp b/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp index 3f151af1fd6..124462f0e0f 100644 --- a/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp +++ b/eval/src/tests/instruction/generic_rename/generic_rename_test.cpp @@ -142,4 +142,29 @@ TEST(GenericRenameTest, generic_rename_works_for_simple_values) { test_generic_rename(SimpleValueBuilderFactory::get()); } +TensorSpec immediate_generic_rename(const TensorSpec &a, const FromTo &ft) +{ + auto &factory = SimpleValueBuilderFactory::get(); + auto lhs = value_from_spec(a, factory); + auto up = GenericRename::perform_rename(*lhs, ft.from, ft.to, factory); + return spec_from_value(*up); +} + +TEST(GenericRenameTest, immediate_generic_rename_works) { + for (const auto & layout : rename_layouts) { + TensorSpec lhs = spec(layout, N()); + ValueType lhs_type = ValueType::from_spec(lhs.type()); + // printf("lhs_type: %s\n", lhs_type.to_spec().c_str()); + for (const auto & from_to : rename_from_to) { + ValueType renamed_type = lhs_type.rename(from_to.from, from_to.to); + if (renamed_type.is_error()) continue; + // printf("type %s -> %s\n", lhs_type.to_spec().c_str(), renamed_type.to_spec().c_str()); + SCOPED_TRACE(fmt("\n===\nLHS: %s\n===\n", lhs.to_string().c_str())); + auto expect = reference_rename(lhs, from_to); + auto actual = immediate_generic_rename(lhs, from_to); + EXPECT_EQ(actual, expect); + } + } +} + GTEST_MAIN_RUN_ALL_TESTS() -- cgit v1.2.3 From 90bd4752ff2aab692415a5ede4661e708307c679 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 11:28:05 +0000 Subject: test immediate operations in conformance test --- eval/src/vespa/eval/eval/engine_or_factory.cpp | 45 +++++++++++++++++++--- .../vespa/eval/eval/test/tensor_conformance.cpp | 28 ++++---------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/eval/src/vespa/eval/eval/engine_or_factory.cpp b/eval/src/vespa/eval/eval/engine_or_factory.cpp index 2a3ba2e543f..e4f710be625 100644 --- a/eval/src/vespa/eval/eval/engine_or_factory.cpp +++ b/eval/src/vespa/eval/eval/engine_or_factory.cpp @@ -5,16 +5,25 @@ #include "simple_value.h" #include "value_codec.h" #include "simple_tensor_engine.h" +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include +#include #include using vespalib::make_string_short::fmt; +using namespace vespalib::eval::instruction; + namespace vespalib::eval { EngineOrFactory EngineOrFactory::_default{tensor::DefaultTensorEngine::ref()}; @@ -88,32 +97,56 @@ EngineOrFactory::copy(const Value &value) const Value & EngineOrFactory::map(const Value &a, operation::op1_t function, Stash &stash) const { - return engine().map(a, function, stash); + if (is_engine()) { + return engine().map(a, function, stash); + } else { + return *stash.create(GenericMap::perform_map(a, function, factory())); + } } const Value & EngineOrFactory::join(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { - return engine().join(a, b, function, stash); + if (is_engine()) { + return engine().join(a, b, function, stash); + } else { + return *stash.create(GenericJoin::perform_join(a, b, function, factory())); + } } const Value & EngineOrFactory::merge(const Value &a, const Value &b, operation::op2_t function, Stash &stash) const { - return engine().merge(a, b, function, stash); + if (is_engine()) { + return engine().merge(a, b, function, stash); + } else { + return *stash.create(GenericMerge::perform_merge(a, b, function, factory())); + } } const Value & EngineOrFactory::reduce(const Value &a, Aggr aggr, const std::vector &dimensions, Stash &stash) const { - return engine().reduce(a, aggr, dimensions, stash); + if (is_engine()) { + return engine().reduce(a, aggr, dimensions, stash); + } else { + return *stash.create(GenericReduce::perform_reduce(a, aggr, dimensions, factory())); + } } const Value & EngineOrFactory::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const { - return engine().concat(a, b, dimension, stash); + if (is_engine()) { + return engine().concat(a, b, dimension, stash); + } else { + return *stash.create(GenericConcat::perform_concat(a, b, dimension, factory())); + } } const Value & EngineOrFactory::rename(const Value &a, const std::vector &from, const std::vector &to, Stash &stash) const { - return engine().rename(a, from, to, stash); + if (is_engine()) { + return engine().rename(a, from, to, stash); + } else { + return *stash.create(GenericRename::perform_rename(a, from, to, factory())); + } } void diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp index c6f73d611cc..0e703e81073 100644 --- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp +++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp @@ -339,9 +339,7 @@ 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)); - if (engine.is_engine()) { - TEST_DO(verify_reduce_result(ImmediateReduce(aggr, domain.dimension), input, expect)); - } + TEST_DO(verify_reduce_result(ImmediateReduce(aggr, domain.dimension), input, expect)); } { Eval::Result expect = ImmediateReduce(aggr).eval(ref_engine, input); @@ -349,9 +347,7 @@ 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)); - if (engine.is_engine()) { - TEST_DO(verify_reduce_result(ImmediateReduce(aggr), input, expect)); - } + TEST_DO(verify_reduce_result(ImmediateReduce(aggr), input, expect)); } } } @@ -388,9 +384,7 @@ struct TestContext { } void test_map_op(const vespalib::string &expr, map_fun_t op, const Sequence &seq) { - if (engine.is_engine()) { - TEST_DO(test_map_op(ImmediateMap(op), op, seq)); - } + 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)); } @@ -667,9 +661,7 @@ struct TestContext { } void test_apply_op(const vespalib::string &expr, join_fun_t op, const Sequence &seq) { - if (engine.is_engine()) { - TEST_DO(test_apply_op(ImmediateJoin(op), op, seq)); - } + 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)); } @@ -732,10 +724,8 @@ struct TestContext { const TensorSpec &expect) { vespalib::string expr = make_string("concat(a,b,%s)", dimension.c_str()); - if (engine.is_engine()) { - ImmediateConcat eval(dimension); - TEST_DO(verify_result(eval.eval(engine, a, b), expect)); - } + 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)); } @@ -773,10 +763,8 @@ struct TestContext { const std::vector &to, const TensorSpec &expect) { - if (engine.is_engine()) { - ImmediateRename eval(from, to); - TEST_DO(verify_result(eval.eval(engine, input), expect)); - } + ImmediateRename eval(from, to); + TEST_DO(verify_result(eval.eval(engine, input), expect)); TEST_DO(verify_result(Expr_T(expr).eval(engine, input), expect)); } -- cgit v1.2.3 From b169f9da0116fa7f2bbcada2411c942fe7fa7052 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 09:52:32 +0000 Subject: add SimpleValueEngine (temporary fallback) --- eval/src/vespa/eval/eval/CMakeLists.txt | 1 + eval/src/vespa/eval/eval/simple_value_engine.cpp | 97 ++++++++++++++++++++++++ eval/src/vespa/eval/eval/simple_value_engine.h | 37 +++++++++ 3 files changed, 135 insertions(+) create mode 100644 eval/src/vespa/eval/eval/simple_value_engine.cpp create mode 100644 eval/src/vespa/eval/eval/simple_value_engine.h diff --git a/eval/src/vespa/eval/eval/CMakeLists.txt b/eval/src/vespa/eval/eval/CMakeLists.txt index 5a60adfb58b..8de7f75226f 100644 --- a/eval/src/vespa/eval/eval/CMakeLists.txt +++ b/eval/src/vespa/eval/eval/CMakeLists.txt @@ -25,6 +25,7 @@ vespa_add_library(eval_eval OBJECT simple_tensor.cpp simple_tensor_engine.cpp simple_value.cpp + simple_value_engine.cpp string_stuff.cpp tensor.cpp tensor_engine.cpp diff --git a/eval/src/vespa/eval/eval/simple_value_engine.cpp b/eval/src/vespa/eval/eval/simple_value_engine.cpp new file mode 100644 index 00000000000..f7f1d06c724 --- /dev/null +++ b/eval/src/vespa/eval/eval/simple_value_engine.cpp @@ -0,0 +1,97 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "simple_value_engine.h" +#include "simple_value.h" +#include "value_codec.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace vespalib::eval::instruction; + +namespace vespalib { +namespace eval { + +const SimpleValueEngine SimpleValueEngine::_engine; + +//----------------------------------------------------------------------------- + +TensorSpec +SimpleValueEngine::to_spec(const Value &value) const +{ + return spec_from_value(value); +} + +Value::UP +SimpleValueEngine::from_spec(const TensorSpec &spec) const +{ + return value_from_spec(spec, SimpleValueBuilderFactory::get()); +} + +//----------------------------------------------------------------------------- + +void +SimpleValueEngine::encode(const Value &value, nbostream &output) const +{ + return encode_value(value, output); +} + +Value::UP +SimpleValueEngine::decode(nbostream &input) const +{ + return decode_value(input, SimpleValueBuilderFactory::get()); +} + +//----------------------------------------------------------------------------- + +const Value & +SimpleValueEngine::map(const Value &a, map_fun_t function, Stash &stash) const +{ + return *stash.create( + GenericMap::perform_map(a, function, SimpleValueBuilderFactory::get())); +} + +const Value & +SimpleValueEngine::join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const +{ + return *stash.create( + GenericJoin::perform_join(a, b, function, SimpleValueBuilderFactory::get())); +} + +const Value & +SimpleValueEngine::merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const +{ + return *stash.create( + GenericMerge::perform_merge(a, b, function, SimpleValueBuilderFactory::get())); +} + +const Value & +SimpleValueEngine::reduce(const Value &a, Aggr aggr, const std::vector &dimensions, Stash &stash) const +{ + return *stash.create( + GenericReduce::perform_reduce(a, aggr, dimensions, SimpleValueBuilderFactory::get())); +} + +const Value & +SimpleValueEngine::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const +{ + return *stash.create( + GenericConcat::perform_concat(a, b, dimension, SimpleValueBuilderFactory::get())); +} + +const Value & +SimpleValueEngine::rename(const Value &a, const std::vector &from, const std::vector &to, Stash &stash) const +{ + return *stash.create( + GenericRename::perform_rename(a, from, to, SimpleValueBuilderFactory::get())); +} + +//----------------------------------------------------------------------------- + +} // namespace vespalib::eval +} // namespace vespalib diff --git a/eval/src/vespa/eval/eval/simple_value_engine.h b/eval/src/vespa/eval/eval/simple_value_engine.h new file mode 100644 index 00000000000..73894d40f9e --- /dev/null +++ b/eval/src/vespa/eval/eval/simple_value_engine.h @@ -0,0 +1,37 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "tensor_engine.h" + +namespace vespalib { +namespace eval { + +/** + * This is a TensorEngine implementation for the SimpleValue + * reference implementation. + **/ +class SimpleValueEngine : public TensorEngine +{ +private: + SimpleValueEngine() {} + static const SimpleValueEngine _engine; +public: + static const TensorEngine &ref() { return _engine; }; + + TensorSpec to_spec(const Value &value) const override; + std::unique_ptr from_spec(const TensorSpec &spec) const override; + + void encode(const Value &value, nbostream &output) const override; + std::unique_ptr decode(nbostream &input) const override; + + const Value &map(const Value &a, map_fun_t function, Stash &stash) const override; + const Value &join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; + const Value &merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; + const Value &reduce(const Value &a, Aggr aggr, const std::vector &dimensions, Stash &stash) const override; + const Value &concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const override; + const Value &rename(const Value &a, const std::vector &from, const std::vector &to, Stash &stash) const override; +}; + +} // namespace vespalib::eval +} // namespace vespalib -- cgit v1.2.3 From e3454747946a6f9075cd1010330c73166c1238fe Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 11:33:28 +0000 Subject: run conformance test also for SimpleValueEngine --- .../tensor/tensor_conformance/tensor_conformance_test.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) 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 a9681cd85c9..1509ea05176 100644 --- a/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp +++ b/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -10,6 +11,7 @@ using vespalib::eval::SimpleValueBuilderFactory; using vespalib::eval::FastValueBuilderFactory; using vespalib::eval::SimpleTensorEngine; +using vespalib::eval::SimpleValueEngine; using vespalib::eval::test::TensorConformance; using vespalib::tensor::DefaultTensorEngine; using vespalib::make_string; @@ -25,11 +27,15 @@ 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("require that SimpleValue implementation passes all conformance tests") { TEST_DO(TensorConformance::run_tests(module_src_path, SimpleValueBuilderFactory::get())); } -TEST("require that FastValue implementation passes all conformance tests (except ImmediateAPI tests)") { +TEST("require that SimpleValueEngine passes all conformance tests") { + TEST_DO(TensorConformance::run_tests(module_src_path, SimpleValueEngine::ref())); +} + +TEST("require that FastValue implementation passes all conformance tests") { TEST_DO(TensorConformance::run_tests(module_src_path, FastValueBuilderFactory::get())); } -- cgit v1.2.3 From 7aa285f121ce527711bbe9e899211da5b91e7856 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 11:51:05 +0000 Subject: fix copyright --- eval/src/vespa/eval/tensor/wrapped_simple_value.cpp | 1 + eval/src/vespa/eval/tensor/wrapped_simple_value.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp b/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp index ca386ee9611..eb552c21aa0 100644 --- a/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp +++ b/eval/src/vespa/eval/tensor/wrapped_simple_value.cpp @@ -1,3 +1,4 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "wrapped_simple_value.h" #include "cell_values.h" diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_value.h b/eval/src/vespa/eval/tensor/wrapped_simple_value.h index 68339790436..3d8c3e43757 100644 --- a/eval/src/vespa/eval/tensor/wrapped_simple_value.h +++ b/eval/src/vespa/eval/tensor/wrapped_simple_value.h @@ -1,4 +1,4 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -- cgit v1.2.3 From 07c7bec5b7b0c94b3b8a18db6ae922ac5258471f Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Mon, 19 Oct 2020 12:25:43 +0000 Subject: drop SimpleValueEngine --- .../tensor_conformance/tensor_conformance_test.cpp | 6 -- eval/src/vespa/eval/eval/CMakeLists.txt | 1 - eval/src/vespa/eval/eval/simple_value_engine.cpp | 97 ---------------------- eval/src/vespa/eval/eval/simple_value_engine.h | 37 --------- 4 files changed, 141 deletions(-) delete mode 100644 eval/src/vespa/eval/eval/simple_value_engine.cpp delete mode 100644 eval/src/vespa/eval/eval/simple_value_engine.h 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 1509ea05176..233aff0e425 100644 --- a/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp +++ b/eval/src/tests/tensor/tensor_conformance/tensor_conformance_test.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -11,7 +10,6 @@ using vespalib::eval::SimpleValueBuilderFactory; using vespalib::eval::FastValueBuilderFactory; using vespalib::eval::SimpleTensorEngine; -using vespalib::eval::SimpleValueEngine; using vespalib::eval::test::TensorConformance; using vespalib::tensor::DefaultTensorEngine; using vespalib::make_string; @@ -31,10 +29,6 @@ TEST("require that SimpleValue implementation passes all conformance tests") { TEST_DO(TensorConformance::run_tests(module_src_path, SimpleValueBuilderFactory::get())); } -TEST("require that SimpleValueEngine passes all conformance tests") { - TEST_DO(TensorConformance::run_tests(module_src_path, SimpleValueEngine::ref())); -} - TEST("require that FastValue implementation passes all conformance tests") { TEST_DO(TensorConformance::run_tests(module_src_path, FastValueBuilderFactory::get())); } diff --git a/eval/src/vespa/eval/eval/CMakeLists.txt b/eval/src/vespa/eval/eval/CMakeLists.txt index 8de7f75226f..5a60adfb58b 100644 --- a/eval/src/vespa/eval/eval/CMakeLists.txt +++ b/eval/src/vespa/eval/eval/CMakeLists.txt @@ -25,7 +25,6 @@ vespa_add_library(eval_eval OBJECT simple_tensor.cpp simple_tensor_engine.cpp simple_value.cpp - simple_value_engine.cpp string_stuff.cpp tensor.cpp tensor_engine.cpp diff --git a/eval/src/vespa/eval/eval/simple_value_engine.cpp b/eval/src/vespa/eval/eval/simple_value_engine.cpp deleted file mode 100644 index f7f1d06c724..00000000000 --- a/eval/src/vespa/eval/eval/simple_value_engine.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "simple_value_engine.h" -#include "simple_value.h" -#include "value_codec.h" -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace vespalib::eval::instruction; - -namespace vespalib { -namespace eval { - -const SimpleValueEngine SimpleValueEngine::_engine; - -//----------------------------------------------------------------------------- - -TensorSpec -SimpleValueEngine::to_spec(const Value &value) const -{ - return spec_from_value(value); -} - -Value::UP -SimpleValueEngine::from_spec(const TensorSpec &spec) const -{ - return value_from_spec(spec, SimpleValueBuilderFactory::get()); -} - -//----------------------------------------------------------------------------- - -void -SimpleValueEngine::encode(const Value &value, nbostream &output) const -{ - return encode_value(value, output); -} - -Value::UP -SimpleValueEngine::decode(nbostream &input) const -{ - return decode_value(input, SimpleValueBuilderFactory::get()); -} - -//----------------------------------------------------------------------------- - -const Value & -SimpleValueEngine::map(const Value &a, map_fun_t function, Stash &stash) const -{ - return *stash.create( - GenericMap::perform_map(a, function, SimpleValueBuilderFactory::get())); -} - -const Value & -SimpleValueEngine::join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const -{ - return *stash.create( - GenericJoin::perform_join(a, b, function, SimpleValueBuilderFactory::get())); -} - -const Value & -SimpleValueEngine::merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const -{ - return *stash.create( - GenericMerge::perform_merge(a, b, function, SimpleValueBuilderFactory::get())); -} - -const Value & -SimpleValueEngine::reduce(const Value &a, Aggr aggr, const std::vector &dimensions, Stash &stash) const -{ - return *stash.create( - GenericReduce::perform_reduce(a, aggr, dimensions, SimpleValueBuilderFactory::get())); -} - -const Value & -SimpleValueEngine::concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const -{ - return *stash.create( - GenericConcat::perform_concat(a, b, dimension, SimpleValueBuilderFactory::get())); -} - -const Value & -SimpleValueEngine::rename(const Value &a, const std::vector &from, const std::vector &to, Stash &stash) const -{ - return *stash.create( - GenericRename::perform_rename(a, from, to, SimpleValueBuilderFactory::get())); -} - -//----------------------------------------------------------------------------- - -} // namespace vespalib::eval -} // namespace vespalib diff --git a/eval/src/vespa/eval/eval/simple_value_engine.h b/eval/src/vespa/eval/eval/simple_value_engine.h deleted file mode 100644 index 73894d40f9e..00000000000 --- a/eval/src/vespa/eval/eval/simple_value_engine.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include "tensor_engine.h" - -namespace vespalib { -namespace eval { - -/** - * This is a TensorEngine implementation for the SimpleValue - * reference implementation. - **/ -class SimpleValueEngine : public TensorEngine -{ -private: - SimpleValueEngine() {} - static const SimpleValueEngine _engine; -public: - static const TensorEngine &ref() { return _engine; }; - - TensorSpec to_spec(const Value &value) const override; - std::unique_ptr from_spec(const TensorSpec &spec) const override; - - void encode(const Value &value, nbostream &output) const override; - std::unique_ptr decode(nbostream &input) const override; - - const Value &map(const Value &a, map_fun_t function, Stash &stash) const override; - const Value &join(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; - const Value &merge(const Value &a, const Value &b, join_fun_t function, Stash &stash) const override; - const Value &reduce(const Value &a, Aggr aggr, const std::vector &dimensions, Stash &stash) const override; - const Value &concat(const Value &a, const Value &b, const vespalib::string &dimension, Stash &stash) const override; - const Value &rename(const Value &a, const std::vector &from, const std::vector &to, Stash &stash) const override; -}; - -} // namespace vespalib::eval -} // namespace vespalib -- cgit v1.2.3