From ffa0ce89d3c785383ff623a20f94e94997d62fb8 Mon Sep 17 00:00:00 2001 From: bokyeong lee Date: Wed, 11 Sep 2024 15:06:24 +0900 Subject: [PATCH 1/6] [luci/service] migrate Range shape inference rule to sinf::Algorithm This commit migrate Range shape inference rule to sinf::Algorithm. ONE-DCO-1.0-Signed-off-by: bokyeong Lee --- .../luci/Service/CircleShapeInference.h | 2 +- .../service/src/CircleShapeInferenceRule.cpp | 45 ----------------- .../luci/service/src/Nodes/CircleRange.cpp | 48 +++++++++++++++++++ 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/compiler/luci/service/include/luci/Service/CircleShapeInference.h b/compiler/luci/service/include/luci/Service/CircleShapeInference.h index ee069d882e2..b9be778a908 100644 --- a/compiler/luci/service/include/luci/Service/CircleShapeInference.h +++ b/compiler/luci/service/include/luci/Service/CircleShapeInference.h @@ -112,7 +112,7 @@ class Algorithm final : public luci::CircleNodeVisitor // loco::TensorShape visit(const luci::CirclePow *node) final; // loco::TensorShape visit(const luci::CirclePRelu *node) final; loco::TensorShape visit(const luci::CircleQuantize *node) final; - // loco::TensorShape visit(const luci::CircleRange *node) final; + loco::TensorShape visit(const luci::CircleRange *node) final; // loco::TensorShape visit(const luci::CircleRank *node) final; // loco::TensorShape visit(const luci::CircleReduceAny *node) final; // loco::TensorShape visit(const luci::CircleReduceMax *node) final; diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp index 6ae15f70494..4fa8405a5bc 100644 --- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp +++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp @@ -911,49 +911,6 @@ loco::NodeShape infer_p_relu(const luci::CirclePRelu *node) return loco::NodeShape{output_shape}; } -loco::NodeShape infer_range(const luci::CircleRange *node) -{ - loco::TensorShape output_shape; - output_shape.rank(1); - - auto start_node = dynamic_cast(node->start()); - auto limit_node = dynamic_cast(node->limit()); - auto delta_node = dynamic_cast(node->delta()); - - if (start_node == nullptr || limit_node == nullptr || delta_node == nullptr) - { - return use_own(node); - } - - double start = 0, limit = 0, delta = 0; - -#define GET_RANGE_PARAM(DT) \ - start = start_node->scalar
(); \ - limit = limit_node->scalar
(); \ - delta = delta_node->scalar
(); - - switch (start_node->dtype()) - { - case loco::DataType::FLOAT32: - GET_RANGE_PARAM(loco::DataType::FLOAT32) - break; - case loco::DataType::S32: - GET_RANGE_PARAM(loco::DataType::S32) - break; - default: - INTERNAL_EXN("Range data type not supported"); - } - -#undef GET_RANGE_PARAM - - if (delta == 0) - INTERNAL_EXN("Delta can not be zero"); - - output_shape.dim(0) = ceil((limit - start) / delta); - - return loco::NodeShape{output_shape}; -} - loco::NodeShape infer_reshape(const luci::CircleReshape *node) { LOGGER(l); @@ -2104,8 +2061,6 @@ class ShapeInferenceAlgorithm final : public luci::CircleNodeVisitor::visit(const luci::CircleRange *) return _graph->nodes()->create(); } +namespace sinf +{ + +loco::TensorShape Algorithm::visit(const luci::CircleRange *node) +{ + loco::TensorShape output_shape; + output_shape.rank(1); + + auto start_node = dynamic_cast(node->start()); + auto limit_node = dynamic_cast(node->limit()); + auto delta_node = dynamic_cast(node->delta()); + + if (start_node == nullptr || limit_node == nullptr || delta_node == nullptr) + { + return output_shape; + } + + double start = 0, limit = 0, delta = 0; + +#define GET_RANGE_PARAM(DT) \ + start = start_node->scalar
(); \ + limit = limit_node->scalar
(); \ + delta = delta_node->scalar
(); + + switch (start_node->dtype()) + { + case loco::DataType::FLOAT32: + GET_RANGE_PARAM(loco::DataType::FLOAT32) + break; + case loco::DataType::S32: + GET_RANGE_PARAM(loco::DataType::S32) + break; + default: + INTERNAL_EXN("Range data type not supported"); + } + +#undef GET_RANGE_PARAM + + if (delta == 0) + INTERNAL_EXN("Delta can not be zero"); + + output_shape.dim(0) = ceil((limit - start) / delta); + + return output_shape; +} + +} // namespace sinf + } // namespace luci From a1d4c753668f17274aa3c5c70187a6903601d6f9 Mon Sep 17 00:00:00 2001 From: bokyeong lee Date: Wed, 11 Sep 2024 15:42:37 +0900 Subject: [PATCH 2/6] [luci/service] add include This commit add include code. ONE-DCO-1.0-Signed-off-by: bokyeong lee --- compiler/luci/service/src/Nodes/CircleRange.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp index ba8f45579c7..a66358ec11e 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -14,7 +14,12 @@ * limitations under the License. */ +#include "luci/Service/CircleShapeInference.h" + #include "CircleCloneNode.h" +#include "CircleShapeInferenceHelper.h" + +#include namespace luci { From 1f3e0fdc79e36477cfd8041303f9597b970abdb6 Mon Sep 17 00:00:00 2001 From: bokyeong lee Date: Wed, 11 Sep 2024 17:45:30 +0900 Subject: [PATCH 3/6] [luci/service] copy own_shape function with non-const params This commit copy own_shape function with non-contst params. ONE-DCO-1.0-Signed-off-by: bokyeong Lee --- compiler/luci/service/src/Nodes/CircleRange.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp index a66358ec11e..227165085ab 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -43,7 +43,20 @@ loco::TensorShape Algorithm::visit(const luci::CircleRange *node) if (start_node == nullptr || limit_node == nullptr || delta_node == nullptr) { - return output_shape; + // We use shape from the node itself + loco::TensorShape shape; + shape.rank(node->rank()); + for (uint32_t r = 0; r < node->rank(); ++r) + { + // Shape inference rules in this file did not consider unknown dimension. + // If some node has unknown dimension, 0 is inserted and wrong shape + // inference was done as a result. + // To fix this, new shape inference algorithm is being implemented. + // Until new inference algorithm is fully implemented, unknown dimension + // would be represented as 1 along with TFLite expression. + shape.dim(r) = node->dim(r).known() ? node->dim(r).value() : 1; + } + return shape; } double start = 0, limit = 0, delta = 0; From 297a18709eb9676c5994bbc5fe2a35d513cb877f Mon Sep 17 00:00:00 2001 From: bokyeong lee Date: Wed, 11 Sep 2024 17:58:24 +0900 Subject: [PATCH 4/6] [luci/service] add tests for range with const param This commit add tests for range with const param. ONE-DCO-1.0-Signed-off-by: bokyeong Lee --- .../luci/service/src/Nodes/CircleRange.cpp | 2 + .../service/src/Nodes/CircleRange.test.cpp | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp index 227165085ab..defdfe3250e 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -83,6 +83,8 @@ loco::TensorShape Algorithm::visit(const luci::CircleRange *node) if (delta == 0) INTERNAL_EXN("Delta can not be zero"); + // 'limit-start' and 'delta' have the same sign. + // refer: https://github.com/tensorflow/tensorflow/blob/da82fa9d392d7c3cea3d86b516e55441e963b784/tensorflow/lite/kernels/range.cc#L49-L50 output_shape.dim(0) = ceil((limit - start) / delta); return output_shape; diff --git a/compiler/luci/service/src/Nodes/CircleRange.test.cpp b/compiler/luci/service/src/Nodes/CircleRange.test.cpp index b2fb296177a..b67d287d1ab 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.test.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.test.cpp @@ -15,6 +15,7 @@ */ #include "luci/Service/CircleNodeClone.h" +#include "luci/Service/CircleShapeInference.h" #include @@ -31,3 +32,66 @@ TEST(CloneNodeTest, clone_Range) auto cloned_range = dynamic_cast(cloned); ASSERT_NE(nullptr, cloned_range); } + +TEST(ShapeRuleTest, range_const_param) +{ + luci::CircleConst start, limit, delta; + luci::CircleRange range; + + start.dtype(loco::DataType::S32); + start.size(1); + start.at(0) = 0; + start.shape_status(luci::ShapeStatus::VALID); + + limit.dtype(loco::DataType::S32); + limit.size(1); + limit.at(0) = 10; + limit.shape_status(luci::ShapeStatus::VALID); + + delta.dtype(loco::DataType::S32); + delta.size(1); + delta.at(0) = 2; + delta.shape_status(luci::ShapeStatus::VALID); + + range.start(&start); + range.limit(&limit); + range.delta(&delta); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&range, shape)); + ASSERT_EQ(1, shape.rank()); + ASSERT_TRUE(shape.dim(0).known()); + ASSERT_EQ(5, shape.dim(0).value()); +} + +TEST(ShapeRuleTest, range_zero_delta_NEG) +{ + luci::CircleConst start, limit, delta; + luci::CircleRange range; + + start.dtype(loco::DataType::S32); + start.size(1); + start.at(0) = 0; + start.shape_status(luci::ShapeStatus::VALID); + + limit.dtype(loco::DataType::S32); + limit.size(1); + limit.at(0) = 10; + limit.shape_status(luci::ShapeStatus::VALID); + + delta.dtype(loco::DataType::S32); + delta.size(1); + delta.at(0) = 0; + delta.shape_status(luci::ShapeStatus::VALID); + + range.start(&start); + range.limit(&limit); + range.delta(&delta); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_ANY_THROW(shape_inf_rule.infer(&range, shape)); +} From 5c474bca90ad75b5bebcb1b78ecededf70cfced1 Mon Sep 17 00:00:00 2001 From: bokyeong lee Date: Wed, 11 Sep 2024 18:03:03 +0900 Subject: [PATCH 5/6] [luci/service] remove comment This commit remove comment. ONE-DCO-1.0-Signed-off-by: bokyeong Lee --- compiler/luci/service/src/Nodes/CircleRange.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp index defdfe3250e..227165085ab 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -83,8 +83,6 @@ loco::TensorShape Algorithm::visit(const luci::CircleRange *node) if (delta == 0) INTERNAL_EXN("Delta can not be zero"); - // 'limit-start' and 'delta' have the same sign. - // refer: https://github.com/tensorflow/tensorflow/blob/da82fa9d392d7c3cea3d86b516e55441e963b784/tensorflow/lite/kernels/range.cc#L49-L50 output_shape.dim(0) = ceil((limit - start) / delta); return output_shape; From 2ea01beb486bf861be439f6d5bbdeab1e4890b8d Mon Sep 17 00:00:00 2001 From: bokyeong-Lee <149753416+kyeong8139@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:06:10 +0900 Subject: [PATCH 6/6] [luci/service] revise comment This commit revise comment about use_own() ONE-DCO-1.0-Signed-off-by: Bokyeong Lee k Co-authored-by: SaeHie Park --- compiler/luci/service/src/Nodes/CircleRange.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp index 227165085ab..b2c8be4d5f8 100644 --- a/compiler/luci/service/src/Nodes/CircleRange.cpp +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -48,6 +48,7 @@ loco::TensorShape Algorithm::visit(const luci::CircleRange *node) shape.rank(node->rank()); for (uint32_t r = 0; r < node->rank(); ++r) { + // TODO remove this copy from `use_own(node);` // Shape inference rules in this file did not consider unknown dimension. // If some node has unknown dimension, 0 is inserted and wrong shape // inference was done as a result.