From 3b80333858c972edf3b31a2c082ff651272a34b0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=82=A8=EA=B6=81=EC=84=9D/On-Device=20Lab=28SR=29/Enginee?= =?utf8?q?r/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Thu, 19 Sep 2019 13:05:44 +0900 Subject: [PATCH] [moco-tf] Support TFMean Canonicalization (#7594) * [moco-tf] Support TFMean Canonicalization This commit will enable for supporting `TFMean` canonicalization Signed-off-by: Seok NamKoong * apply comments --- .../src/Canonicalization/MeanCanonicalizer.cpp | 47 ++++++++ .../src/Canonicalization/MeanCanonicalizer.h | 44 ++++++++ compiler/moco-tf/src/Canonicalizer.cpp | 2 + compiler/moco-tf/src/TFReduceCanonicalzeHelper.h | 118 +++++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.cpp create mode 100644 compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.h create mode 100644 compiler/moco-tf/src/TFReduceCanonicalzeHelper.h diff --git a/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.cpp new file mode 100644 index 0000000..fef77a1 --- /dev/null +++ b/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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 "MeanCanonicalizer.h" +#include "TFReduceCanonicalzeHelper.h" + +namespace moco +{ +namespace tf +{ + +bool MeanCanonicalizer::run(loco::Graph *graph) +{ + auto active_nodes = loco::active_nodes(loco::output_nodes(graph)); + bool changed = false; + + for (auto node : active_nodes) + { + if (node->dialect() == TFDialect::get()) + { + auto tf_mean = dynamic_cast(node); + if (tf_mean != nullptr) + { + if (canonicalize_reduce_node(tf_mean)) + changed = true; + } + } + } + + return changed; +} + +} // namespace tf +} // namespace moco diff --git a/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.h b/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.h new file mode 100644 index 0000000..857c8b8 --- /dev/null +++ b/compiler/moco-tf/src/Canonicalization/MeanCanonicalizer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#ifndef __MOCO_TF_MEAN_CANONICALIZER_H__ +#define __MOCO_TF_MEAN_CANONICALIZER_H__ + +#include "Transform.h" + +#include + +namespace moco +{ +namespace tf +{ + +/** + * @brief Canonicalize TF-dialect TFMean into canonical TensorReduce(Mean) node + */ +class MeanCanonicalizer : public Transform +{ +public: + const char *name(void) const final { return "MeanCanonicalizer"; } + +public: + bool run(loco::Graph *graph) override; +}; + +} // namespace tf +} // namespace moco + +#endif // __MOCO_TF_MEAN_CANONICALIZER_H__ diff --git a/compiler/moco-tf/src/Canonicalizer.cpp b/compiler/moco-tf/src/Canonicalizer.cpp index c705d68..6f39ca3 100644 --- a/compiler/moco-tf/src/Canonicalizer.cpp +++ b/compiler/moco-tf/src/Canonicalizer.cpp @@ -31,6 +31,7 @@ #include "Canonicalization/DepthwiseConv2dNativeCanonicalizer.h" #include "Canonicalization/IdentityCanonicalizer.h" #include "Canonicalization/MaxPoolCanonicalizer.h" +#include "Canonicalization/MeanCanonicalizer.h" #include "Canonicalization/MulCanonicalizer.h" #include "Canonicalization/RealDivCanonicalizer.h" #include "Canonicalization/ReluCanonicalizer.h" @@ -101,6 +102,7 @@ void Canonicalizer::canonicalize(loco::Graph *g) const phase.emplace_back(stdex::make_unique()); phase.emplace_back(stdex::make_unique()); phase.emplace_back(stdex::make_unique()); + phase.emplace_back(stdex::make_unique()); phase.emplace_back(stdex::make_unique()); phase.emplace_back(stdex::make_unique()); phase.emplace_back(stdex::make_unique()); diff --git a/compiler/moco-tf/src/TFReduceCanonicalzeHelper.h b/compiler/moco-tf/src/TFReduceCanonicalzeHelper.h new file mode 100644 index 0000000..88d285c --- /dev/null +++ b/compiler/moco-tf/src/TFReduceCanonicalzeHelper.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ + +#ifndef __TF_REDUCE_CANONICALIZE_HELPER_H__ +#define __TF_REDUCE_CANONICALIZE_HELPER_H__ + +#include "Dialect/TFDialect.h" +#include "Dialect/TFNodes.h" + +#include + +#include + +namespace +{ + +template loco::ReduceFunc reduceFunc(void); + +template <> loco::ReduceFunc reduceFunc(void) { return loco::ReduceFunc::Mean; } + +template bool canonicalize_reduce_node(TFNode *node) +{ + LOGGER(l); + + INFO(l) << "TFNodeCanonicalize ReduceNode begin"; + + auto graph = node->graph(); + + /** + * This will replace T/F Reduce node with a corresponding Canonical Reduce node + * + * BEFORE + * reduction_indices -------- T/F Node -- C + * input -------/ + * + * AFTER + * +------ T/F Node -- + * | / + * reduction_indices ------- + * | \ + * input -+------ Canonical Node -- C + * + * NOTE + * - T/F Node is disconnected from C after transformation + */ + + // TFSqueeze had to be inserted if keep_dims() was false + assert(node->keep_dims()); + + auto axes_node = node->reduction_indices(); + assert(axes_node != nullptr); + + auto node_tensor_shape = loco::shape_get(node).template as(); + + // Canonicalization into TensorReduce is valid when reduction indices is constant + // TODO Support general TensorReduce case + std::vector axes_values; + if (auto const_axes = dynamic_cast(axes_node)) + { + // TODO Support S64 type + assert(const_axes->dtype() == loco::DataType::S32); + + for (uint32_t i = 0; i < const_axes->size(); ++i) + { + int32_t axis = const_axes->at(i); + if (axis < 0) + axis += node_tensor_shape.rank(); + axes_values.push_back(axis); + } + } + else if (auto const_axes = dynamic_cast(axes_node)) + { + // TODO Support S64 type + assert(const_axes->dtype() == loco::DataType::S32); + + for (uint32_t i = 0; i < const_axes->size(); ++i) + { + int32_t axis = const_axes->at(i); + if (axis < 0) + axis += node_tensor_shape.rank(); + axes_values.push_back(axis); + } + } + else + return false; + + // Create loco node to replace + auto reduce = graph->nodes()->template create(); + + // replace + reduce->func(reduceFunc()); + reduce->input(node->input()); + for (uint32_t i = 0; i < axes_values.size(); ++i) + reduce->axes()->insert(axes_values.at(i)); + + replace(node).with(reduce); + + INFO(l) << "TFNodeCanonicalize ReduceNode done"; + + return true; +} + +} // namespace + +#endif // __TF_REDUCE_CANONICALIZE_HELPER_H__ -- 2.7.4