aboutsummaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2019-05-03 10:07:40 +0000
committerHåvard Pettersen <havardpe@oath.com>2019-05-03 11:22:03 +0000
commitfe283c00dd00c91548f2b8ef8ef9c7a465234587 (patch)
tree764f146cbefd1c31c6f80e916b8a4b902e57ba5a /eval
parent2bc26be1fd42205b293b723678c5b32cebe9a2a0 (diff)
disable optimizations for tensors with non-double cells
use reference implementation for tensors claiming to have non-double cells to be able to preserve cell type for tensors created from a TensorSpec (specifically lambda tensors with float cells).
Diffstat (limited to 'eval')
-rw-r--r--eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp4
-rw-r--r--eval/src/tests/tensor/dense_dot_product_function/dense_dot_product_function_test.cpp15
-rw-r--r--eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp5
-rw-r--r--eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp8
-rw-r--r--eval/src/tests/tensor/dense_inplace_map_function/dense_inplace_map_function_test.cpp5
-rw-r--r--eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp5
-rw-r--r--eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp8
-rw-r--r--eval/src/vespa/eval/tensor/default_tensor_engine.cpp16
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp3
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_dot_product_function.cpp19
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp5
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp5
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.cpp3
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp3
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_xw_product_function.cpp3
-rw-r--r--eval/src/vespa/eval/tensor/tensor.cpp3
16 files changed, 78 insertions, 32 deletions
diff --git a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp b/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
index 9b46fc3393a..eaf4623afea 100644
--- a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
+++ b/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
@@ -99,4 +99,8 @@ TEST("require that dimension addition optimization requires unit constant tensor
TEST_DO(verify_not_optimized("tensor(x[2])(1)*tensor(y[2])(1)"));
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("x5*tensor<float>(a[1],b[1],c[1])(1)"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
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 fae5db75618..b5a1cac6d0f 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
@@ -103,6 +103,7 @@ EvalFixture::ParamRepo make_params() {
.add("v04_y3", spec({y(3)}, MyVecSeq(10)))
.add("v05_x5", spec({x(5)}, MyVecSeq(6.0)))
.add("v06_x5", spec({x(5)}, MyVecSeq(7.0)))
+ .add("v07_x5f", spec({x(5)}, MyVecSeq(7.0)), "tensor<float>(x[5])")
.add("m01_x3y3", spec({x(3),y(3)}, MyVecSeq(1.0)))
.add("m02_x3y3", spec({x(3),y(3)}, MyVecSeq(2.0)));
}
@@ -183,11 +184,17 @@ void verify_not_compatible(const vespalib::string &a, const vespalib::string &b)
TEST("require that type compatibility test is appropriate") {
TEST_DO(verify_compatible("tensor(x[5])", "tensor(x[5])"));
+ TEST_DO(verify_not_compatible("tensor(x[5])", "tensor<float>(x[5])"));
+ TEST_DO(verify_not_compatible("tensor<float>(x[5])", "tensor<float>(x[5])"));
+ TEST_DO(verify_not_compatible("tensor(x[5])", "tensor(x[6])"));
TEST_DO(verify_not_compatible("tensor(x[5])", "tensor(y[5])"));
- TEST_DO(verify_compatible("tensor(x[5])", "tensor(x[3])"));
- TEST_DO(verify_compatible("tensor(x[3],y[7],z[9])", "tensor(x[5],y[7],z[9])"));
- TEST_DO(verify_not_compatible("tensor(x[5],y[7],z[9])", "tensor(x[5],y[5],z[9])"));
- TEST_DO(verify_not_compatible("tensor(x[5],y[7],z[9])", "tensor(x[5],y[7],z[5])"));
+ TEST_DO(verify_compatible("tensor(x[3],y[7],z[9])", "tensor(x[3],y[7],z[9])"));
+ TEST_DO(verify_not_compatible("tensor(x[3],y[7],z[9])", "tensor(x[5],y[7],z[9])"));
+ TEST_DO(verify_not_compatible("tensor(x[9],y[7],z[5])", "tensor(x[5],y[7],z[9])"));
+}
+
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(assertNotOptimized("reduce(v05_x5*v07_x5f,sum)"));
}
//-----------------------------------------------------------------------------
diff --git a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp b/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
index 10b4c622a0a..773381b4c77 100644
--- a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
+++ b/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
@@ -25,6 +25,7 @@ const TensorEngine &prod_engine = DefaultTensorEngine::ref();
EvalFixture::ParamRepo make_params() {
return EvalFixture::ParamRepo()
.add("x5", spec({x(5)}, N()))
+ .add("x5f", spec({x(5)}, N()), "tensor<float>(x[5])")
.add("x_m", spec({x({"a", "b", "c"})}, N()))
.add("x5y3", spec({x(5),y(3)}, N()));
}
@@ -71,4 +72,8 @@ TEST("require that chained optimized renames are compacted into a single operati
TEST_DO(verify_optimized("rename(rename(x5,x,y),y,z)"));
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("rename(x5f,x,y)"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp b/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp
index 7ee603e1763..c9e581e6b21 100644
--- a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp
+++ b/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp
@@ -45,6 +45,8 @@ EvalFixture::ParamRepo make_params() {
.add_mutable("mut_x5_A", spec({x(5)}, seq))
.add_mutable("mut_x5_B", spec({x(5)}, seq))
.add_mutable("mut_x5_C", spec({x(5)}, seq))
+ .add_mutable("mut_x5f_D", spec({x(5)}, seq), "tensor<float>(x[5])")
+ .add_mutable("mut_x5f_E", spec({x(5)}, seq), "tensor<float>(x[5])")
.add_mutable("mut_x5y3_A", spec({x(5),y(3)}, seq))
.add_mutable("mut_x5y3_B", spec({x(5),y(3)}, seq))
.add_mutable("mut_x_sparse", spec({x({"a", "b", "c"})}, seq));
@@ -142,4 +144,10 @@ TEST("require that inplace join can be debug dumped") {
fprintf(stderr, "%s\n", info[0]->as_string().c_str());
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("mut_x5_A-mut_x5f_D"));
+ TEST_DO(verify_not_optimized("mut_x5f_D-mut_x5_A"));
+ TEST_DO(verify_not_optimized("mut_x5f_D-mut_x5f_E"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/tests/tensor/dense_inplace_map_function/dense_inplace_map_function_test.cpp b/eval/src/tests/tensor/dense_inplace_map_function/dense_inplace_map_function_test.cpp
index a17b7e02eb8..36ebdec028b 100644
--- a/eval/src/tests/tensor/dense_inplace_map_function/dense_inplace_map_function_test.cpp
+++ b/eval/src/tests/tensor/dense_inplace_map_function/dense_inplace_map_function_test.cpp
@@ -26,6 +26,7 @@ EvalFixture::ParamRepo make_params() {
.add("x5", spec({x(5)}, N()))
.add_mutable("_d", spec(5.0))
.add_mutable("_x5", spec({x(5)}, N()))
+ .add_mutable("_x5f", spec({x(5)}, N()), "tensor<float>(x[5])")
.add_mutable("_x5y3", spec({x(5),y(3)}, N()))
.add_mutable("_x_m", spec({x({"a", "b", "c"})}, N()));
}
@@ -71,4 +72,8 @@ TEST("require that mapped tensors are not optimized") {
TEST_DO(verify_not_optimized("map(_x_m,f(x)(x+10))"));
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("map(_x5f,f(x)(x+10))"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp b/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
index ac451d10b50..65208aedb4b 100644
--- a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
+++ b/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
@@ -25,6 +25,7 @@ const TensorEngine &prod_engine = DefaultTensorEngine::ref();
EvalFixture::ParamRepo make_params() {
return EvalFixture::ParamRepo()
.add("x1y5z1", spec({x(1),y(5),z(1)}, N()))
+ .add("x1y5z1f", spec({x(1),y(5),z(1)}, N()), "tensor<float>(x[1],y[5],z[1])")
.add("x1y1z1", spec({x(1),y(1),z(1)}, N()))
.add("x1y5z_m", spec({x(1),y(5),z({"a"})}, N()));
}
@@ -77,4 +78,8 @@ TEST("require that inappropriate tensor types cannot be optimized") {
TEST_DO(verify_not_optimized("reduce(x1y5z_m,sum,z)"));
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("reduce(x1y5z1f,avg,x)"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
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 b55e223ab07..5c976073732 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
@@ -39,11 +39,13 @@ EvalFixture::ParamRepo make_params() {
return EvalFixture::ParamRepo()
.add("y1", spec({y(1)}, MyVecSeq()))
.add("y3", spec({y(3)}, MyVecSeq()))
+ .add("y3f", spec({y(3)}, MyVecSeq()), "tensor<float>(y[3])")
.add("y5", spec({y(5)}, MyVecSeq()))
.add("y16", spec({y(16)}, MyVecSeq()))
.add("x1y1", spec({x(1),y(1)}, MyMatSeq()))
.add("y1z1", spec({y(1),z(1)}, MyMatSeq()))
.add("x2y3", spec({x(2),y(3)}, MyMatSeq()))
+ .add("x2y3f", spec({x(2),y(3)}, MyMatSeq()), "tensor<float>(x[2],y[3])")
.add("x2z3", spec({x(2),z(3)}, MyMatSeq()))
.add("y3z2", spec({y(3),z(2)}, MyMatSeq()))
.add("x8y5", spec({x(8),y(5)}, MyMatSeq()))
@@ -117,4 +119,10 @@ TEST("require that xw product can be debug dumped") {
fprintf(stderr, "%s\n", info[0]->as_string().c_str());
}
+TEST("require that optimization is disabled for tensors with non-double cells") {
+ TEST_DO(verify_not_optimized("reduce(y3f*x2y3,sum,y)"));
+ TEST_DO(verify_not_optimized("reduce(y3*x2y3f,sum,y)"));
+ TEST_DO(verify_not_optimized("reduce(y3f*x2y3f,sum,y)"));
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp
index 5a16511fe71..263d77e5d1e 100644
--- a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp
+++ b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp
@@ -125,19 +125,9 @@ Value::UP
DefaultTensorEngine::from_spec(const TensorSpec &spec) const
{
ValueType type = ValueType::from_spec(spec.type());
- bool is_dense = false;
- bool is_sparse = false;
- for (const auto &dimension: type.dimensions()) {
- if (dimension.is_mapped()) {
- is_sparse = true;
- }
- if (dimension.is_indexed()) {
- is_dense = true;
- }
- }
- if (is_dense && is_sparse) {
+ if (!tensor::Tensor::supported({type})) {
return std::make_unique<WrappedSimpleTensor>(eval::SimpleTensor::create(spec));
- } else if (is_dense) {
+ } else if (type.is_dense()) {
DenseTensorBuilder builder;
std::map<vespalib::string,DenseTensorBuilder::Dimension> dimension_map;
for (const auto &dimension: type.dimensions()) {
@@ -151,7 +141,7 @@ DefaultTensorEngine::from_spec(const TensorSpec &spec) const
builder.addCell(cell.second);
}
return builder.build();
- } else if (is_sparse) {
+ } else if (type.is_sparse()) {
DefaultTensor::builder builder;
std::map<vespalib::string,DefaultTensor::builder::Dimension> dimension_map;
for (const auto &dimension: type.dimensions()) {
diff --git a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp b/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp
index f55566fe199..842e064de43 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp
+++ b/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp
@@ -20,6 +20,9 @@ using namespace eval::operation;
namespace {
bool is_concrete_dense_tensor(const ValueType &type) {
+ if (type.cell_type() != ValueType::CellType::DOUBLE) {
+ return false; // non-double cell types not supported
+ }
return type.is_dense();
}
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 859a7092ce2..988edba7d55 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
@@ -51,23 +51,12 @@ DenseDotProductFunction::compile_self(Stash &) const
bool
DenseDotProductFunction::compatible_types(const ValueType &res, const ValueType &lhs, const ValueType &rhs)
{
- if (!res.is_double() || !lhs.is_dense() || !rhs.is_dense() ||
- (lhs.dimensions().size() != rhs.dimensions().size()) ||
- (lhs.dimensions().empty()))
+ if (lhs.cell_type() != ValueType::CellType::DOUBLE ||
+ rhs.cell_type() != ValueType::CellType::DOUBLE)
{
- return false;
+ return false; // non-double cell types not supported
}
- for (size_t i = 0; i < lhs.dimensions().size(); ++i) {
- const auto &ldim = lhs.dimensions()[i];
- const auto &rdim = rhs.dimensions()[i];
- bool first = (i == 0);
- bool name_mismatch = (ldim.name != rdim.name);
- bool size_mismatch = ((ldim.size != rdim.size) || !ldim.is_bound());
- if (name_mismatch || (!first && size_mismatch)) {
- return false;
- }
- }
- return true;
+ return (res.is_double() && lhs.is_dense() && (rhs == lhs));
}
const TensorFunction &
diff --git a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp b/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp
index b32a1efa234..09977df25b7 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp
+++ b/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp
@@ -22,6 +22,11 @@ bool is_concrete_dense_stable_rename(const ValueType &from_type, const ValueType
const std::vector<vespalib::string> &from,
const std::vector<vespalib::string> &to)
{
+ if (from_type.cell_type() != ValueType::CellType::DOUBLE ||
+ to_type.cell_type() != ValueType::CellType::DOUBLE)
+ {
+ return false; // non-double cell types not supported
+ }
if (!from_type.is_dense() ||
!to_type.is_dense() ||
(from.size() != to.size()))
diff --git a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp
index 4828808683a..ce6b1743951 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp
+++ b/eval/src/vespa/eval/tensor/dense/dense_inplace_join_function.cpp
@@ -41,6 +41,11 @@ void my_inplace_join_op(eval::InterpretedFunction::State &state, uint64_t param)
}
bool sameShapeConcreteDenseTensors(const ValueType &a, const ValueType &b) {
+ if (a.cell_type() != ValueType::CellType::DOUBLE ||
+ b.cell_type() != ValueType::CellType::DOUBLE)
+ {
+ return false; // non-double cell types not supported
+ }
return (a.is_dense() && (a == b));
}
diff --git a/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.cpp
index bac1e336292..c72889ca0ed 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.cpp
+++ b/eval/src/vespa/eval/tensor/dense/dense_inplace_map_function.cpp
@@ -30,6 +30,9 @@ void my_inplace_map_op(eval::InterpretedFunction::State &state, uint64_t param)
}
bool isConcreteDenseTensor(const ValueType &type) {
+ if (type.cell_type() != ValueType::CellType::DOUBLE) {
+ return false; // non-double cell types not supported
+ }
return type.is_dense();
}
diff --git a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp b/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp
index d6716e8ad1a..3c58320a6e6 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp
+++ b/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp
@@ -15,6 +15,9 @@ using namespace eval::tensor_function;
namespace {
bool is_concrete_dense_tensor(const ValueType &type) {
+ if (type.cell_type() != ValueType::CellType::DOUBLE) {
+ return false; // non-double cell types not supported
+ }
return type.is_dense();
}
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 660e5e3e0b7..a3056311fab 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
@@ -76,6 +76,9 @@ void my_xw_product_op(eval::InterpretedFunction::State &state, uint64_t param) {
}
bool isConcreteDenseTensor(const ValueType &type, size_t d) {
+ if (type.cell_type() != ValueType::CellType::DOUBLE) {
+ return false; // non-double cell types not supported
+ }
return (type.is_dense() && (type.dimensions().size() == d));
}
diff --git a/eval/src/vespa/eval/tensor/tensor.cpp b/eval/src/vespa/eval/tensor/tensor.cpp
index 51c94aab5b0..5697458f3ca 100644
--- a/eval/src/vespa/eval/tensor/tensor.cpp
+++ b/eval/src/vespa/eval/tensor/tensor.cpp
@@ -17,6 +17,9 @@ Tensor::supported(TypeList types)
bool sparse = false;
bool dense = false;
for (const eval::ValueType &type: types) {
+ if (type.cell_type() != eval::ValueType::CellType::DOUBLE) {
+ return false; // non-double cell types not supported
+ }
dense = (dense || type.is_double());
for (const auto &dim: type.dimensions()) {
dense = (dense || dim.is_indexed());