summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorArne Juul <arnej@verizonmedia.com>2021-03-10 13:20:53 +0000
committerArne Juul <arnej@verizonmedia.com>2021-03-11 09:08:50 +0000
commite9f62f97dd3162be72690625b26cd95fd1c14c5b (patch)
tree47642ef028f8c5814848b8ae6b5b0b8e9aceb45a /eval
parentdbd2b74348866390972450dd30818bf82f803401 (diff)
prepare GenericMap for different input/output cell types
* also, use apply_op1_vec when possible, from MixedMapFunction * now uses a MapParam, to wire the result type in an uniform manner
Diffstat (limited to 'eval')
-rw-r--r--eval/src/tests/instruction/generic_map/generic_map_test.cpp6
-rw-r--r--eval/src/vespa/eval/eval/tensor_function.cpp4
-rw-r--r--eval/src/vespa/eval/instruction/generic_map.cpp67
-rw-r--r--eval/src/vespa/eval/instruction/generic_map.h4
4 files changed, 58 insertions, 23 deletions
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 bfa7154968d..54ba0ea2a31 100644
--- a/eval/src/tests/instruction/generic_map/generic_map_test.cpp
+++ b/eval/src/tests/instruction/generic_map/generic_map_test.cpp
@@ -35,11 +35,13 @@ const std::vector<GenSpec> map_layouts = {
TensorSpec perform_generic_map(const TensorSpec &a, map_fun_t func, const ValueBuilderFactory &factory)
{
+ Stash stash;
auto lhs = value_from_spec(a, factory);
auto res_type = lhs->type().map();
- auto my_op = GenericMap::make_instruction(res_type, lhs->type(), func);
+ auto my_op = GenericMap::make_instruction(res_type, lhs->type(), func, stash);
InterpretedFunction::EvalSingle single(factory, my_op);
- return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs})));
+ const auto & v = single.eval(std::vector<Value::CREF>({*lhs}));
+ return spec_from_value(v);
}
void test_generic_map_with(const ValueBuilderFactory &factory) {
diff --git a/eval/src/vespa/eval/eval/tensor_function.cpp b/eval/src/vespa/eval/eval/tensor_function.cpp
index fd8b20bfed0..c0cd7280212 100644
--- a/eval/src/vespa/eval/eval/tensor_function.cpp
+++ b/eval/src/vespa/eval/eval/tensor_function.cpp
@@ -158,9 +158,9 @@ Reduce::visit_self(vespalib::ObjectVisitor &visitor) const
//-----------------------------------------------------------------------------
Instruction
-Map::compile_self(const ValueBuilderFactory &, Stash &) const
+Map::compile_self(const ValueBuilderFactory &, Stash &stash) const
{
- return instruction::GenericMap::make_instruction(result_type(), child().result_type(), _function);
+ return instruction::GenericMap::make_instruction(result_type(), child().result_type(), _function, stash);
}
void
diff --git a/eval/src/vespa/eval/instruction/generic_map.cpp b/eval/src/vespa/eval/instruction/generic_map.cpp
index 4f6780c2276..9e584422b01 100644
--- a/eval/src/vespa/eval/instruction/generic_map.cpp
+++ b/eval/src/vespa/eval/instruction/generic_map.cpp
@@ -1,8 +1,9 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "generic_map.h"
-#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/inline_operation.h>
+#include <vespa/eval/eval/value.h>
+#include <vespa/eval/eval/wrap_param.h>
#include <vespa/vespalib/util/stash.h>
#include <vespa/vespalib/util/typify.h>
#include <cassert>
@@ -11,54 +12,84 @@ namespace vespalib::eval::instruction {
using State = InterpretedFunction::State;
using Instruction = InterpretedFunction::Instruction;
+using vespalib::eval::tensor_function::unwrap_param;
+using vespalib::eval::tensor_function::wrap_param;
+
+struct MapParam {
+ const ValueType res_type;
+ const map_fun_t function;
+ MapParam(const ValueType &r, map_fun_t f) : res_type(r), function(f) {}
+};
namespace {
-uint64_t to_param(map_fun_t value) { return (uint64_t)value; }
-map_fun_t to_map_fun(uint64_t param) { return (map_fun_t)param; }
+template <typename ICT, typename OCT, typename Func>
+void my_generic_map_op(State &state, uint64_t param_in) {
+ const auto &param = unwrap_param<MapParam>(param_in);
+ Func function(param.function);
+ const Value &a = state.peek(0);
+ auto input_cells = a.cells().typify<ICT>();
+ auto output_cells = state.stash.create_uninitialized_array<OCT>(input_cells.size());
+ auto pos = output_cells.begin();
+ for (ICT value : input_cells) {
+ *pos++ = (OCT) function(value);
+ }
+ assert(pos == output_cells.end());
+ ValueType &result_type = state.stash.create<ValueType>(param.res_type);
+ // XXX: could we refer to param.res_type from ValueView instead?
+ Value &result_ref = state.stash.create<ValueView>(result_type, a.index(), TypedCells(output_cells));
+ state.pop_push(result_ref);
+}
template <typename CT, typename Func>
-void my_generic_map_op(State &state, uint64_t param_in) {
- Func function(to_map_fun(param_in));
+void my_simple_map_op(State &state, uint64_t param_in) {
+ const auto &param = unwrap_param<MapParam>(param_in);
+ Func function(param.function);
const Value &a = state.peek(0);
auto input_cells = a.cells().typify<CT>();
auto output_cells = state.stash.create_uninitialized_array<CT>(input_cells.size());
auto pos = output_cells.begin();
- for (CT value : input_cells) {
- *pos++ = (CT) function(value);
- }
- assert(pos == output_cells.end());
+ apply_op1_vec(pos, input_cells.begin(), output_cells.size(), function);
Value &result_ref = state.stash.create<ValueView>(a.type(), a.index(), TypedCells(output_cells));
state.pop_push(result_ref);
}
template <typename Func>
void my_double_map_op(State &state, uint64_t param_in) {
- Func fun(to_map_fun(param_in));
+ const auto &param = unwrap_param<MapParam>(param_in);
+ Func fun(param.function);
state.pop_push(state.stash.create<DoubleValue>(fun(state.peek(0).as_double())));
}
struct SelectGenericMapOp {
- template <typename CT, typename Func> static auto invoke(const ValueType &type) {
- if (type.is_double()) {
- assert((std::is_same_v<CT,double>));
+ template <typename ICM, typename Func> static auto invoke() {
+ if constexpr (ICM::value.is_scalar) {
return my_double_map_op<Func>;
}
- return my_generic_map_op<CT, Func>;
+ using ICT = CellValueType<ICM::value.cell_type>;
+ using OCT = CellValueType<ICM::value.map().cell_type>;
+ if constexpr (std::is_same<ICT,OCT>::value) {
+ return my_simple_map_op<ICT, Func>;
+ } else {
+ return my_generic_map_op<ICT, OCT, Func>;
+ }
}
};
} // namespace <unnamed>
-using MapTypify = TypifyValue<TypifyCellType,operation::TypifyOp1>;
+using MapTypify = TypifyValue<TypifyCellMeta,operation::TypifyOp1>;
InterpretedFunction::Instruction
GenericMap::make_instruction(const ValueType &result_type,
- const ValueType &input_type, map_fun_t function)
+ const ValueType &input_type,
+ map_fun_t function,
+ Stash &stash)
{
+ const auto &param = stash.create<MapParam>(result_type, function);
assert(result_type == input_type.map());
- auto op = typify_invoke<2,MapTypify,SelectGenericMapOp>(input_type.cell_type(), function, input_type);
- return Instruction(op, to_param(function));
+ auto op = typify_invoke<2,MapTypify,SelectGenericMapOp>(input_type.cell_meta(), function);
+ return Instruction(op, wrap_param<MapParam>(param));
}
} // namespace
diff --git a/eval/src/vespa/eval/instruction/generic_map.h b/eval/src/vespa/eval/instruction/generic_map.h
index f6c01760898..6878546018d 100644
--- a/eval/src/vespa/eval/instruction/generic_map.h
+++ b/eval/src/vespa/eval/instruction/generic_map.h
@@ -15,7 +15,9 @@ using map_fun_t = operation::op1_t;
struct GenericMap {
static InterpretedFunction::Instruction
make_instruction(const ValueType &result_type,
- const ValueType &input_type, map_fun_t function);
+ const ValueType &input_type,
+ map_fun_t function,
+ Stash &stash);
};
} // namespace