diff options
author | Håvard Pettersen <havardpe@oath.com> | 2021-02-04 08:28:21 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2021-02-04 12:19:58 +0000 |
commit | 7bfb2536fc656e401469107d4c1dd182be80248b (patch) | |
tree | 49f4e5506e5befcb7f7143f314b27d0cad0e05c6 /eval | |
parent | 8c8a2061cc06036374ca46971798c35534a6a253 (diff) |
rework sequence concept to match GenSpec
Diffstat (limited to 'eval')
-rw-r--r-- | eval/src/apps/tensor_conformance/generate.cpp | 8 | ||||
-rw-r--r-- | eval/src/tests/eval/gen_spec/gen_spec_test.cpp | 77 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/gen_spec.cpp | 33 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/gen_spec.h | 44 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/tensor_conformance.cpp | 4 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/tensor_model.cpp | 4 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/tensor_model.h | 61 |
7 files changed, 132 insertions, 99 deletions
diff --git a/eval/src/apps/tensor_conformance/generate.cpp b/eval/src/apps/tensor_conformance/generate.cpp index e3d0c3c1063..537e35dee1f 100644 --- a/eval/src/apps/tensor_conformance/generate.cpp +++ b/eval/src/apps/tensor_conformance/generate.cpp @@ -183,8 +183,8 @@ void generate_tensor_join(TestBuilder &dst) { void generate_dot_product(TestBuilder &dst, double expect, - const Layout &lhs, const Seq &lhs_seq, - const Layout &rhs, const Seq &rhs_seq) + const Layout &lhs, const Sequence &lhs_seq, + const Layout &rhs, const Sequence &rhs_seq) { dst.add("reduce(a*b,sum)", { {"a", spec(lhs, lhs_seq)},{"b", spec(rhs, rhs_seq)} }, @@ -194,8 +194,8 @@ void generate_dot_product(TestBuilder &dst, void generate_dot_product(TestBuilder &dst, double expect, const Layout &layout, - const Seq &lhs_seq, - const Seq &rhs_seq) + const Sequence &lhs_seq, + const Sequence &rhs_seq) { auto fl_lay = float_cells(layout); generate_dot_product(dst, expect, layout, lhs_seq, layout, rhs_seq); diff --git a/eval/src/tests/eval/gen_spec/gen_spec_test.cpp b/eval/src/tests/eval/gen_spec/gen_spec_test.cpp index 0d1a4744e42..9af26e1284d 100644 --- a/eval/src/tests/eval/gen_spec/gen_spec_test.cpp +++ b/eval/src/tests/eval/gen_spec/gen_spec_test.cpp @@ -8,7 +8,7 @@ using namespace vespalib::eval::test; //----------------------------------------------------------------------------- -TEST(DimSpec, indexed_dimension) { +TEST(DimSpecTest, indexed_dimension) { ValueType::Dimension ref("foo", 10); DimSpec idx("foo", 10); EXPECT_EQ(idx.type(), ref); @@ -18,7 +18,7 @@ TEST(DimSpec, indexed_dimension) { EXPECT_EQ(idx.label(3), TensorSpec::Label(size_t(3))); } -TEST(DimSpec, mapped_dimension) { +TEST(DimSpecTest, mapped_dimension) { ValueType::Dimension ref("foo"); DimSpec map("foo", {"a", "b", "c", "d"}); EXPECT_EQ(map.type(), ref); @@ -28,19 +28,19 @@ TEST(DimSpec, mapped_dimension) { EXPECT_EQ(map.label(2), TensorSpec::Label("c")); } -TEST(DimSpec, simple_dictionary_creation) { +TEST(DimSpecTest, simple_dictionary_creation) { auto dict = DimSpec::make_dict(5, 1, ""); std::vector<vespalib::string> expect = {"0", "1", "2", "3", "4"}; } -TEST(DimSpec, advanced_dictionary_creation) { +TEST(DimSpecTest, advanced_dictionary_creation) { auto dict = DimSpec::make_dict(5, 3, "str_"); std::vector<vespalib::string> expect = {"str_0", "str_3", "str_6", "str_9", "str_12"}; } //----------------------------------------------------------------------------- -TEST(GenSpec, default_spec) { +TEST(GenSpecTest, default_spec) { GenSpec spec; EXPECT_TRUE(spec.dims().empty()); EXPECT_EQ(spec.cells(), CellType::DOUBLE); @@ -55,29 +55,66 @@ TEST(GenSpec, default_spec) { TensorSpec scalar_1 = TensorSpec("double").add({}, 1.0); TensorSpec scalar_5 = TensorSpec("double").add({}, 5.0); -TEST(GenSpec, scalar_double) { +TEST(GenSpecTest, scalar_double) { EXPECT_EQ(GenSpec().gen(), scalar_1); EXPECT_EQ(GenSpec().seq_bias(5.0).gen(), scalar_5); } -TEST(GenSpec, not_scalar_float_just_yet) { +TEST(GenSpecTest, not_scalar_float_just_yet) { EXPECT_EQ(GenSpec().cells_float().gen(), scalar_1); EXPECT_EQ(GenSpec().cells_float().seq_bias(5.0).gen(), scalar_5); } //----------------------------------------------------------------------------- -TEST(Seq, seq_n) { - GenSpec::seq_t seq = GenSpec().seq_n().seq(); +TEST(SequenceTest, n) { + GenSpec::seq_t seq = GenSpec().seq(N()).seq(); for (size_t i = 0; i < 4096; ++i) { EXPECT_EQ(seq(i), (i + 1.0)); } } -TEST(Seq, seq_bias) { - GenSpec::seq_t seq = GenSpec().seq_bias(13.0).seq(); +TEST(SequenceTest, bias) { + GenSpec::seq_t seq = GenSpec().seq(N(13.5)).seq(); for (size_t i = 0; i < 4096; ++i) { - EXPECT_EQ(seq(i), (i + 13.0)); + EXPECT_EQ(seq(i), (i + 13.5)); + } +} + +TEST(SequenceTest, ax_b) { + GenSpec::seq_t seq = GenSpec().seq(AX_B(3.5, 2.5)).seq(); + for (size_t i = 0; i < 4096; ++i) { + EXPECT_EQ(seq(i), (i * 3.5) + 2.5); + } +} + +TEST(SequenceTest, seq) { + std::vector<double> values({1.5, 3.5, 2.5, 10.0}); + GenSpec::seq_t seq = GenSpec().seq(Seq(values)).seq(); + for (size_t i = 0; i < 4096; ++i) { + EXPECT_EQ(seq(i), values[i % values.size()]); + } +} + +TEST(SequenceTest, n_div16_sub2) { + GenSpec::seq_t seq = GenSpec().seq(Sub2(Div16(N()))).seq(); + for (size_t i = 0; i < 4096; ++i) { + EXPECT_EQ(seq(i), ((i + 1.0) / 16.0) - 2.0); + } +} + +TEST(SequenceTest, n_op_sqrt) { + GenSpec::seq_t seq = GenSpec().seq(OpSeq(N(), operation::Sqrt::f)).seq(); + for (size_t i = 0; i < 4096; ++i) { + EXPECT_EQ(seq(i), operation::Sqrt::f(i + 1.0)); + } +} + +TEST(SequenceTest, n_sigmoidf) { + GenSpec::seq_t seq = GenSpec().seq(SigmoidF(N())).seq(); + for (size_t i = 0; i < 4096; ++i) { + EXPECT_EQ(seq(i), double((float)operation::Sigmoid::f(i + 1.0))); + EXPECT_TRUE(seq(i) == double((float)operation::Sigmoid::f(i + 1.0))); } } @@ -86,7 +123,7 @@ TEST(Seq, seq_bias) { GenSpec flt() { return GenSpec().cells_float(); } GenSpec dbl() { return GenSpec().cells_double(); } -TEST(GenSpec, value_type) { +TEST(GenSpecTest, value_type) { EXPECT_EQ(dbl().type().to_spec(), "double"); EXPECT_EQ(flt().type().to_spec(), "double"); // NB EXPECT_EQ(dbl().idx("x", 10).type().to_spec(), "tensor(x[10])"); @@ -122,15 +159,15 @@ TensorSpec custom_vector = TensorSpec("tensor(a[5])") .add({{"a", 3}}, 2.0) .add({{"a", 4}}, 1.0); -TEST(GenSpec, generating_basic_vector) { +TEST(GenSpecTest, generating_basic_vector) { EXPECT_EQ(GenSpec().idx("a", 5).gen(), basic_vector); } -TEST(GenSpec, generating_float_vector) { +TEST(GenSpecTest, generating_float_vector) { EXPECT_EQ(GenSpec().idx("a", 5).cells_float().gen(), float_vector); } -TEST(GenSpec, generating_custom_vector) { +TEST(GenSpecTest, generating_custom_vector) { GenSpec::seq_t my_seq = [](size_t idx) noexcept { return (5.0 - idx); }; EXPECT_EQ(GenSpec().idx("a", 5).seq(my_seq).gen(), custom_vector); } @@ -147,14 +184,14 @@ TensorSpec custom_map = TensorSpec("tensor(a{})") .add({{"a", "s5"}}, 2.0) .add({{"a", "s10"}}, 3.0); -TEST(GenSpec, generating_basic_map) { +TEST(GenSpecTest, generating_basic_map) { EXPECT_EQ(GenSpec().map("a", 3).gen(), basic_map); EXPECT_EQ(GenSpec().map("a", 3, 1).gen(), basic_map); EXPECT_EQ(GenSpec().map("a", 3, 1, "").gen(), basic_map); EXPECT_EQ(GenSpec().map("a", {"0", "1", "2"}).gen(), basic_map); } -TEST(GenSpec, generating_custom_map) { +TEST(GenSpecTest, generating_custom_map) { EXPECT_EQ(GenSpec().map("a", 3, 5, "s").gen(), custom_map); EXPECT_EQ(GenSpec().map("a", {"s0", "s5", "s10"}).gen(), custom_map); } @@ -183,11 +220,11 @@ TensorSpec inverted_mixed = TensorSpec("tensor(a{},b[1],c{},d[3])") .add({{"a", "1"},{"b", 0},{"c", "0"},{"d", 2}}, 8.0) .add({{"a", "2"},{"b", 0},{"c", "0"},{"d", 2}}, 9.0); -TEST(GenSpec, generating_basic_mixed) { +TEST(GenSpecTest, generating_basic_mixed) { EXPECT_EQ(GenSpec().map("a", 3).idx("b", 1).map("c", 1).idx("d", 3).gen(), basic_mixed); } -TEST(GenSpec, generating_inverted_mixed) { +TEST(GenSpecTest, generating_inverted_mixed) { EXPECT_EQ(GenSpec().idx("d", 3).map("c", 1).idx("b", 1).map("a", 3).gen(), inverted_mixed); } diff --git a/eval/src/vespa/eval/eval/test/gen_spec.cpp b/eval/src/vespa/eval/eval/test/gen_spec.cpp index c20e9005318..5ef4896d694 100644 --- a/eval/src/vespa/eval/eval/test/gen_spec.cpp +++ b/eval/src/vespa/eval/eval/test/gen_spec.cpp @@ -8,6 +8,39 @@ using vespalib::make_string_short::fmt; namespace vespalib::eval::test { +//----------------------------------------------------------------------------- + +Sequence N(double bias) { + return [bias](size_t i) { return (i + bias); }; +} + +Sequence AX_B(double a, double b) { + return [a,b](size_t i) { return (a * i) + b; }; +} + +Sequence Div16(const Sequence &seq) { + return [seq](size_t i) { return (seq(i) / 16.0); }; +} + +Sequence Sub2(const Sequence &seq) { + return [seq](size_t i) { return (seq(i) - 2.0); }; +} + +Sequence OpSeq(const Sequence &seq, map_fun_t op) { + return [seq,op](size_t i) { return op(seq(i)); }; +} + +Sequence SigmoidF(const Sequence &seq) { + return [seq](size_t i) { return (float)operation::Sigmoid::f(seq(i)); }; +} + +Sequence Seq(const std::vector<double> &seq) { + assert(!seq.empty()); + return [seq](size_t i) { return seq[i % seq.size()]; }; +} + +//----------------------------------------------------------------------------- + DimSpec::~DimSpec() = default; std::vector<vespalib::string> diff --git a/eval/src/vespa/eval/eval/test/gen_spec.h b/eval/src/vespa/eval/eval/test/gen_spec.h index 36bbd554125..6b9631c66c7 100644 --- a/eval/src/vespa/eval/eval/test/gen_spec.h +++ b/eval/src/vespa/eval/eval/test/gen_spec.h @@ -4,11 +4,39 @@ #include <vespa/eval/eval/tensor_spec.h> #include <vespa/eval/eval/value_type.h> +#include <vespa/eval/eval/operation.h> #include <functional> #include <cassert> namespace vespalib::eval::test { +using map_fun_t = vespalib::eval::operation::op1_t; +using join_fun_t = vespalib::eval::operation::op2_t; +using Sequence = std::function<double(size_t)>; + +// Sequence counting up from 1 (default) +// bias (starting point) can be adjusted +// bias = 1.5 -> 1.5, 2.5, 3.5 ... +Sequence N(double bias = 1.0); + +// Sequence of numbers ax + b (where x is the index) +Sequence AX_B(double a, double b); + +// Sequence of another sequence divided by 16 +Sequence Div16(const Sequence &seq); + +// Sequence of another sequence minus 2 +Sequence Sub2(const Sequence &seq); + +// Sequence of a unary operator applied to a sequence +Sequence OpSeq(const Sequence &seq, map_fun_t op); + +// Sequence of applying sigmoid to another sequence, plus rounding to nearest float +Sequence SigmoidF(const Sequence &seq); + +// pre-defined repeating sequence of numbers +Sequence Seq(const std::vector<double> &seq); + /** * Type and labels for a single dimension of a TensorSpec to be * generated. Dimensions are specified independent of each other for @@ -57,15 +85,15 @@ public: class GenSpec { public: - using seq_t = std::function<double(size_t)>; + using seq_t = Sequence; + private: std::vector<DimSpec> _dims; CellType _cells; seq_t _seq; - static double default_seq(size_t idx) { return (idx + 1.0); } public: - GenSpec() : _dims(), _cells(CellType::DOUBLE), _seq(default_seq) {} + GenSpec() : _dims(), _cells(CellType::DOUBLE), _seq(N()) {} GenSpec(GenSpec &&other); GenSpec(const GenSpec &other); GenSpec &operator=(GenSpec &&other); @@ -73,7 +101,7 @@ public: ~GenSpec(); std::vector<DimSpec> dims() const { return _dims; } CellType cells() const { return _cells; } - seq_t seq() const { return _seq; } + const seq_t &seq() const { return _seq; } GenSpec cpy() const { return *this; } GenSpec &idx(const vespalib::string &name, size_t size) { _dims.emplace_back(name, size); @@ -93,15 +121,11 @@ public: } GenSpec &cells_double() { return cells(CellType::DOUBLE); } GenSpec &cells_float() { return cells(CellType::FLOAT); } - GenSpec &seq(seq_t seq_in) { + GenSpec &seq(const seq_t &seq_in) { _seq = seq_in; return *this; } - GenSpec &seq_n() { return seq(default_seq); } - GenSpec &seq_bias(double bias) { - seq_t fun = [bias](size_t idx) noexcept { return (idx + bias); }; - return seq(fun); - } + GenSpec &seq_bias(double bias) { return seq(N(bias)); } ValueType type() const; TensorSpec gen() const; }; diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp index bd203b42ef1..1e9afde3cb9 100644 --- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp +++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp @@ -503,8 +503,8 @@ struct TestContext { } void test_dot_product(double expect, - const Layout &lhs, const Seq &lhs_seq, - const Layout &rhs, const Seq &rhs_seq) + const Layout &lhs, const Sequence &lhs_seq, + const Layout &rhs, const Sequence &rhs_seq) { TEST_DO(test_dot_product(expect, spec(lhs, lhs_seq), spec(rhs, rhs_seq))); TEST_DO(test_dot_product(expect, spec(float_cells(lhs), lhs_seq), spec(rhs, rhs_seq))); diff --git a/eval/src/vespa/eval/eval/test/tensor_model.cpp b/eval/src/vespa/eval/eval/test/tensor_model.cpp index 98470388eb5..7860563bccd 100644 --- a/eval/src/vespa/eval/eval/test/tensor_model.cpp +++ b/eval/src/vespa/eval/eval/test/tensor_model.cpp @@ -5,8 +5,6 @@ namespace vespalib::eval::test { -Seq::~Seq() = default; - Domain::Domain(const Domain &) = default; Domain::~Domain() = default; @@ -63,7 +61,7 @@ private: void generate(size_t layout_idx) { if (layout_idx == _source.layout.size()) { - _spec.add(_addr, _source.seq[_idx++]); + _spec.add(_addr, _source.seq(_idx++)); } else { const Domain &domain = _source.layout[layout_idx]; if (domain.size > 0) { // indexed diff --git a/eval/src/vespa/eval/eval/test/tensor_model.h b/eval/src/vespa/eval/eval/test/tensor_model.h index 28b9bfd4c6e..56504795cee 100644 --- a/eval/src/vespa/eval/eval/test/tensor_model.h +++ b/eval/src/vespa/eval/eval/test/tensor_model.h @@ -2,69 +2,10 @@ #pragma once -#include <vespa/eval/eval/tensor_spec.h> -#include <vespa/eval/eval/operation.h> -#include <vespa/eval/eval/cell_type.h> -#include <cassert> -#include <vector> +#include "gen_spec.h" namespace vespalib::eval::test { -using map_fun_t = vespalib::eval::operation::op1_t; -using join_fun_t = vespalib::eval::operation::op2_t; - -// Random access sequence of numbers -struct Sequence { - virtual double operator[](size_t i) const = 0; - virtual ~Sequence() {} -}; - -// Sequence of natural numbers (starting at 1) -struct N : Sequence { - double operator[](size_t i) const override { return (1.0 + i); } -}; - -// Sequence of another sequence divided by 16 -struct Div16 : Sequence { - const Sequence &seq; - Div16(const Sequence &seq_in) : seq(seq_in) {} - double operator[](size_t i) const override { return (seq[i] / 16.0); } -}; - -// Sequence of another sequence minus 2 -struct Sub2 : Sequence { - const Sequence &seq; - Sub2(const Sequence &seq_in) : seq(seq_in) {} - double operator[](size_t i) const override { return (seq[i] - 2.0); } -}; - -// Sequence of a unary operator applied to a sequence -struct OpSeq : Sequence { - const Sequence &seq; - map_fun_t op; - OpSeq(const Sequence &seq_in, map_fun_t op_in) : seq(seq_in), op(op_in) {} - double operator[](size_t i) const override { return op(seq[i]); } -}; - -// Sequence of applying sigmoid to another sequence, plus rounding to nearest float -struct SigmoidF : Sequence { - const Sequence &seq; - SigmoidF(const Sequence &seq_in) : seq(seq_in) {} - double operator[](size_t i) const override { return (float)operation::Sigmoid::f(seq[i]); } -}; - -// pre-defined repeating sequence of numbers -struct Seq : Sequence { - std::vector<double> seq; - Seq() : seq() {} - Seq(const std::vector<double> &seq_in) - : seq(seq_in) { assert(!seq_in.empty()); } - ~Seq() override; - double operator[](size_t i) const override { - return seq[i % seq.size()]; - } -}; - // custom op1 struct MyOp { static double f(double a) { |