Removed constant folding for Tile op (#1595)
authorIlya Churaev <ilya.churaev@intel.com>
Tue, 4 Aug 2020 04:42:23 +0000 (07:42 +0300)
committerGitHub <noreply@github.com>
Tue, 4 Aug 2020 04:42:23 +0000 (07:42 +0300)
14 files changed:
inference-engine/src/readers/ir_reader/ie_ir_parser.cpp
ngraph/src/ngraph/CMakeLists.txt
ngraph/src/ngraph/op/tile.cpp
ngraph/src/ngraph/op/tile.hpp
ngraph/src/ngraph/pass/constant_folding.hpp
ngraph/src/ngraph/pass/constant_folding_tile.cpp [deleted file]
ngraph/src/ngraph/runtime/reference/tile.cpp [new file with mode: 0644]
ngraph/src/ngraph/runtime/reference/tile.hpp
ngraph/src/ngraph/serializer.cpp
ngraph/test/backend/tile.in.cpp
ngraph/test/constant_folding.cpp
ngraph/test/op_is.cpp
ngraph/test/runtime/opset0_tbl.hpp
ngraph/test/type_prop/tile.cpp

index 6e5c856..8d9f63a 100644 (file)
@@ -354,7 +354,7 @@ std::shared_ptr<ngraph::Node> V10Parser::createNode(const std::vector<ngraph::Ou
         std::make_shared<LayerCreator<ngraph::op::Squeeze>>("Squeeze"),
         std::make_shared<LayerCreator<ngraph::op::Tan>>("Tan"),
         std::make_shared<LayerCreator<ngraph::op::Tanh>>("TanH"),
-        std::make_shared<LayerCreator<ngraph::op::Tile>>("Tile"),
+        std::make_shared<LayerCreator<ngraph::op::v0::Tile>>("Tile"),
         std::make_shared<LayerCreator<ngraph::op::v1::TopK>>("TopK"),
         std::make_shared<LayerCreator<ngraph::op::TensorIterator>>("TensorIterator"),
         std::make_shared<LayerCreator<ngraph::op::Transpose>>("Transpose"),
@@ -1232,11 +1232,11 @@ std::shared_ptr<ngraph::Node> V10Parser::LayerCreator<ngraph::op::Result>::creat
 
 // Tile layer
 template <>
-std::shared_ptr<ngraph::Node> V10Parser::LayerCreator<ngraph::op::Tile>::createLayer(
+std::shared_ptr<ngraph::Node> V10Parser::LayerCreator<ngraph::op::v0::Tile>::createLayer(
     const ngraph::OutputVector& inputs, const pugi::xml_node& node, std::istream& binStream,
     const GenericLayerParams& layerParsePrms) {
     checkParameters(inputs, layerParsePrms, 2);
-    return std::make_shared<ngraph::op::Tile>(inputs[0], inputs[1]);
+    return std::make_shared<ngraph::op::v0::Tile>(inputs[0], inputs[1]);
 }
 
 // StridedSlice layer
index 10b9574..7c48e4f 100644 (file)
@@ -451,7 +451,6 @@ set (SRC
     pass/constant_folding_slice.cpp
     pass/constant_folding_split.cpp
     pass/constant_folding_variadic_split.cpp
-    pass/constant_folding_tile.cpp
     pass/constant_folding.cpp
     pass/constant_folding.hpp
     pass/convert_fp32_to_fp16.hpp
@@ -516,6 +515,8 @@ set (SRC
     runtime/reference/eval_helpers.hpp
     runtime/reference/reshape.cpp
     runtime/reference/reshape.hpp
+    runtime/reference/tile.cpp
+    runtime/reference/tile.hpp
     shape.cpp
     shape.hpp
     shape_util.cpp
index eb8780e..1c9d1d6 100644 (file)
 #include "ngraph/op/tile.hpp"
 
 #include "ngraph/op/constant.hpp"
+#include "ngraph/runtime/reference/tile.hpp"
 
 using namespace std;
 using namespace ngraph;
 
-constexpr NodeTypeInfo op::Tile::type_info;
+constexpr NodeTypeInfo op::v0::Tile::type_info;
 
-op::Tile::Tile(const Output<Node>& data, const Output<Node>& repeats)
+op::v0::Tile::Tile(const Output<Node>& data, const Output<Node>& repeats)
     : Op({data, repeats})
 {
     constructor_validate_and_infer_types();
@@ -34,7 +35,7 @@ bool ngraph::op::v0::Tile::visit_attributes(AttributeVisitor& visitor)
     return true;
 }
 
-void op::Tile::validate_and_infer_types()
+void op::v0::Tile::validate_and_infer_types()
 {
     auto arg_et = get_input_element_type(0);
 
@@ -88,8 +89,37 @@ void op::Tile::validate_and_infer_types()
     set_input_is_relevant_to_shape(1);
 }
 
-shared_ptr<Node> op::Tile::clone_with_new_inputs(const OutputVector& new_args) const
+shared_ptr<Node> op::v0::Tile::clone_with_new_inputs(const OutputVector& new_args) const
 {
     check_new_args_count(this, new_args);
     return make_shared<Tile>(new_args.at(0), new_args.at(1));
 }
+
+bool op::v0::Tile::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs)
+{
+    const auto& data = inputs[0];
+    const auto& axis = inputs[1];
+    auto& output = outputs[0];
+    auto repeats_val = read_vector<int64_t>(axis);
+    auto repeats_rank = repeats_val.size();
+    Shape data_shape = data->get_shape();
+    auto data_rank = data_shape.size();
+    auto output_rank = std::max(data_rank, repeats_rank);
+
+    // expand data shape and repeats to output rank
+    data_shape.insert(data_shape.begin(), output_rank - data_rank, 1);
+    repeats_val.insert(repeats_val.begin(), output_rank - repeats_rank, 1);
+
+    Shape output_shape(output_rank);
+    for (size_t i = 0; i < output_rank; i++)
+    {
+        output_shape[i] = data_shape[i] * repeats_val[i];
+    }
+    runtime::reference::tile(data->get_data_ptr<const char>(),
+                             output->get_data_ptr<char>(),
+                             data->get_shape(),
+                             output_shape,
+                             data->get_element_type().size());
+
+    return true;
+}
index e3c503b..7d49f49 100644 (file)
@@ -17,6 +17,7 @@
 #pragma once
 
 #include "ngraph/op/op.hpp"
+#include "ngraph/runtime/host_tensor.hpp"
 
 namespace ngraph
 {
@@ -43,8 +44,10 @@ namespace ngraph
 
                 virtual std::shared_ptr<Node>
                     clone_with_new_inputs(const OutputVector& new_args) const override;
+
+                bool evaluate(const HostTensorVector& outputs,
+                              const HostTensorVector& inputs) override;
             };
         }
-        using v0::Tile;
     }
 }
index 2de3be5..c2f4729 100644 (file)
@@ -52,7 +52,6 @@ public:
         construct_constant_slice();
         construct_constant_select();
         construct_constant_one_hot();
-        construct_constant_tile();
         construct_constant_default();
     }
 
@@ -71,7 +70,6 @@ private:
     void construct_constant_split();
     void construct_constant_variadic_split();
     void construct_constant_one_hot();
-    void construct_constant_tile();
     void construct_constant_default();
 
     ngraph::BuildNodeExecutorMap m_cfmap;
diff --git a/ngraph/src/ngraph/pass/constant_folding_tile.cpp b/ngraph/src/ngraph/pass/constant_folding_tile.cpp
deleted file mode 100644 (file)
index 4003e5f..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-//*****************************************************************************
-// Copyright 2017-2020 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//*****************************************************************************
-
-#include "constant_folding.hpp"
-#include "ngraph/op/tile.hpp"
-#include "ngraph/runtime/reference/tile.hpp"
-
-using namespace std;
-using namespace ngraph;
-
-template <typename T>
-static shared_ptr<op::Constant> fold_constant_tile(const shared_ptr<op::Constant>& data,
-                                                   const shared_ptr<Node>& tile)
-{
-    runtime::AlignedBuffer buffer(shape_size(tile->get_shape()) * sizeof(T));
-    T* data_ptr = buffer.get_ptr<T>();
-    // No need to call the reference kernel.
-    if (shape_size(tile->get_shape()) == 0)
-    {
-        return make_shared<op::Constant>(
-            tile->get_output_element_type(0), tile->get_output_shape(0), data_ptr);
-    }
-
-    if (auto tile_v0 = as_type_ptr<op::v0::Tile>(tile))
-    {
-        runtime::reference::tile<T>(
-            data->get_data_ptr<T>(), data_ptr, data->get_shape(), tile_v0->get_shape());
-    }
-    else
-    {
-        throw ngraph_error("Unsupported op in tile constant folding.");
-    }
-
-    return make_shared<op::Constant>(
-        tile->get_output_element_type(0), tile->get_output_shape(0), data_ptr);
-}
-
-void pass::ConstantFolding::construct_constant_tile()
-{
-    auto data_label = make_shared<pattern::op::Label>(
-        element::f32, Shape{2, 2, 3}, pattern::has_class<op::Constant>());
-    auto repeats_label =
-        make_shared<pattern::op::Label>(element::i64, Shape{3}, pattern::has_class<op::Constant>());
-    auto tile_v0 = make_shared<op::v0::Tile>(data_label, repeats_label);
-
-    auto constant_tile_callback = [data_label](pattern::Matcher& m) {
-        NGRAPH_DEBUG << "In callback for constant_tile_callback against node = "
-                     << m.get_match_root()->get_name();
-
-        auto pattern_map = m.get_pattern_map();
-
-        auto data = static_pointer_cast<op::Constant>(pattern_map[data_label]);
-        auto tile = m.get_match_root();
-
-        NGRAPH_CHECK(revalidate_and_ensure_static(tile));
-
-        std::shared_ptr<Node> replacement;
-        auto data_type = data->get_output_element_type(0);
-        switch (data_type)
-        {
-        case element::Type_t::undefined:
-            NGRAPH_CHECK(false, "Encountered 'undefined' element type in constant_tile_callback");
-            break;
-        case element::Type_t::dynamic:
-            NGRAPH_CHECK(false, "Encountered 'dynamic' element type in constant_tile_callback");
-            break;
-        case element::Type_t::u1:
-            NGRAPH_CHECK(false, "Encountered 'u1' element type in constant_tile_callback");
-            break;
-        case element::Type_t::boolean: replacement = fold_constant_tile<char>(data, tile); break;
-        case element::Type_t::bf16: replacement = fold_constant_tile<bfloat16>(data, tile); break;
-        case element::Type_t::f16: replacement = fold_constant_tile<float16>(data, tile); break;
-        case element::Type_t::f32: replacement = fold_constant_tile<float>(data, tile); break;
-        case element::Type_t::f64: replacement = fold_constant_tile<double>(data, tile); break;
-        case element::Type_t::i8: replacement = fold_constant_tile<int8_t>(data, tile); break;
-        case element::Type_t::i16: replacement = fold_constant_tile<int16_t>(data, tile); break;
-        case element::Type_t::i32: replacement = fold_constant_tile<int32_t>(data, tile); break;
-        case element::Type_t::i64: replacement = fold_constant_tile<int64_t>(data, tile); break;
-        case element::Type_t::u8: replacement = fold_constant_tile<uint8_t>(data, tile); break;
-        case element::Type_t::u16: replacement = fold_constant_tile<uint16_t>(data, tile); break;
-        case element::Type_t::u32: replacement = fold_constant_tile<uint32_t>(data, tile); break;
-        case element::Type_t::u64: replacement = fold_constant_tile<uint64_t>(data, tile); break;
-        }
-
-        replace_node(m.get_match_root(), replacement);
-        return true;
-    };
-
-    auto tile_matcher_v0 = make_shared<pattern::Matcher>(tile_v0, "ConstantFolding.ConstantTileV0");
-    this->add_matcher(tile_matcher_v0, constant_tile_callback, PassProperty::CHANGE_DYNAMIC_STATE);
-}
diff --git a/ngraph/src/ngraph/runtime/reference/tile.cpp b/ngraph/src/ngraph/runtime/reference/tile.cpp
new file mode 100644 (file)
index 0000000..335a530
--- /dev/null
@@ -0,0 +1,47 @@
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//*****************************************************************************
+
+#include <cmath>
+#include <stdio.h>
+
+#include "ngraph/check.hpp"
+#include "ngraph/runtime/reference/tile.hpp"
+
+using namespace ngraph;
+
+void runtime::reference::tile(
+    const char* arg, char* out, const Shape& in_shape, const Shape& out_shape, size_t elem_size)
+{
+    Shape in_shape_expanded(in_shape);
+    in_shape_expanded.insert(in_shape_expanded.begin(), out_shape.size() - in_shape.size(), 1);
+    CoordinateTransform input_transform(in_shape_expanded);
+    CoordinateTransform output_transform(out_shape);
+
+    for (const Coordinate& output_coord : output_transform)
+    {
+        std::vector<size_t> coord;
+        for (auto i = 0; i < output_coord.size(); i++)
+        {
+            auto val = output_coord[i] % in_shape_expanded[i];
+            coord.push_back(val);
+        }
+        Coordinate input_coord(coord);
+
+        memcpy(out + output_transform.index(output_coord) * elem_size,
+               arg + input_transform.index(input_coord) * elem_size,
+               elem_size);
+    }
+}
index 653eb0e..53d25ee 100644 (file)
@@ -19,6 +19,7 @@
 #include <cmath>
 
 #include "ngraph/coordinate_transform.hpp"
+#include "ngraph/type/element_type.hpp"
 
 namespace ngraph
 {
@@ -26,28 +27,11 @@ namespace ngraph
     {
         namespace reference
         {
-            template <typename T>
-            void tile(const T* arg, T* out, const Shape& in_shape, const Shape& out_shape)
-            {
-                Shape in_shape_expanded(in_shape);
-                in_shape_expanded.insert(
-                    in_shape_expanded.begin(), out_shape.size() - in_shape.size(), 1);
-                CoordinateTransform input_transform(in_shape_expanded);
-                CoordinateTransform output_transform(out_shape);
-
-                for (const Coordinate& output_coord : output_transform)
-                {
-                    std::vector<size_t> coord;
-                    for (auto i = 0; i < output_coord.size(); i++)
-                    {
-                        auto val = output_coord[i] % in_shape_expanded[i];
-                        coord.push_back(val);
-                    }
-                    Coordinate input_coord(coord);
-                    out[output_transform.index(output_coord)] =
-                        arg[input_transform.index(input_coord)];
-                }
-            }
+            void tile(const char* arg,
+                      char* out,
+                      const Shape& in_shape,
+                      const Shape& out_shape,
+                      size_t elem_size);
         }
     }
 }
index f385b16..f9c9e37 100644 (file)
@@ -1843,7 +1843,7 @@ shared_ptr<Node> JSONDeserializer::deserialize_node(json node_js)
 
         case OP_TYPEID::Tile:
         {
-            node = make_shared<op::Tile>(args[0], args[1]);
+            node = make_shared<op::v0::Tile>(args[0], args[1]);
             break;
         }
         case OP_TYPEID::TopK:
index 68fc6ea..d9b4b5d 100644 (file)
@@ -44,7 +44,7 @@ NGRAPH_TEST(${BACKEND_NAME}, tile_3d_small_data_rank)
     auto repeats = make_shared<op::Constant>(element::i64, shape_re, vector<int>{2, 2, 1});
     Shape shape_r{2, 2, 3};
 
-    auto tile = make_shared<op::Tile>(A, repeats);
+    auto tile = make_shared<op::v0::Tile>(A, repeats);
 
     auto f = make_shared<Function>(tile, ParameterVector{A});
 
@@ -71,7 +71,7 @@ NGRAPH_TEST(${BACKEND_NAME}, tile_3d_few_repeats)
     auto repeats = make_shared<op::Constant>(element::i64, shape_re, vector<int>{2, 1});
     Shape shape_r{2, 2, 3};
 
-    auto tile = make_shared<op::Tile>(A, repeats);
+    auto tile = make_shared<op::v0::Tile>(A, repeats);
 
     auto f = make_shared<Function>(tile, ParameterVector{A});
 
index f175f3b..efaaf5e 100644 (file)
@@ -2658,7 +2658,7 @@ TEST(constant_folding, constant_tile_1d)
     pass_manager.register_pass<pass::ConstantFolding>();
     pass_manager.run_passes(f);
 
-    ASSERT_EQ(count_ops_of_type<op::Tile>(f), 0);
+    ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
     ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
 
     auto new_const =
@@ -2687,7 +2687,7 @@ TEST(constant_folding, constant_tile_3d_small_data_rank)
     pass_manager.register_pass<pass::ConstantFolding>();
     pass_manager.run_passes(f);
 
-    ASSERT_EQ(count_ops_of_type<op::Tile>(f), 0);
+    ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
     ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
 
     auto new_const =
@@ -2716,7 +2716,7 @@ TEST(constant_folding, constant_tile_3d_few_repeats)
     pass_manager.register_pass<pass::ConstantFolding>();
     pass_manager.run_passes(f);
 
-    ASSERT_EQ(count_ops_of_type<op::Tile>(f), 0);
+    ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
     ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
 
     auto new_const =
@@ -2745,7 +2745,7 @@ TEST(constant_folding, constant_tile_1d_0_repeats)
     pass_manager.register_pass<pass::ConstantFolding>();
     pass_manager.run_passes(f);
 
-    ASSERT_EQ(count_ops_of_type<op::Tile>(f), 0);
+    ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
     ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
 
     auto new_const =
@@ -2774,7 +2774,7 @@ TEST(constant_folding, constant_tile_0_rank_data)
     pass_manager.register_pass<pass::ConstantFolding>();
     pass_manager.run_passes(f);
 
-    ASSERT_EQ(count_ops_of_type<op::Tile>(f), 0);
+    ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
     ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
 
     auto new_const =
index 33c97a5..de3d1a3 100644 (file)
@@ -965,7 +965,7 @@ namespace
 
     void op_is_Tile()
     {
-        op::Tile node;
+        op::v0::Tile node;
         EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
         EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
         EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
index 81fbe21..e1c5eb5 100644 (file)
@@ -150,7 +150,7 @@ NGRAPH_OP(Sum, ngraph::op)
 NGRAPH_OP(Tan, ngraph::op)
 NGRAPH_OP(Tanh, ngraph::op)
 NGRAPH_OP(TensorIterator, ngraph::op)
-NGRAPH_OP(Tile, ngraph::op)
+NGRAPH_OP(Tile, ngraph::op::v0)
 NGRAPH_OP(TopK, ngraph::op::v0)
 NGRAPH_OP(Unsqueeze, ngraph::op)
 NGRAPH_OP(Xor, ngraph::op)
index db3761a..e3c9a30 100644 (file)
@@ -25,7 +25,7 @@ TEST(type_prop, tile)
 {
     auto param0 = make_shared<op::Parameter>(element::f32, Shape{6, 8, 10});
     auto param1 = op::Constant::create(element::i64, Shape{3}, {3, 4, 1});
-    auto top = make_shared<op::Tile>(param0, param1);
+    auto top = make_shared<op::v0::Tile>(param0, param1);
     ASSERT_EQ(top->get_element_type(), element::f32);
     ASSERT_EQ(top->get_shape(), (Shape{18, 32, 10}));
 }
@@ -34,7 +34,7 @@ TEST(type_prop, tile_small_data_rank)
 {
     auto param0 = make_shared<op::Parameter>(element::f32, Shape{8, 10});
     auto param1 = op::Constant::create(element::i64, Shape{3}, {3, 4, 1});
-    auto top = make_shared<op::Tile>(param0, param1);
+    auto top = make_shared<op::v0::Tile>(param0, param1);
     ASSERT_EQ(top->get_element_type(), element::f32);
     ASSERT_EQ(top->get_shape(), (Shape{3, 32, 10}));
 }
@@ -43,7 +43,7 @@ TEST(type_prop, tile_few_repeats)
 {
     auto param0 = make_shared<op::Parameter>(element::f32, Shape{6, 8, 10});
     auto param1 = op::Constant::create(element::i64, Shape{2}, {4, 1});
-    auto top = make_shared<op::Tile>(param0, param1);
+    auto top = make_shared<op::v0::Tile>(param0, param1);
     ASSERT_EQ(top->get_element_type(), element::f32);
     ASSERT_EQ(top->get_shape(), (Shape{6, 32, 10}));
 }