From c054e1cb66837f0cd1e6ab211b5b1efdd03078ab Mon Sep 17 00:00:00 2001 From: Allen Guo Date: Fri, 13 Aug 2021 11:52:15 +0800 Subject: [PATCH] add op builder for canonicalization (#57) * use new pow_handler --- paddle/fluid/framework/ipu/CMakeLists.txt | 1 + .../canonicalization_utils.cc | 33 +++++- .../canonicalization_utils.h | 12 +-- .../ipu/popart_canonicalization/math_ops.cc | 48 ++------- .../ipu/popart_canonicalization/op_builder.cc | 102 ++++++++++++++++++ .../ipu/popart_canonicalization/op_builder.h | 43 ++++++++ 6 files changed, 193 insertions(+), 46 deletions(-) create mode 100644 paddle/fluid/framework/ipu/popart_canonicalization/op_builder.cc create mode 100644 paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h diff --git a/paddle/fluid/framework/ipu/CMakeLists.txt b/paddle/fluid/framework/ipu/CMakeLists.txt index 8f507765bd0ef..59a2d5da5aa30 100644 --- a/paddle/fluid/framework/ipu/CMakeLists.txt +++ b/paddle/fluid/framework/ipu/CMakeLists.txt @@ -1,5 +1,6 @@ set(POPART_CANONICALIZATION_SRC "popart_canonicalization/canonicalization_utils.cc" + "popart_canonicalization/op_builder.cc" "popart_canonicalization/activation_ops.cc" "popart_canonicalization/logic_ops.cc" "popart_canonicalization/math_ops.cc" diff --git a/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.cc b/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.cc index 0e8f3958e4230..6d238b87a45fe 100644 --- a/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.cc +++ b/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.cc @@ -59,6 +59,21 @@ void MoveNodeInputs(ir::Node *node, ir::Node *new_node) { } } +void ReplaceNodeInputs(ir::Node *node, ir::Node *new_node) { + if (node->inputs.empty()) { + return; + } + new_node->inputs = node->inputs; + for (auto *node_in : node->inputs) { + for (size_t i = 0; i < node_in->outputs.size(); ++i) { + if (node_in->outputs[i] == node) { + node_in->outputs[i] = new_node; + break; + } + } + } +} + void MoveNodeOutputs(ir::Node *node, ir::Node *new_node) { if (node->outputs.empty()) { return; @@ -74,12 +89,26 @@ void MoveNodeOutputs(ir::Node *node, ir::Node *new_node) { } } +void ReplaceNodeOutputs(ir::Node *node, ir::Node *new_node) { + if (node->outputs.empty()) { + return; + } + for (auto *node_out : node->outputs) { + for (size_t i = 0; i < node_out->inputs.size(); ++i) { + if (node_out->inputs[i] == node) { + node_out->inputs[i] = new_node; + break; + } + } + } +} + void ConnectNodes(ir::Node *first_node, ir::Node *next_node) { first_node->outputs.push_back(next_node); next_node->inputs.push_back(first_node); } -void CopyOpAttr(std::string attr_name, OpDesc *op, OpDesc *new_op, +void CopyOpAttr(const std::string &attr_name, OpDesc *op, OpDesc *new_op, bool override) { if (new_op->HasAttr(attr_name) && !override) { return; @@ -90,7 +119,7 @@ void CopyOpAttr(std::string attr_name, OpDesc *op, OpDesc *new_op, } } -int ConvertDataType(int type) { +const int ConvertDataType(const int &type) { auto dtype = static_cast(type); switch (dtype) { case proto::VarType::BOOL: diff --git a/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h b/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h index af22c900bd2c7..0b55ddc887254 100644 --- a/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h +++ b/paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h @@ -14,10 +14,6 @@ #pragma once -#include -#include -#include - #include "paddle/fluid/framework/ipu/ipu_utils.h" #include "paddle/fluid/framework/ir/graph.h" #include "paddle/fluid/framework/ir/node.h" @@ -39,13 +35,17 @@ bool RegisterHandler(const std::string &, const SymbolHandler &); SymbolHandler GetHandler(const std::string &); +// TODO(alleng) remove these func void MoveNodeInputs(ir::Node *node, ir::Node *new_node); void MoveNodeOutputs(ir::Node *node, ir::Node *new_node); + +void ReplaceNodeInputs(ir::Node *node, ir::Node *new_node); +void ReplaceNodeOutputs(ir::Node *node, ir::Node *new_node); void ConnectNodes(ir::Node *first_node, ir::Node *next_node); -void CopyOpAttr(std::string attr_name, OpDesc *op, OpDesc *new_op, +void CopyOpAttr(const std::string &attr_name, OpDesc *op, OpDesc *new_op, bool override = false); -int ConvertDataType(int); +const int ConvertDataType(const int &type); } // namespace ipu } // namespace framework diff --git a/paddle/fluid/framework/ipu/popart_canonicalization/math_ops.cc b/paddle/fluid/framework/ipu/popart_canonicalization/math_ops.cc index a27e89117fc08..0e41e5a753d7a 100644 --- a/paddle/fluid/framework/ipu/popart_canonicalization/math_ops.cc +++ b/paddle/fluid/framework/ipu/popart_canonicalization/math_ops.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h" +#include "paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h" #include "paddle/fluid/platform/enforce.h" namespace paddle { @@ -65,45 +66,16 @@ ir::Node *reduce_mean_handler(ir::Graph *graph, ir::Node *node) { ir::Node *pow_handler(ir::Graph *graph, ir::Node *node) { // Op(pow) -> Op(Constant)->Var(const_out)->Op(Pow) auto *op = node->Op(); - // Op(Constant) - auto op_const = std::make_unique(); - op_const->SetType("Constant"); - std::string op_const_out = op->Output("Out").front() + ":__0_"; auto value_ = BOOST_GET_CONST(float, op->GetAttr("factor")); - auto value = std::vector{value_}; - op_const->SetAttr("value", value); - auto dims = std::vector{1}; - op_const->SetAttr("dims", dims); - op_const->SetAttr("dtype", ONNXDataType::FLOAT); - std::vector outputs_const; - outputs_const.push_back(op_const_out); - op_const->SetOutput("__outputs__", outputs_const); - op_const->Flush(); - // Var(const_out) - auto var_const = std::make_unique(op_const_out); - var_const->SetType(proto::VarType::LOD_TENSOR); - var_const->SetDataType(proto::VarType::FP32); - auto shape_var_const = std::vector{1}; - var_const->SetShape(shape_var_const); - auto var_node_const = graph->CreateVarNode(var_const.get()); - auto node_const = graph->CreateOpNode(op_const.get()); - MoveNodeInputs(node, node_const); - ConnectNodes(node_const, var_node_const); - // Op(Pow) - auto op_pow = std::make_unique(); - op_pow->SetType("Pow"); - std::vector inputs; - inputs.push_back(op->Input("X").front()); - inputs.push_back(op_const->Output("__outputs__").front()); - op_pow->SetInput("__inputs__", inputs); - std::vector outputs; - outputs.push_back(op->Output("Out").front()); - op_pow->SetOutput("__outputs__", outputs); - op_pow->Flush(); - auto node_pow = graph->CreateOpNode(op_pow.get()); - ConnectNodes(var_node_const, node_pow); - MoveNodeOutputs(node, node_pow); - return node_pow; + auto attrs = MakeConstAttributeMap(value_, {1}, ONNXDataType::FLOAT); + auto new_node_const = CreateConst(graph, {node}, {}, attrs); + ReplaceNodeOutputs(node, new_node_const); + + auto new_node_pow = + CreatePow(graph, {node->inputs[0], new_node_const->outputs[0]}, + {node->outputs[0]}, {}); + ReplaceNodeInputs(node, new_node_pow); + return new_node_pow; } ir::Node *mul_handler(ir::Graph *graph, ir::Node *node) { diff --git a/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.cc b/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.cc new file mode 100644 index 0000000000000..ac241ba9cf122 --- /dev/null +++ b/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.cc @@ -0,0 +1,102 @@ +// Copyright (c) 2021 PaddlePaddle Authors. 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 "paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h" + +#include "paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h" + +namespace paddle { +namespace framework { +namespace ipu { + +// singleton +static int var_count = 0; + +std::string GenerateVarName() { + return std::string("_popart_gen_") + std::to_string(var_count++); +} + +ir::Node *MakeVarNode(ir::Graph *graph) { + auto var_name = GenerateVarName(); + auto var_desc = std::make_unique(var_name); + + auto var = graph->CreateVarNode(var_desc.get()); + return var; +} + +ir::Node *MakeOpNode(ir::Graph *graph, const std::string &type, + const std::vector &inputs, + const std::vector &outputs) { + auto op_desc = std::make_unique(); + op_desc->SetType(type); + auto op = graph->CreateOpNode(op_desc.get()); + + for (auto *in : inputs) { + ConnectNodes(in, op); + } + if (outputs.empty()) { + auto var = MakeVarNode(graph); + ConnectNodes(op, var); + } else { + for (auto *out : outputs) { + ConnectNodes(op, out); + } + } + + // i/o + std::vector input_names; + for (auto node : op->inputs) { + input_names.push_back(node->Name()); + } + op->Op()->SetInput("__inputs__", input_names); + std::vector output_names; + for (auto node : op->outputs) { + output_names.push_back(node->Name()); + } + op->Op()->SetOutput("__outputs__", output_names); + op->Op()->Flush(); + + return op; +} + +AttributeMap MakeConstAttributeMap(float v, std::vector dims, + int dtype) { + size_t size = 1; + for (auto &dim : dims) { + size *= dim; + } + std::vector value(size, v); + return AttributeMap{ + {"value", value}, {"dims", dims}, {"dtype", dtype}, + }; +} + +ir::Node *CreateConst(ir::Graph *graph, const std::vector &inputs, + const std::vector &outputs, + const AttributeMap &attrs) { + auto node = MakeOpNode(graph, "Constant", {}, {}); + node->Op()->SetAttrMap(attrs); + return node; +} + +ir::Node *CreatePow(ir::Graph *graph, const std::vector &inputs, + const std::vector &outputs, + const AttributeMap &attrs) { + auto node = MakeOpNode(graph, "Pow", inputs, outputs); + return node; +} + +} // namespace ipu +} // namespace framework +} // namespace paddle diff --git a/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h b/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h new file mode 100644 index 0000000000000..607c518952f81 --- /dev/null +++ b/paddle/fluid/framework/ipu/popart_canonicalization/op_builder.h @@ -0,0 +1,43 @@ +// Copyright (c) 2021 PaddlePaddle Authors. 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. + +#pragma once + +#include "paddle/fluid/framework/ipu/popart_canonicalization/canonicalization_utils.h" + +namespace paddle { +namespace framework { +namespace ipu { + +std::string GenerateVarName(); + +ir::Node *MakeVarNode(ir::Graph *graph); +ir::Node *MakeOpNode(ir::Graph *graph, const std::string &type, + const std::vector &inputs, + const std::vector &outputs); + +// TODO(alleng) make template +AttributeMap MakeConstAttributeMap(float v, std::vector dims, + int dtype); +ir::Node *CreateConst(ir::Graph *graph, const std::vector &inputs, + const std::vector &outputs, + const AttributeMap &attrs); + +ir::Node *CreatePow(ir::Graph *graph, const std::vector &inputs, + const std::vector &outputs, + const AttributeMap &attrs); + +} // namespace ipu +} // namespace framework +} // namespace paddle