From 55a43ad8525ef0358bb6f416dbfc8c3a7d0b8730 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Wed, 25 Aug 2021 10:43:44 +0000 Subject: [PATCH 01/15] add piano graph executor --- .../compiler/paddle2piano/CMakeLists.txt | 2 + .../paddle2piano/piano_graph_executor.cc | 151 ++++++++++++++++++ .../paddle2piano/piano_graph_executor.h | 70 ++++++++ .../compiler/paddle2piano/piano_op_registry.h | 3 + .../compiler/paddle2piano/vartype2notetype.h | 105 ++++++++++++ 5 files changed, 331 insertions(+) create mode 100644 paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc create mode 100644 paddle/fluid/compiler/paddle2piano/piano_graph_executor.h create mode 100644 paddle/fluid/compiler/paddle2piano/vartype2notetype.h diff --git a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt index 30fb12adaf96e..c0e4efb8f56c5 100644 --- a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt +++ b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt @@ -7,3 +7,5 @@ cc_test(piano_op_registry_test SRCS piano_op_registry_test.cc DEPS piano_op_regi cc_library(piano_op_kernel_context SRCS piano_op_kernel_context.cc DEPS piano_op_registry proto_desc note_builder) cc_test(piano_op_kernel_context_test SRCS piano_op_kernel_context_test.cc DEPS piano_op_kernel_context op_registry) + +cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc new file mode 100644 index 0000000000000..58420ee54629d --- /dev/null +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -0,0 +1,151 @@ +/* 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/compiler/paddle2piano/piano_graph_executor.h" + +#include +#include +#include + +#include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" +#include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" +// #include "paddle/fluid/compiler/piano/meta_op.h" +#include "paddle/fluid/platform/enforce.h" + +namespace paddle { +namespace piano { + +using framework::ir::Node; +using GraphNodeVec = GraphExecutor::GraphNodeVec; + +void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, + NoteBuilder* builder) { + for (size_t id = 0; id < cluster_inputs.size(); ++id) { + auto* node = cluster_inputs.at(id); + PADDLE_ENFORCE_EQ(node->IsVar(), true, + platform::errors::InvalidArgument( + "Cluster Sub-Graph Input should be var")); + + const auto& var_name = node->Name(); + + // create operand shape + const auto& var_shape = node->Var()->GetShape(); + const auto& var_type = node->Var()->GetType(); + + // convert framework vartype to piano note type + note::ElementTypeProto element_type = VarType2NoteType(var_type); + Shape operand_shape(element_type, var_shape); + + // create Operand + Operand op; + // Operand op = Parameter(builder, id, operand_shape, var_name); + + // store into PianoScope + scope->SetOperand(var_name, op); + } +} + +void TopologicSortGraph(const GraphNodeVec& cluster, + GraphNodeVec* cluster_sorted) { + std::unordered_set cluster_set(cluster.cbegin(), cluster.cend()); + + std::unordered_map> in_ops; + std::unordered_map> out_ops; + std::queue topo_queue; + + // ensure all op node in 'in_ops' and 'out_ops' + for (auto* n : cluster) { + PADDLE_ENFORCE_EQ(n->IsOp(), true, + platform::errors::InvalidArgument( + "Cluster Sub-Graph all should be op")); + + in_ops.emplace(n, std::unordered_set()); + out_ops.emplace(n, std::unordered_set()); + } + + // record all op's input op and output op + for (auto* n : cluster) { + // the op's input is var + for (auto* in_var : n->inputs) { + // the var's input is op + for (auto* in_op : in_var->inputs) { + if (cluster_set.find(in_op) != cluster_set.end()) { + in_ops.at(n).insert(in_op); + out_ops.at(in_op).insert(n); + } + } + } + } + + // find topology entrance + for (auto* n : cluster) { + if (in_ops.at(n).empty()) { + topo_queue.push(n); + } + } + + // topological sorting + while (!topo_queue.empty()) { + auto* cur_op = topo_queue.front(); + topo_queue.pop(); + + cluster_sorted->emplace_back(cur_op); + for (auto* out : out_ops.at(cur_op)) { + // decrease output op's in-degree + in_ops.at(out).erase(cur_op); + + // if empty, push into queue + if (in_ops.at(out).empty()) { + topo_queue.push(out); + } + } + } +} + +void RunCompile(const GraphExecutor::GraphNodeVec& cluster, PianoScope* scope, + NoteBuilder* builder) { + for (auto* n : cluster) { + const auto& op_name = n->Name(); + const auto* op_desc = n->Op(); + + const auto& op_kernel_map = PianoOpRegistry::AllPianoOpKernels(op_name); + // TODO(jiangcheng05): how to distinguish library's kernel, like cudnn? + op_kernel_map.at("PLAIN")(PianoOpKernelContext(op_desc, scope, builder)); + } +} + +note::ModuleProto GraphExecutor::operator()() { + // Step1: create unique NoteBuilder + std::string builder_name = "NoteBuilderOfGraph_"; + builder_name.append(std::to_string(graph_id_)); + + NoteBuilder builder(builder_name); + + // Step2: create graph's input operand + PianoScope scope; + CreateInputOperand(cluster_inputs_, &scope, &builder); + + // Step3: topo sort graph + GraphNodeVec cluster_sorted; + TopologicSortGraph(cluster_, &cluster_sorted); + + // Step4: get PianoOpKernel and run compile + RunCompile(cluster_sorted, &scope, &builder); + + // Step5: build and return module + return builder.Build(); +} + +} // namespace piano +} // namespace paddle diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h new file mode 100644 index 0000000000000..667114b075de5 --- /dev/null +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -0,0 +1,70 @@ +/* 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 + +#include "paddle/fluid/compiler/piano/note/note.pb.h" +#include "paddle/fluid/framework/ir/node.h" + +namespace paddle { +namespace piano { + +// An executor accept sub-graph which is generated by PianoCompilePass, +// run each op's PianoOpKernel, finally return the graph's ModuleProto. +// +// Parameter: +// 1. graph_id: the unique graph id, used for generating unique notebuilder name +// 2. cluster: a vector which contains all graph op, non-topological-sorting. +// 3. cluster_inputs: a vector which contains all graph's input var, the var's +// input are outside op, the output are inside op +// 4. cluster_outputs: a vector which contains all graph's output var, the var's +// input are inside op, the output are outside op +// 5. pcluster_internals: a vector which contains all graph's internal var, the +// var's input and output are inside op +// +// Describe: +// The executor consisted by the following step: +// 1. create a NoteBuilder, it's name is unique for each graph +// 2. create PianoScope, initially, scope only consist graph's input var and its +// operand +// 3. topological sorting graph +// 4. create PianoOpKernelContext and run each op's PianoOpKernel +// 5. run NoteBuilder's Build function to generate graph's ModuleProto +class GraphExecutor { + public: + using GraphNodeVec = std::vector; + + GraphExecutor(size_t graph_id, const GraphNodeVec& cluster, + const GraphNodeVec& cluster_inputs, + const GraphNodeVec& cluster_outputs, + const GraphNodeVec& cluster_internals) + : cluster_(cluster), + cluster_inputs_(cluster_inputs), + cluster_outputs_(cluster_outputs), + cluster_internals_(cluster_internals) {} + + note::ModuleProto operator()(); + + private: + size_t graph_id_; + const GraphNodeVec& cluster_; + const GraphNodeVec& cluster_inputs_; + const GraphNodeVec& cluster_outputs_; + const GraphNodeVec& cluster_internals_; +}; + +} // namespace piano +} // namespace paddle diff --git a/paddle/fluid/compiler/paddle2piano/piano_op_registry.h b/paddle/fluid/compiler/paddle2piano/piano_op_registry.h index bef43862e7d22..1ae598f0d1a94 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_op_registry.h +++ b/paddle/fluid/compiler/paddle2piano/piano_op_registry.h @@ -35,6 +35,8 @@ class PianoOpMaker; class PianoOpRegistry final { public: using OpKernelFunc = std::function; + + // map library to op kernel, default library is PLAIN using OpKernelMap = std::unordered_map; // Register a Piano backend. @@ -83,6 +85,7 @@ class PianoOpRegistry final { Instance().ops_.at(op_type)->kernel_.emplace(library_type, func); } + // return OpKernelMap, which is the map from library name to PianoOpKernel static const OpKernelMap& AllPianoOpKernels(const std::string& op_type); private: diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h new file mode 100644 index 0000000000000..4f3d7a5b20418 --- /dev/null +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -0,0 +1,105 @@ +/* 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 + +#include "paddle/fluid/compiler/piano/note/note.pb.h" +#include "paddle/fluid/framework/framework.pb.h" + +namespace paddle { +namespace piano { + +note::ElementTypeProto VarType2NoteType(framework::proto::VarType_Type type) { + static std::unordered_map + vartype2notetype = {{framework::proto::VarType_Type_BOOL, note::B1}, + {framework::proto::VarType_Type_INT8, note::S8}, + {framework::proto::VarType_Type_INT16, note::S16}, + {framework::proto::VarType_Type_INT32, note::S32}, + {framework::proto::VarType_Type_INT64, note::S64}, + {framework::proto::VarType_Type_FP16, note::F16}, + {framework::proto::VarType_Type_FP32, note::F32}, + {framework::proto::VarType_Type_FP64, note::F64}, + {framework::proto::VarType_Type_UINT8, note::U8}, + {framework::proto::VarType_Type_SIZE_T, note::U64}}; + return vartype2notetype.at(type); +} + +template +constexpr note::ElementTypeProto VarType2NoteType(); + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::B1; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::S8; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::S16; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::S32; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::S64; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::F16; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::F32; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::F64; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::U8; +} + +template <> +constexpr note::ElementTypeProto +VarType2NoteType() { + return note::U64; +} + +} // namespace piano +} // namespace paddle From 33e7e0a4b67ff86c7390cafff42bda6fc8afd581 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Thu, 26 Aug 2021 09:43:01 +0000 Subject: [PATCH 02/15] change VarType_Type to VarType::Type --- .../paddle2piano/piano_graph_executor.cc | 8 ++-- .../paddle2piano/piano_graph_executor.h | 22 ++++++--- .../compiler/paddle2piano/vartype2notetype.h | 46 +++++++++---------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index 58420ee54629d..c5907a9d35983 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -27,7 +27,7 @@ namespace paddle { namespace piano { using framework::ir::Node; -using GraphNodeVec = GraphExecutor::GraphNodeVec; +using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, NoteBuilder* builder) { @@ -41,7 +41,7 @@ void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, // create operand shape const auto& var_shape = node->Var()->GetShape(); - const auto& var_type = node->Var()->GetType(); + const auto& var_type = node->Var()->GetDataType(); // convert framework vartype to piano note type note::ElementTypeProto element_type = VarType2NoteType(var_type); @@ -113,7 +113,7 @@ void TopologicSortGraph(const GraphNodeVec& cluster, } } -void RunCompile(const GraphExecutor::GraphNodeVec& cluster, PianoScope* scope, +void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, NoteBuilder* builder) { for (auto* n : cluster) { const auto& op_name = n->Name(); @@ -125,7 +125,7 @@ void RunCompile(const GraphExecutor::GraphNodeVec& cluster, PianoScope* scope, } } -note::ModuleProto GraphExecutor::operator()() { +note::ModuleProto PianoGraphExecutor::operator()() { // Step1: create unique NoteBuilder std::string builder_name = "NoteBuilderOfGraph_"; builder_name.append(std::to_string(graph_id_)); diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h index 667114b075de5..66f2374dab302 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -32,9 +32,19 @@ namespace piano { // input are outside op, the output are inside op // 4. cluster_outputs: a vector which contains all graph's output var, the var's // input are inside op, the output are outside op -// 5. pcluster_internals: a vector which contains all graph's internal var, the +// 5. cluster_internals: a vector which contains all graph's internal var, the // var's input and output are inside op // +// Example: +// -------------------------> op3 -> var4 -> +// / / +// -> var1 -> op1 -> var2 -> op2 -> var3 +// +// cluster: [op1, op2, op3] +// cluster_inputs: [var1] +// cluster_outputs: [var4] +// cluster_internals: [var2, var3] +// // Describe: // The executor consisted by the following step: // 1. create a NoteBuilder, it's name is unique for each graph @@ -43,14 +53,14 @@ namespace piano { // 3. topological sorting graph // 4. create PianoOpKernelContext and run each op's PianoOpKernel // 5. run NoteBuilder's Build function to generate graph's ModuleProto -class GraphExecutor { +class PianoGraphExecutor { public: using GraphNodeVec = std::vector; - GraphExecutor(size_t graph_id, const GraphNodeVec& cluster, - const GraphNodeVec& cluster_inputs, - const GraphNodeVec& cluster_outputs, - const GraphNodeVec& cluster_internals) + PianoGraphExecutor(size_t graph_id, const GraphNodeVec& cluster, + const GraphNodeVec& cluster_inputs, + const GraphNodeVec& cluster_outputs, + const GraphNodeVec& cluster_internals) : cluster_(cluster), cluster_inputs_(cluster_inputs), cluster_outputs_(cluster_outputs), diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index 4f3d7a5b20418..1e324a59ca998 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -22,82 +22,82 @@ limitations under the License. */ namespace paddle { namespace piano { -note::ElementTypeProto VarType2NoteType(framework::proto::VarType_Type type) { - static std::unordered_map - vartype2notetype = {{framework::proto::VarType_Type_BOOL, note::B1}, - {framework::proto::VarType_Type_INT8, note::S8}, - {framework::proto::VarType_Type_INT16, note::S16}, - {framework::proto::VarType_Type_INT32, note::S32}, - {framework::proto::VarType_Type_INT64, note::S64}, - {framework::proto::VarType_Type_FP16, note::F16}, - {framework::proto::VarType_Type_FP32, note::F32}, - {framework::proto::VarType_Type_FP64, note::F64}, - {framework::proto::VarType_Type_UINT8, note::U8}, - {framework::proto::VarType_Type_SIZE_T, note::U64}}; + vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, + {framework::proto::VarType::INT8, note::S8}, + {framework::proto::VarType::INT16, note::S16}, + {framework::proto::VarType::INT32, note::S32}, + {framework::proto::VarType::INT64, note::S64}, + {framework::proto::VarType::FP16, note::F16}, + {framework::proto::VarType::FP32, note::F32}, + {framework::proto::VarType::FP64, note::F64}, + {framework::proto::VarType::UINT8, note::U8}, + {framework::proto::VarType::SIZE_T, note::U64}}; return vartype2notetype.at(type); } -template +template constexpr note::ElementTypeProto VarType2NoteType(); template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::B1; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::S8; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::S16; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::S32; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::S64; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::F16; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::F32; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::F64; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::U8; } template <> constexpr note::ElementTypeProto -VarType2NoteType() { +VarType2NoteType() { return note::U64; } From 8464aae784eb3b882436547985e9fa9e7fd95871 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Thu, 26 Aug 2021 13:02:14 +0000 Subject: [PATCH 03/15] add single test script --- .../compiler/paddle2piano/CMakeLists.txt | 1 + .../paddle2piano/piano_graph_executor.h | 4 +- .../paddle2piano/piano_graph_executor_test.cc | 187 ++++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc diff --git a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt index c0e4efb8f56c5..bec6b9a83da8a 100644 --- a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt +++ b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt @@ -9,3 +9,4 @@ cc_library(piano_op_kernel_context SRCS piano_op_kernel_context.cc DEPS piano_op cc_test(piano_op_kernel_context_test SRCS piano_op_kernel_context_test.cc DEPS piano_op_kernel_context op_registry) cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context) +cc_test(piano_graph_executor_test SRCS piano_graph_executor_test.cc DEPS piano_graph_executor node) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h index 66f2374dab302..b1c179ee16c4c 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -57,7 +57,7 @@ class PianoGraphExecutor { public: using GraphNodeVec = std::vector; - PianoGraphExecutor(size_t graph_id, const GraphNodeVec& cluster, + PianoGraphExecutor(int64_t graph_id, const GraphNodeVec& cluster, const GraphNodeVec& cluster_inputs, const GraphNodeVec& cluster_outputs, const GraphNodeVec& cluster_internals) @@ -69,7 +69,7 @@ class PianoGraphExecutor { note::ModuleProto operator()(); private: - size_t graph_id_; + int64_t graph_id_; const GraphNodeVec& cluster_; const GraphNodeVec& cluster_inputs_; const GraphNodeVec& cluster_outputs_; diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc new file mode 100644 index 0000000000000..2e957a8297a3b --- /dev/null +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -0,0 +1,187 @@ +/* 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/compiler/paddle2piano/piano_graph_executor.h" + +#include + +#include + +#include "paddle/fluid/compiler/paddle2piano/piano_op_kernel.h" +#include "paddle/fluid/compiler/paddle2piano/piano_op_registry.h" +#include "paddle/fluid/framework/ir/node.h" + +namespace paddle { +namespace piano { + +using framework::ir::Node; +using framework::VariableNameMap; +using framework::AttributeMap; +using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; + +using paddle::framework::InferShapeContext; +using paddle::framework::OpProtoAndCheckerMaker; +using paddle::framework::OperatorWithKernel; + +std::unordered_set TestDatatypes() { + static std::unordered_set supported_types = { + note::F16, note::F32, note::F64}; + return supported_types; +} + +class TestOp : public OperatorWithKernel { + public: + using OperatorWithKernel::OperatorWithKernel; + + void InferShape(InferShapeContext* ctx) const override { + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "test"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "test"); + + auto in_dims = ctx->GetInputDim("X"); + + ctx->SetOutputDim("Out", in_dims); + ctx->ShareLoD("X", /*->*/ "Out"); + } +}; + +class TestOpMaker : public OpProtoAndCheckerMaker { + public: + void Make() override { + AddInput("X", "(Tensor), The input tensor of test op."); + AddOutput("Out", "(Tensor), The output tensor of test op."); + AddComment(R"DOC(Test Operator.)DOC"); + } +}; + +// register piano op kernel with limit allow backend list +class TestPianoOpMaker : public PianoOpMaker { + public: + void Make() override { + // do nothing, pass + } +}; + +class TestPianoOpKernel : public PianoOpKernel { + public: + void Compile(const PianoOpKernelContext& context) const override { + // do nothing, pass + } +}; + +std::array>, 4> CreateGraph() { + // -------------------------> op3 -> var4 -> + // / / + // -> var1 -> op1 -> var2 -> op2 -> var3 + // + // cluster: [op1, op2, op3] + // cluster_inputs: [var1] + // cluster_outputs: [var4] + // cluster_internals: [var2, var3] + + std::array>, 4> graph; + // first insert cluster op node + framework::OpDesc op_desc_1("op1", {{"var1", {""}}}, {{"var2", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_1)); + + framework::OpDesc op_desc_2("op2", {{"var2", {""}}}, {{"var3", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_2)); + + framework::OpDesc op_desc_3("op3", {{"var1", {""}}, {"var3", {""}}}, + {{"var4", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_3)); + + // second insert cluster_inputs var node + framework::VarDesc var_desc_1("var1"); + var_desc_1.SetType(framework::proto::VarType::LOD_TENSOR); + var_desc_1.SetDataType(framework::proto::VarType::FP32); + var_desc_1.SetShape({64, 1024, 128}); + graph.at(1).emplace_back(framework::ir::CreateNodeForTest(&var_desc_1)); + + // third insert cluster_internals var node + framework::VarDesc var_desc_2("var2"); + var_desc_2.SetType(framework::proto::VarType::LOD_TENSOR); + var_desc_2.SetDataType(framework::proto::VarType::FP32); + var_desc_2.SetShape({64}); + graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_2)); + + framework::VarDesc var_desc_3("var3"); + var_desc_3.SetType(framework::proto::VarType::LOD_TENSOR); + var_desc_3.SetDataType(framework::proto::VarType::FP32); + var_desc_3.SetShape({1024}); + graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_3)); + + // finally insert cluster_outputs var node + framework::VarDesc var_desc_4("var4"); + var_desc_4.SetType(framework::proto::VarType::LOD_TENSOR); + var_desc_4.SetDataType(framework::proto::VarType::FP32); + var_desc_4.SetShape({64, 1024, 128}); + graph.at(3).emplace_back(framework::ir::CreateNodeForTest(&var_desc_4)); + + return graph; +} + +void CreateCluster(GraphNodeVec* cluster, GraphNodeVec* cluster_inputs, + GraphNodeVec* cluster_outputs, + GraphNodeVec* cluster_internals) { + // static to avoid destroy + static const auto& graph = CreateGraph(); + + // generate cluster + for (const auto& node : graph.at(0)) { + cluster->emplace_back(node.get()); + } + // generate cluster_inputs + for (const auto& node : graph.at(1)) { + cluster_inputs->emplace_back(node.get()); + } + // generate cluster_internals + for (const auto& node : graph.at(2)) { + cluster_internals->emplace_back(node.get()); + } + // generate cluster_outputs + for (const auto& node : graph.at(3)) { + cluster_outputs->emplace_back(node.get()); + } +} + +} // namespace piano +} // namespace paddle + +#define REGISTER_TEST_OP(name) \ + REGISTER_OP_WITHOUT_GRADIENT(name, paddle::piano::TestOp, \ + paddle::piano::TestOpMaker); \ + REGISTER_PIANO_OP(name, paddle::piano::TestPianoOpMaker, \ + paddle::piano::TestPianoOpKernel) + +REGISTER_TEST_OP(op1) +REGISTER_TEST_OP(op2) +REGISTER_TEST_OP(op3) + +#undef REGISTER_TEST_OP + +namespace paddle { +namespace piano { + +TEST(GraphExecutorTest, basic) { + GraphNodeVec cluster, cluster_inputs, cluster_outputs, cluster_internals; + CreateCluster(&cluster, &cluster_inputs, &cluster_outputs, + &cluster_internals); + + PianoGraphExecutor exec(0, cluster, cluster_inputs, cluster_outputs, + cluster_internals); + exec(); +} + +} // namespace piano +} // namespace paddle From ef9c568836fb4533ee4bbab0ae2e005e4cc8f719 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Fri, 27 Aug 2021 02:21:31 +0000 Subject: [PATCH 04/15] complete some test script --- .../paddle2piano/piano_graph_executor_test.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc index 2e957a8297a3b..6af5cd27bd237 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -19,6 +19,7 @@ limitations under the License. */ #include #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel.h" +#include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" #include "paddle/fluid/compiler/paddle2piano/piano_op_registry.h" #include "paddle/fluid/framework/ir/node.h" @@ -40,6 +41,11 @@ std::unordered_set TestDatatypes() { return supported_types; } +std::vector& GetCompileOrder() { + static std::vector order; + return order; +} + class TestOp : public OperatorWithKernel { public: using OperatorWithKernel::OperatorWithKernel; @@ -76,6 +82,7 @@ class TestPianoOpKernel : public PianoOpKernel { public: void Compile(const PianoOpKernelContext& context) const override { // do nothing, pass + GetCompileOrder().emplace_back(context.Type()); } }; @@ -180,7 +187,13 @@ TEST(GraphExecutorTest, basic) { PianoGraphExecutor exec(0, cluster, cluster_inputs, cluster_outputs, cluster_internals); - exec(); + auto module_proto = exec(); + + // check topologic sorting right + ASSERT_EQ(GetCompileOrder(), std::vector({"op1", "op2", "op3"})); + + // check module proto right + ASSERT_TRUE(module_proto.has_name()); } } // namespace piano From 3ed24005b3eb3035d7793bafd6af8d9b1c8eaf9d Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Fri, 27 Aug 2021 09:44:26 +0000 Subject: [PATCH 05/15] add enforce at convert vartype --- paddle/fluid/compiler/paddle2piano/vartype2notetype.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index 1e324a59ca998..ad881e1e8ccac 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -18,6 +18,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/piano/note/note.pb.h" #include "paddle/fluid/framework/framework.pb.h" +#include "paddle/fluid/platform/enforce.h" namespace paddle { namespace piano { @@ -35,6 +36,9 @@ note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { {framework::proto::VarType::FP64, note::F64}, {framework::proto::VarType::UINT8, note::U8}, {framework::proto::VarType::SIZE_T, note::U64}}; + PADDLE_ENFORCE_EQ( + vartype2notetype.find(type), vartype2notetype.end(), + platform::errors::NotFound("Cannot found VarType %d.", type)); return vartype2notetype.at(type); } From 7f0f347a7b0f69d6cd0b0bd7503b90e765fda5ee Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Mon, 30 Aug 2021 06:15:34 +0000 Subject: [PATCH 06/15] fix some bug and merge meta op PR change --- .../compiler/paddle2piano/CMakeLists.txt | 4 +-- .../paddle2piano/piano_graph_executor.cc | 14 ++++---- .../paddle2piano/piano_graph_executor.h | 3 +- .../paddle2piano/piano_graph_executor_test.cc | 35 ++++++++++++++----- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt index bec6b9a83da8a..5ed1b2b83e858 100644 --- a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt +++ b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt @@ -5,8 +5,8 @@ cc_test(piano_compile_pass_test SRCS piano_compile_pass_tester.cc DEPS piano_com cc_library(piano_op_registry SRCS piano_op_registry.cc DEPS framework_proto op_registry note_proto piano_data_description) cc_test(piano_op_registry_test SRCS piano_op_registry_test.cc DEPS piano_op_registry operator op_registry) -cc_library(piano_op_kernel_context SRCS piano_op_kernel_context.cc DEPS piano_op_registry proto_desc note_builder) +cc_library(piano_op_kernel_context SRCS piano_op_kernel_context.cc DEPS piano_op_registry proto_desc piano_symbolization_builder) cc_test(piano_op_kernel_context_test SRCS piano_op_kernel_context_test.cc DEPS piano_op_kernel_context op_registry) -cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context) +cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context piano_symbolization_meat_op) cc_test(piano_graph_executor_test SRCS piano_graph_executor_test.cc DEPS piano_graph_executor node) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index c5907a9d35983..cb907d98a6dc3 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -20,7 +20,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" #include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" -// #include "paddle/fluid/compiler/piano/meta_op.h" +#include "paddle/fluid/compiler/piano/symbolization/meta_op.h" #include "paddle/fluid/platform/enforce.h" namespace paddle { @@ -30,8 +30,8 @@ using framework::ir::Node; using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, - NoteBuilder* builder) { - for (size_t id = 0; id < cluster_inputs.size(); ++id) { + symbolization::NoteBuilder* builder) { + for (int64_t id = 0; id < cluster_inputs.size(); ++id) { auto* node = cluster_inputs.at(id); PADDLE_ENFORCE_EQ(node->IsVar(), true, platform::errors::InvalidArgument( @@ -48,8 +48,8 @@ void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, Shape operand_shape(element_type, var_shape); // create Operand - Operand op; - // Operand op = Parameter(builder, id, operand_shape, var_name); + symbolization::Operand op = + symbolization::Parameter(builder, id, operand_shape, var_name); // store into PianoScope scope->SetOperand(var_name, op); @@ -114,7 +114,7 @@ void TopologicSortGraph(const GraphNodeVec& cluster, } void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, - NoteBuilder* builder) { + symbolization::NoteBuilder* builder) { for (auto* n : cluster) { const auto& op_name = n->Name(); const auto* op_desc = n->Op(); @@ -130,7 +130,7 @@ note::ModuleProto PianoGraphExecutor::operator()() { std::string builder_name = "NoteBuilderOfGraph_"; builder_name.append(std::to_string(graph_id_)); - NoteBuilder builder(builder_name); + symbolization::NoteBuilder builder(builder_name); // Step2: create graph's input operand PianoScope scope; diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h index b1c179ee16c4c..c2b0689ce5b6d 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -61,7 +61,8 @@ class PianoGraphExecutor { const GraphNodeVec& cluster_inputs, const GraphNodeVec& cluster_outputs, const GraphNodeVec& cluster_internals) - : cluster_(cluster), + : graph_id_(graph_id), + cluster_(cluster), cluster_inputs_(cluster_inputs), cluster_outputs_(cluster_outputs), cluster_internals_(cluster_internals) {} diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc index 6af5cd27bd237..2121714dc88ec 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -14,6 +14,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_graph_executor.h" +#include #include #include @@ -21,6 +22,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel.h" #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" #include "paddle/fluid/compiler/paddle2piano/piano_op_registry.h" +#include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" #include "paddle/fluid/framework/ir/node.h" namespace paddle { @@ -112,27 +114,27 @@ std::array>, 4> CreateGraph() { framework::VarDesc var_desc_1("var1"); var_desc_1.SetType(framework::proto::VarType::LOD_TENSOR); var_desc_1.SetDataType(framework::proto::VarType::FP32); - var_desc_1.SetShape({64, 1024, 128}); + var_desc_1.SetShape({64}); graph.at(1).emplace_back(framework::ir::CreateNodeForTest(&var_desc_1)); // third insert cluster_internals var node framework::VarDesc var_desc_2("var2"); var_desc_2.SetType(framework::proto::VarType::LOD_TENSOR); - var_desc_2.SetDataType(framework::proto::VarType::FP32); - var_desc_2.SetShape({64}); + var_desc_2.SetDataType(framework::proto::VarType::INT32); + var_desc_2.SetShape({64, 128}); graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_2)); framework::VarDesc var_desc_3("var3"); var_desc_3.SetType(framework::proto::VarType::LOD_TENSOR); - var_desc_3.SetDataType(framework::proto::VarType::FP32); - var_desc_3.SetShape({1024}); + var_desc_3.SetDataType(framework::proto::VarType::BOOL); + var_desc_3.SetShape({64, 128, 1024}); graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_3)); // finally insert cluster_outputs var node framework::VarDesc var_desc_4("var4"); var_desc_4.SetType(framework::proto::VarType::LOD_TENSOR); - var_desc_4.SetDataType(framework::proto::VarType::FP32); - var_desc_4.SetShape({64, 1024, 128}); + var_desc_4.SetDataType(framework::proto::VarType::UINT8); + var_desc_4.SetShape({64, 128, 1024, 4096}); graph.at(3).emplace_back(framework::ir::CreateNodeForTest(&var_desc_4)); return graph; @@ -185,15 +187,30 @@ TEST(GraphExecutorTest, basic) { CreateCluster(&cluster, &cluster_inputs, &cluster_outputs, &cluster_internals); - PianoGraphExecutor exec(0, cluster, cluster_inputs, cluster_outputs, + PianoGraphExecutor exec(100, cluster, cluster_inputs, cluster_outputs, cluster_internals); auto module_proto = exec(); // check topologic sorting right ASSERT_EQ(GetCompileOrder(), std::vector({"op1", "op2", "op3"})); - // check module proto right + // check module proto right? ASSERT_TRUE(module_proto.has_name()); + ASSERT_TRUE(module_proto.has_entry_function_signature()); + + const auto& entry_sig = module_proto.entry_function_signature(); + ASSERT_EQ(entry_sig.parameters_size(), cluster_inputs.size()); + for (int i = 0; i < entry_sig.parameter_names_size(); ++i) { + ASSERT_NE(entry_sig.parameter_names(i).find(cluster_inputs[i]->Name()), + std::string::npos); + } + + const auto& entry_param = entry_sig.parameters(0); + ASSERT_TRUE(entry_param.has_element_type()); + ASSERT_EQ(entry_param.element_type(), + VarType2NoteType(framework::proto::VarType::FP32)); + ASSERT_EQ(entry_param.dimensions_size(), 1); + ASSERT_EQ(entry_param.dimensions(0), 64); } } // namespace piano From 9a465a95b68d91ad264ed0b2506dbf16c1cca357 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Mon, 30 Aug 2021 06:21:20 +0000 Subject: [PATCH 07/15] fix VarType2NoteType bug --- paddle/fluid/compiler/paddle2piano/vartype2notetype.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index ad881e1e8ccac..27a23e93435bd 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -23,7 +23,8 @@ limitations under the License. */ namespace paddle { namespace piano { -note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { +static note::ElementTypeProto VarType2NoteType( + framework::proto::VarType::Type type) { static std::unordered_map vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, @@ -36,7 +37,7 @@ note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { {framework::proto::VarType::FP64, note::F64}, {framework::proto::VarType::UINT8, note::U8}, {framework::proto::VarType::SIZE_T, note::U64}}; - PADDLE_ENFORCE_EQ( + PADDLE_ENFORCE_NE( vartype2notetype.find(type), vartype2notetype.end(), platform::errors::NotFound("Cannot found VarType %d.", type)); return vartype2notetype.at(type); From 472c0aaeed717632a2ac3f379c325671d744cfc3 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Mon, 30 Aug 2021 07:54:14 +0000 Subject: [PATCH 08/15] improve and perfect test script --- .../paddle2piano/piano_graph_executor_test.cc | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc index 2121714dc88ec..fcb6dc885ffc4 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -98,44 +98,78 @@ std::array>, 4> CreateGraph() { // cluster_outputs: [var4] // cluster_internals: [var2, var3] + // index : meaning + // 0 : cluster + // 1 : cluster_inputs + // 2 : cluster_outputs + // 3 : cluster_internals std::array>, 4> graph; - // first insert cluster op node - framework::OpDesc op_desc_1("op1", {{"var1", {""}}}, {{"var2", {""}}}, {}); - graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_1)); - framework::OpDesc op_desc_2("op2", {{"var2", {""}}}, {{"var3", {""}}}, {}); - graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_2)); - - framework::OpDesc op_desc_3("op3", {{"var1", {""}}, {"var3", {""}}}, - {{"var4", {""}}}, {}); - graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_3)); - - // second insert cluster_inputs var node + // insert cluster_inputs var node framework::VarDesc var_desc_1("var1"); var_desc_1.SetType(framework::proto::VarType::LOD_TENSOR); var_desc_1.SetDataType(framework::proto::VarType::FP32); var_desc_1.SetShape({64}); graph.at(1).emplace_back(framework::ir::CreateNodeForTest(&var_desc_1)); + auto* var1 = graph.at(1).back().get(); - // third insert cluster_internals var node + // insert cluster_internals var node framework::VarDesc var_desc_2("var2"); var_desc_2.SetType(framework::proto::VarType::LOD_TENSOR); var_desc_2.SetDataType(framework::proto::VarType::INT32); var_desc_2.SetShape({64, 128}); graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_2)); + auto* var2 = graph.at(2).back().get(); framework::VarDesc var_desc_3("var3"); var_desc_3.SetType(framework::proto::VarType::LOD_TENSOR); var_desc_3.SetDataType(framework::proto::VarType::BOOL); var_desc_3.SetShape({64, 128, 1024}); graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_3)); + auto* var3 = graph.at(2).back().get(); - // finally insert cluster_outputs var node + // insert cluster_outputs var node framework::VarDesc var_desc_4("var4"); var_desc_4.SetType(framework::proto::VarType::LOD_TENSOR); var_desc_4.SetDataType(framework::proto::VarType::UINT8); var_desc_4.SetShape({64, 128, 1024, 4096}); graph.at(3).emplace_back(framework::ir::CreateNodeForTest(&var_desc_4)); + auto* var4 = graph.at(3).back().get(); + + // insert cluster op node + framework::OpDesc op_desc_1("op1", {{"var1", {""}}}, {{"var2", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_1)); + auto* op1 = graph.at(0).back().get(); + + op1->inputs.emplace_back(var1); + var1->outputs.emplace_back(op1); + + op1->outputs.emplace_back(var2); + var2->inputs.emplace_back(op1); + + framework::OpDesc op_desc_3("op3", {{"var1", {""}}, {"var3", {""}}}, + {{"var4", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_3)); + auto* op3 = graph.at(0).back().get(); + + op3->inputs.emplace_back(var1); + var1->outputs.emplace_back(op3); + + op3->inputs.emplace_back(var3); + var3->outputs.emplace_back(op3); + + op3->outputs.emplace_back(var4); + var4->inputs.emplace_back(op3); + + framework::OpDesc op_desc_2("op2", {{"var2", {""}}}, {{"var3", {""}}}, {}); + graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_2)); + auto* op2 = graph.at(0).back().get(); + + op2->inputs.emplace_back(var2); + var2->outputs.emplace_back(op2); + + op2->outputs.emplace_back(var3); + var3->inputs.emplace_back(op2); return graph; } @@ -194,7 +228,7 @@ TEST(GraphExecutorTest, basic) { // check topologic sorting right ASSERT_EQ(GetCompileOrder(), std::vector({"op1", "op2", "op3"})); - // check module proto right? + // check module proto right ASSERT_TRUE(module_proto.has_name()); ASSERT_TRUE(module_proto.has_entry_function_signature()); From e98b24279f1187853e5d07ef8d3c0eadbff60ea3 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Tue, 31 Aug 2021 02:28:09 +0000 Subject: [PATCH 09/15] use vector instead of unordered_set --- .../paddle2piano/piano_graph_executor.cc | 22 +++++---- .../paddle2piano/piano_graph_executor_test.cc | 47 ++++++++++++------- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index cb907d98a6dc3..c76b491e5d439 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -60,8 +60,8 @@ void TopologicSortGraph(const GraphNodeVec& cluster, GraphNodeVec* cluster_sorted) { std::unordered_set cluster_set(cluster.cbegin(), cluster.cend()); - std::unordered_map> in_ops; - std::unordered_map> out_ops; + std::unordered_map in_ops; + std::unordered_map> out_ops; std::queue topo_queue; // ensure all op node in 'in_ops' and 'out_ops' @@ -70,8 +70,8 @@ void TopologicSortGraph(const GraphNodeVec& cluster, platform::errors::InvalidArgument( "Cluster Sub-Graph all should be op")); - in_ops.emplace(n, std::unordered_set()); - out_ops.emplace(n, std::unordered_set()); + in_ops.emplace(n, 0); + out_ops.emplace(n, std::vector()); } // record all op's input op and output op @@ -81,8 +81,8 @@ void TopologicSortGraph(const GraphNodeVec& cluster, // the var's input is op for (auto* in_op : in_var->inputs) { if (cluster_set.find(in_op) != cluster_set.end()) { - in_ops.at(n).insert(in_op); - out_ops.at(in_op).insert(n); + ++in_ops.at(n); + out_ops.at(in_op).emplace_back(n); } } } @@ -90,7 +90,7 @@ void TopologicSortGraph(const GraphNodeVec& cluster, // find topology entrance for (auto* n : cluster) { - if (in_ops.at(n).empty()) { + if (in_ops.at(n) == 0) { topo_queue.push(n); } } @@ -103,14 +103,18 @@ void TopologicSortGraph(const GraphNodeVec& cluster, cluster_sorted->emplace_back(cur_op); for (auto* out : out_ops.at(cur_op)) { // decrease output op's in-degree - in_ops.at(out).erase(cur_op); + --in_ops.at(out); // if empty, push into queue - if (in_ops.at(out).empty()) { + if (in_ops.at(out) == 0) { topo_queue.push(out); } } } + + PADDLE_ENFORCE_EQ(cluster_sorted->size(), cluster.size(), + platform::errors::PreconditionNotMet( + "Cluster Sub-Graph shouldn't contain cycle.")); } void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc index fcb6dc885ffc4..0463d870bce09 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -89,14 +89,14 @@ class TestPianoOpKernel : public PianoOpKernel { }; std::array>, 4> CreateGraph() { - // -------------------------> op3 -> var4 -> - // / / - // -> var1 -> op1 -> var2 -> op2 -> var3 + // -> var4 -- + // / \/ + // -> var1 -> op1 -> var2 -> op2 -> var3 -> op3 -> var5 // // cluster: [op1, op2, op3] // cluster_inputs: [var1] - // cluster_outputs: [var4] - // cluster_internals: [var2, var3] + // cluster_outputs: [var5] + // cluster_internals: [var2, var3, var4] // index : meaning // 0 : cluster @@ -123,18 +123,25 @@ std::array>, 4> CreateGraph() { framework::VarDesc var_desc_3("var3"); var_desc_3.SetType(framework::proto::VarType::LOD_TENSOR); - var_desc_3.SetDataType(framework::proto::VarType::BOOL); + var_desc_3.SetDataType(framework::proto::VarType::INT32); var_desc_3.SetShape({64, 128, 1024}); graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_3)); auto* var3 = graph.at(2).back().get(); - // insert cluster_outputs var node framework::VarDesc var_desc_4("var4"); var_desc_4.SetType(framework::proto::VarType::LOD_TENSOR); - var_desc_4.SetDataType(framework::proto::VarType::UINT8); + var_desc_4.SetDataType(framework::proto::VarType::INT32); var_desc_4.SetShape({64, 128, 1024, 4096}); - graph.at(3).emplace_back(framework::ir::CreateNodeForTest(&var_desc_4)); - auto* var4 = graph.at(3).back().get(); + graph.at(2).emplace_back(framework::ir::CreateNodeForTest(&var_desc_4)); + auto* var4 = graph.at(2).back().get(); + + // insert cluster_outputs var node + framework::VarDesc var_desc_5("var5"); + var_desc_5.SetType(framework::proto::VarType::LOD_TENSOR); + var_desc_5.SetDataType(framework::proto::VarType::BOOL); + var_desc_5.SetShape({64, 128, 1024, 4096, 32}); + graph.at(3).emplace_back(framework::ir::CreateNodeForTest(&var_desc_5)); + auto* var5 = graph.at(3).back().get(); // insert cluster op node framework::OpDesc op_desc_1("op1", {{"var1", {""}}}, {{"var2", {""}}}, {}); @@ -147,21 +154,22 @@ std::array>, 4> CreateGraph() { op1->outputs.emplace_back(var2); var2->inputs.emplace_back(op1); - framework::OpDesc op_desc_3("op3", {{"var1", {""}}, {"var3", {""}}}, - {{"var4", {""}}}, {}); + framework::OpDesc op_desc_3("op3", {{"var3", {""}}, {"var4", {""}}}, + {{"var5", {""}}}, {}); graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_3)); auto* op3 = graph.at(0).back().get(); - op3->inputs.emplace_back(var1); - var1->outputs.emplace_back(op3); - op3->inputs.emplace_back(var3); var3->outputs.emplace_back(op3); - op3->outputs.emplace_back(var4); - var4->inputs.emplace_back(op3); + op3->inputs.emplace_back(var4); + var4->outputs.emplace_back(op3); + + op3->outputs.emplace_back(var5); + var5->inputs.emplace_back(op3); - framework::OpDesc op_desc_2("op2", {{"var2", {""}}}, {{"var3", {""}}}, {}); + framework::OpDesc op_desc_2("op2", {{"var2", {""}}}, + {{"var3", {""}}, {"var4", {""}}}, {}); graph.at(0).emplace_back(framework::ir::CreateNodeForTest(&op_desc_2)); auto* op2 = graph.at(0).back().get(); @@ -171,6 +179,9 @@ std::array>, 4> CreateGraph() { op2->outputs.emplace_back(var3); var3->inputs.emplace_back(op2); + op2->outputs.emplace_back(var4); + var4->inputs.emplace_back(op2); + return graph; } From 29b8be20a28b5b1fbd44a84eb12649bb38bfc4fc Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Tue, 31 Aug 2021 03:32:21 +0000 Subject: [PATCH 10/15] perfect topo sort by @wzzju 's review advise --- .../paddle2piano/piano_graph_executor.cc | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index c76b491e5d439..39b5a4c263a27 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -60,29 +60,25 @@ void TopologicSortGraph(const GraphNodeVec& cluster, GraphNodeVec* cluster_sorted) { std::unordered_set cluster_set(cluster.cbegin(), cluster.cend()); - std::unordered_map in_ops; - std::unordered_map> out_ops; + std::unordered_map indegree; + std::unordered_map> adj_list; std::queue topo_queue; - // ensure all op node in 'in_ops' and 'out_ops' - for (auto* n : cluster) { - PADDLE_ENFORCE_EQ(n->IsOp(), true, - platform::errors::InvalidArgument( - "Cluster Sub-Graph all should be op")); - - in_ops.emplace(n, 0); - out_ops.emplace(n, std::vector()); - } - // record all op's input op and output op for (auto* n : cluster) { + PADDLE_ENFORCE_EQ(n->IsOp(), true, + platform::errors::PreconditionNotMet( + "Cluster's node all should be op node")); + PADDLE_ENFORCE_EQ(PianoOpRegistry::IsPianoOp(n->Name()), true, + platform::errors::PreconditionNotMet( + "Cluster's op all should be piano op")); // the op's input is var for (auto* in_var : n->inputs) { // the var's input is op for (auto* in_op : in_var->inputs) { if (cluster_set.find(in_op) != cluster_set.end()) { - ++in_ops.at(n); - out_ops.at(in_op).emplace_back(n); + ++indegree[n]; + ++adj_list[in_op][n]; } } } @@ -90,7 +86,7 @@ void TopologicSortGraph(const GraphNodeVec& cluster, // find topology entrance for (auto* n : cluster) { - if (in_ops.at(n) == 0) { + if (indegree[n] == 0) { topo_queue.push(n); } } @@ -101,13 +97,13 @@ void TopologicSortGraph(const GraphNodeVec& cluster, topo_queue.pop(); cluster_sorted->emplace_back(cur_op); - for (auto* out : out_ops.at(cur_op)) { + for (const auto& adj_pair : adj_list[cur_op]) { // decrease output op's in-degree - --in_ops.at(out); + indegree.at(adj_pair.first) -= adj_pair.second; // if empty, push into queue - if (in_ops.at(out) == 0) { - topo_queue.push(out); + if (indegree.at(adj_pair.first) == 0) { + topo_queue.push(adj_pair.first); } } } From 60e126aafeb919ae0c31860bbb14d77c98a9065d Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Wed, 1 Sep 2021 10:03:24 +0000 Subject: [PATCH 11/15] fix get var data type problem --- .../paddle2piano/piano_graph_executor.cc | 21 ++++- .../compiler/paddle2piano/vartype2notetype.h | 79 +++---------------- 2 files changed, 32 insertions(+), 68 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index 39b5a4c263a27..19a4cffae6889 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -27,8 +27,27 @@ namespace paddle { namespace piano { using framework::ir::Node; +using framework::proto::VarType; using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; +VarType::Type GetVarDataType(const framework::VarDesc* var) { + // non-pod type list + static std::unordered_set non_pod_types = { + VarType::LOD_TENSOR, VarType::SELECTED_ROWS, VarType::LOD_TENSOR_ARRAY}; + + const auto& var_type = var->GetType(); + if (non_pod_types.count(var_type) != 0) { + // if the value type is non-pod type + return var->GetDataType(); + } else if (GetVarType2NoteTypeMap().count(var_type) != 0) { + // if value is supported type + return var_type; + } + PADDLE_THROW( + platform::errors::Unimplemented("Unsupported value data type (%s)", + framework::DataTypeToString(var_type))); +} + void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, symbolization::NoteBuilder* builder) { for (int64_t id = 0; id < cluster_inputs.size(); ++id) { @@ -41,7 +60,7 @@ void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, // create operand shape const auto& var_shape = node->Var()->GetShape(); - const auto& var_type = node->Var()->GetDataType(); + const auto& var_type = GetVarDataType(node->Var()); // convert framework vartype to piano note type note::ElementTypeProto element_type = VarType2NoteType(var_type); diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index 27a23e93435bd..e9f24b7b4bd07 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -17,14 +17,16 @@ limitations under the License. */ #include #include "paddle/fluid/compiler/piano/note/note.pb.h" +#include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/framework/framework.pb.h" #include "paddle/fluid/platform/enforce.h" namespace paddle { namespace piano { -static note::ElementTypeProto VarType2NoteType( - framework::proto::VarType::Type type) { +static const std::unordered_map& +GetVarType2NoteTypeMap() { static std::unordered_map vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, @@ -37,73 +39,16 @@ static note::ElementTypeProto VarType2NoteType( {framework::proto::VarType::FP64, note::F64}, {framework::proto::VarType::UINT8, note::U8}, {framework::proto::VarType::SIZE_T, note::U64}}; - PADDLE_ENFORCE_NE( - vartype2notetype.find(type), vartype2notetype.end(), - platform::errors::NotFound("Cannot found VarType %d.", type)); - return vartype2notetype.at(type); + return vartype2notetype; } -template -constexpr note::ElementTypeProto VarType2NoteType(); - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::B1; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::S8; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::S16; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::S32; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::S64; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::F16; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::F32; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::F64; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::U8; -} - -template <> -constexpr note::ElementTypeProto -VarType2NoteType() { - return note::U64; +static note::ElementTypeProto VarType2NoteType( + framework::proto::VarType::Type type) { + const auto& vartype2notetype = GetVarType2NoteTypeMap(); + PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), + "Unsupported value data type (%s)", + framework::DataTypeToString(type)); + return vartype2notetype.at(type); } } // namespace piano From d0ca5fed648c448576009f4a5321d2467951a7fc Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Wed, 1 Sep 2021 10:24:23 +0000 Subject: [PATCH 12/15] fix print string not c-string bug --- paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc | 6 +++--- paddle/fluid/compiler/paddle2piano/vartype2notetype.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index 19a4cffae6889..81600c64bc0d8 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -43,9 +43,9 @@ VarType::Type GetVarDataType(const framework::VarDesc* var) { // if value is supported type return var_type; } - PADDLE_THROW( - platform::errors::Unimplemented("Unsupported value data type (%s)", - framework::DataTypeToString(var_type))); + PADDLE_THROW(platform::errors::Unimplemented( + "Unsupported value data type (%s)", + framework::DataTypeToString(var_type).c_str())); } void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index e9f24b7b4bd07..39d79c718e63b 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -47,7 +47,7 @@ static note::ElementTypeProto VarType2NoteType( const auto& vartype2notetype = GetVarType2NoteTypeMap(); PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), "Unsupported value data type (%s)", - framework::DataTypeToString(type)); + framework::DataTypeToString(type).c_str()); return vartype2notetype.at(type); } From bb37a3c32f0b87ec4e3e7accba843d1552435897 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Wed, 1 Sep 2021 12:36:06 +0000 Subject: [PATCH 13/15] perfect PianoGraphExecutor class structure by @wzzju 's review advise --- .../paddle2piano/piano_graph_executor.cc | 65 ++++++++++++++----- .../paddle2piano/piano_graph_executor.h | 21 +++++- .../compiler/paddle2piano/vartype2notetype.h | 30 +-------- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index 81600c64bc0d8..239a659a5977e 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -21,6 +21,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" #include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" #include "paddle/fluid/compiler/piano/symbolization/meta_op.h" +#include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/platform/enforce.h" namespace paddle { @@ -28,9 +29,37 @@ namespace piano { using framework::ir::Node; using framework::proto::VarType; -using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; -VarType::Type GetVarDataType(const framework::VarDesc* var) { +namespace { +const std::unordered_map& +GetVarType2NoteTypeMap() { + static std::unordered_map + vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, + {framework::proto::VarType::INT8, note::S8}, + {framework::proto::VarType::INT16, note::S16}, + {framework::proto::VarType::INT32, note::S32}, + {framework::proto::VarType::INT64, note::S64}, + {framework::proto::VarType::FP16, note::F16}, + {framework::proto::VarType::FP32, note::F32}, + {framework::proto::VarType::FP64, note::F64}, + {framework::proto::VarType::UINT8, note::U8}, + {framework::proto::VarType::SIZE_T, note::U64}}; + return vartype2notetype; +} +} // namespace + +note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { + const auto& vartype2notetype = GetVarType2NoteTypeMap(); + PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), + "Unsupported value data type (%s)", + framework::DataTypeToString(type).c_str()); + return vartype2notetype.at(type); +} + +VarType::Type PianoGraphExecutor::GetVarDataType( + const framework::VarDesc* var) { // non-pod type list static std::unordered_set non_pod_types = { VarType::LOD_TENSOR, VarType::SELECTED_ROWS, VarType::LOD_TENSOR_ARRAY}; @@ -46,12 +75,13 @@ VarType::Type GetVarDataType(const framework::VarDesc* var) { PADDLE_THROW(platform::errors::Unimplemented( "Unsupported value data type (%s)", framework::DataTypeToString(var_type).c_str())); + return framework::proto::VarType::RAW; } -void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, - symbolization::NoteBuilder* builder) { - for (int64_t id = 0; id < cluster_inputs.size(); ++id) { - auto* node = cluster_inputs.at(id); +void PianoGraphExecutor::CreateInputOperand( + PianoScope* scope, symbolization::NoteBuilder* builder) const { + for (int64_t id = 0; id < cluster_inputs_.size(); ++id) { + auto* node = cluster_inputs_.at(id); PADDLE_ENFORCE_EQ(node->IsVar(), true, platform::errors::InvalidArgument( "Cluster Sub-Graph Input should be var")); @@ -75,16 +105,16 @@ void CreateInputOperand(const GraphNodeVec& cluster_inputs, PianoScope* scope, } } -void TopologicSortGraph(const GraphNodeVec& cluster, - GraphNodeVec* cluster_sorted) { - std::unordered_set cluster_set(cluster.cbegin(), cluster.cend()); +void PianoGraphExecutor::TopologicSortCluster( + GraphNodeVec* cluster_sorted) const { + std::unordered_set cluster_set(cluster_.cbegin(), cluster_.cend()); std::unordered_map indegree; std::unordered_map> adj_list; std::queue topo_queue; // record all op's input op and output op - for (auto* n : cluster) { + for (auto* n : cluster_) { PADDLE_ENFORCE_EQ(n->IsOp(), true, platform::errors::PreconditionNotMet( "Cluster's node all should be op node")); @@ -104,7 +134,7 @@ void TopologicSortGraph(const GraphNodeVec& cluster, } // find topology entrance - for (auto* n : cluster) { + for (auto* n : cluster_) { if (indegree[n] == 0) { topo_queue.push(n); } @@ -127,13 +157,14 @@ void TopologicSortGraph(const GraphNodeVec& cluster, } } - PADDLE_ENFORCE_EQ(cluster_sorted->size(), cluster.size(), + PADDLE_ENFORCE_EQ(cluster_sorted->size(), cluster_.size(), platform::errors::PreconditionNotMet( "Cluster Sub-Graph shouldn't contain cycle.")); } -void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, - symbolization::NoteBuilder* builder) { +void PianoGraphExecutor::RunCompile(const GraphNodeVec& cluster, + PianoScope* scope, + symbolization::NoteBuilder* builder) const { for (auto* n : cluster) { const auto& op_name = n->Name(); const auto* op_desc = n->Op(); @@ -144,7 +175,7 @@ void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, } } -note::ModuleProto PianoGraphExecutor::operator()() { +note::ModuleProto PianoGraphExecutor::operator()() const { // Step1: create unique NoteBuilder std::string builder_name = "NoteBuilderOfGraph_"; builder_name.append(std::to_string(graph_id_)); @@ -153,11 +184,11 @@ note::ModuleProto PianoGraphExecutor::operator()() { // Step2: create graph's input operand PianoScope scope; - CreateInputOperand(cluster_inputs_, &scope, &builder); + CreateInputOperand(&scope, &builder); // Step3: topo sort graph GraphNodeVec cluster_sorted; - TopologicSortGraph(cluster_, &cluster_sorted); + TopologicSortCluster(&cluster_sorted); // Step4: get PianoOpKernel and run compile RunCompile(cluster_sorted, &scope, &builder); diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h index c2b0689ce5b6d..77915d5285f39 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -16,7 +16,9 @@ limitations under the License. */ #include +#include "paddle/fluid/compiler/paddle2piano/piano_scope.h" #include "paddle/fluid/compiler/piano/note/note.pb.h" +#include "paddle/fluid/compiler/piano/symbolization/note_builder.h" #include "paddle/fluid/framework/ir/node.h" namespace paddle { @@ -67,14 +69,29 @@ class PianoGraphExecutor { cluster_outputs_(cluster_outputs), cluster_internals_(cluster_internals) {} - note::ModuleProto operator()(); + note::ModuleProto operator()() const; private: - int64_t graph_id_; + const int64_t graph_id_; const GraphNodeVec& cluster_; const GraphNodeVec& cluster_inputs_; const GraphNodeVec& cluster_outputs_; const GraphNodeVec& cluster_internals_; + + // get var's data type + static framework::proto::VarType::Type GetVarDataType( + const framework::VarDesc* var); + + // create graph's input operand from cluster_inputs_ + void CreateInputOperand(PianoScope* scope, + symbolization::NoteBuilder* builder) const; + + // run PianoOpKernel's Compile + void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, + symbolization::NoteBuilder* builder) const; + + // topologic sorting graph node + void TopologicSortCluster(GraphNodeVec* cluster_sorted) const; }; } // namespace piano diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h index 39d79c718e63b..2fcda81d38324 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype2notetype.h @@ -17,39 +17,13 @@ limitations under the License. */ #include #include "paddle/fluid/compiler/piano/note/note.pb.h" -#include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/framework/framework.pb.h" -#include "paddle/fluid/platform/enforce.h" namespace paddle { namespace piano { -static const std::unordered_map& -GetVarType2NoteTypeMap() { - static std::unordered_map - vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, - {framework::proto::VarType::INT8, note::S8}, - {framework::proto::VarType::INT16, note::S16}, - {framework::proto::VarType::INT32, note::S32}, - {framework::proto::VarType::INT64, note::S64}, - {framework::proto::VarType::FP16, note::F16}, - {framework::proto::VarType::FP32, note::F32}, - {framework::proto::VarType::FP64, note::F64}, - {framework::proto::VarType::UINT8, note::U8}, - {framework::proto::VarType::SIZE_T, note::U64}}; - return vartype2notetype; -} - -static note::ElementTypeProto VarType2NoteType( - framework::proto::VarType::Type type) { - const auto& vartype2notetype = GetVarType2NoteTypeMap(); - PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), - "Unsupported value data type (%s)", - framework::DataTypeToString(type).c_str()); - return vartype2notetype.at(type); -} +extern note::ElementTypeProto VarType2NoteType( + framework::proto::VarType::Type type); } // namespace piano } // namespace paddle From 1fe30905375acd6f6b56f1d5181e98f1fc2644d2 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Thu, 2 Sep 2021 02:47:32 +0000 Subject: [PATCH 14/15] optimize vartype utils by wzzju 's advice --- .../compiler/paddle2piano/CMakeLists.txt | 6 +- .../paddle2piano/piano_graph_executor.cc | 82 ++++--------------- .../paddle2piano/piano_graph_executor.h | 11 +-- .../paddle2piano/piano_graph_executor_test.cc | 4 +- .../compiler/paddle2piano/vartype_utils.cc | 82 +++++++++++++++++++ .../{vartype2notetype.h => vartype_utils.h} | 10 ++- 6 files changed, 118 insertions(+), 77 deletions(-) create mode 100644 paddle/fluid/compiler/paddle2piano/vartype_utils.cc rename paddle/fluid/compiler/paddle2piano/{vartype2notetype.h => vartype_utils.h} (72%) diff --git a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt index 5ed1b2b83e858..e1ce067292427 100644 --- a/paddle/fluid/compiler/paddle2piano/CMakeLists.txt +++ b/paddle/fluid/compiler/paddle2piano/CMakeLists.txt @@ -8,5 +8,7 @@ cc_test(piano_op_registry_test SRCS piano_op_registry_test.cc DEPS piano_op_regi cc_library(piano_op_kernel_context SRCS piano_op_kernel_context.cc DEPS piano_op_registry proto_desc piano_symbolization_builder) cc_test(piano_op_kernel_context_test SRCS piano_op_kernel_context_test.cc DEPS piano_op_kernel_context op_registry) -cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context piano_symbolization_meat_op) -cc_test(piano_graph_executor_test SRCS piano_graph_executor_test.cc DEPS piano_graph_executor node) +cc_library(vartype_utils SRCS vartype_utils.cc DEPS proto_desc data_type note_proto) + +cc_library(piano_graph_executor SRCS piano_graph_executor.cc DEPS piano_op_kernel_context piano_symbolization_meat_op vartype_utils) +cc_test(piano_graph_executor_test SRCS piano_graph_executor_test.cc DEPS piano_graph_executor node vartype_utils) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index 239a659a5977e..b5e9949325b4c 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -14,72 +14,25 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_graph_executor.h" +#include #include #include #include #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" -#include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" +#include "paddle/fluid/compiler/paddle2piano/vartype_utils.h" #include "paddle/fluid/compiler/piano/symbolization/meta_op.h" -#include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/platform/enforce.h" namespace paddle { namespace piano { using framework::ir::Node; -using framework::proto::VarType; - -namespace { -const std::unordered_map& -GetVarType2NoteTypeMap() { - static std::unordered_map - vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, - {framework::proto::VarType::INT8, note::S8}, - {framework::proto::VarType::INT16, note::S16}, - {framework::proto::VarType::INT32, note::S32}, - {framework::proto::VarType::INT64, note::S64}, - {framework::proto::VarType::FP16, note::F16}, - {framework::proto::VarType::FP32, note::F32}, - {framework::proto::VarType::FP64, note::F64}, - {framework::proto::VarType::UINT8, note::U8}, - {framework::proto::VarType::SIZE_T, note::U64}}; - return vartype2notetype; -} -} // namespace - -note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { - const auto& vartype2notetype = GetVarType2NoteTypeMap(); - PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), - "Unsupported value data type (%s)", - framework::DataTypeToString(type).c_str()); - return vartype2notetype.at(type); -} +using GraphNodeVec = PianoGraphExecutor::GraphNodeVec; -VarType::Type PianoGraphExecutor::GetVarDataType( - const framework::VarDesc* var) { - // non-pod type list - static std::unordered_set non_pod_types = { - VarType::LOD_TENSOR, VarType::SELECTED_ROWS, VarType::LOD_TENSOR_ARRAY}; - - const auto& var_type = var->GetType(); - if (non_pod_types.count(var_type) != 0) { - // if the value type is non-pod type - return var->GetDataType(); - } else if (GetVarType2NoteTypeMap().count(var_type) != 0) { - // if value is supported type - return var_type; - } - PADDLE_THROW(platform::errors::Unimplemented( - "Unsupported value data type (%s)", - framework::DataTypeToString(var_type).c_str())); - return framework::proto::VarType::RAW; -} - -void PianoGraphExecutor::CreateInputOperand( - PianoScope* scope, symbolization::NoteBuilder* builder) const { +std::unique_ptr PianoGraphExecutor::CreateInputOperand( + symbolization::NoteBuilder* builder) const { + std::unique_ptr scope = std::make_unique(); for (int64_t id = 0; id < cluster_inputs_.size(); ++id) { auto* node = cluster_inputs_.at(id); PADDLE_ENFORCE_EQ(node->IsVar(), true, @@ -90,10 +43,10 @@ void PianoGraphExecutor::CreateInputOperand( // create operand shape const auto& var_shape = node->Var()->GetShape(); - const auto& var_type = GetVarDataType(node->Var()); + const auto& var_type = utils::GetVarDataType(node->Var()); // convert framework vartype to piano note type - note::ElementTypeProto element_type = VarType2NoteType(var_type); + note::ElementTypeProto element_type = utils::VarType2NoteType(var_type); Shape operand_shape(element_type, var_shape); // create Operand @@ -103,10 +56,11 @@ void PianoGraphExecutor::CreateInputOperand( // store into PianoScope scope->SetOperand(var_name, op); } + return std::move(scope); } -void PianoGraphExecutor::TopologicSortCluster( - GraphNodeVec* cluster_sorted) const { +GraphNodeVec PianoGraphExecutor::SortInternalCluster() const { + GraphNodeVec cluster_sorted; std::unordered_set cluster_set(cluster_.cbegin(), cluster_.cend()); std::unordered_map indegree; @@ -145,7 +99,7 @@ void PianoGraphExecutor::TopologicSortCluster( auto* cur_op = topo_queue.front(); topo_queue.pop(); - cluster_sorted->emplace_back(cur_op); + cluster_sorted.emplace_back(cur_op); for (const auto& adj_pair : adj_list[cur_op]) { // decrease output op's in-degree indegree.at(adj_pair.first) -= adj_pair.second; @@ -157,9 +111,10 @@ void PianoGraphExecutor::TopologicSortCluster( } } - PADDLE_ENFORCE_EQ(cluster_sorted->size(), cluster_.size(), + PADDLE_ENFORCE_EQ(cluster_sorted.size(), cluster_.size(), platform::errors::PreconditionNotMet( "Cluster Sub-Graph shouldn't contain cycle.")); + return cluster_sorted; } void PianoGraphExecutor::RunCompile(const GraphNodeVec& cluster, @@ -183,15 +138,14 @@ note::ModuleProto PianoGraphExecutor::operator()() const { symbolization::NoteBuilder builder(builder_name); // Step2: create graph's input operand - PianoScope scope; - CreateInputOperand(&scope, &builder); + auto&& scope = CreateInputOperand(&builder); // Step3: topo sort graph - GraphNodeVec cluster_sorted; - TopologicSortCluster(&cluster_sorted); + // rvalue references avoid useless copy + auto&& cluster_sorted = SortInternalCluster(); // Step4: get PianoOpKernel and run compile - RunCompile(cluster_sorted, &scope, &builder); + RunCompile(cluster_sorted, scope.get(), &builder); // Step5: build and return module return builder.Build(); diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h index 77915d5285f39..4e2243a660a7c 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.h @@ -78,20 +78,17 @@ class PianoGraphExecutor { const GraphNodeVec& cluster_outputs_; const GraphNodeVec& cluster_internals_; - // get var's data type - static framework::proto::VarType::Type GetVarDataType( - const framework::VarDesc* var); - // create graph's input operand from cluster_inputs_ - void CreateInputOperand(PianoScope* scope, - symbolization::NoteBuilder* builder) const; + // why return std::unique_ptr ? PianoScope DISABLE_COPY_AND_ASSIGN + std::unique_ptr CreateInputOperand( + symbolization::NoteBuilder* builder) const; // run PianoOpKernel's Compile void RunCompile(const GraphNodeVec& cluster, PianoScope* scope, symbolization::NoteBuilder* builder) const; // topologic sorting graph node - void TopologicSortCluster(GraphNodeVec* cluster_sorted) const; + GraphNodeVec SortInternalCluster() const; }; } // namespace piano diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc index 0463d870bce09..7008f682e0071 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor_test.cc @@ -22,7 +22,7 @@ limitations under the License. */ #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel.h" #include "paddle/fluid/compiler/paddle2piano/piano_op_kernel_context.h" #include "paddle/fluid/compiler/paddle2piano/piano_op_registry.h" -#include "paddle/fluid/compiler/paddle2piano/vartype2notetype.h" +#include "paddle/fluid/compiler/paddle2piano/vartype_utils.h" #include "paddle/fluid/framework/ir/node.h" namespace paddle { @@ -253,7 +253,7 @@ TEST(GraphExecutorTest, basic) { const auto& entry_param = entry_sig.parameters(0); ASSERT_TRUE(entry_param.has_element_type()); ASSERT_EQ(entry_param.element_type(), - VarType2NoteType(framework::proto::VarType::FP32)); + utils::VarType2NoteType(framework::proto::VarType::FP32)); ASSERT_EQ(entry_param.dimensions_size(), 1); ASSERT_EQ(entry_param.dimensions(0), 64); } diff --git a/paddle/fluid/compiler/paddle2piano/vartype_utils.cc b/paddle/fluid/compiler/paddle2piano/vartype_utils.cc new file mode 100644 index 0000000000000..6b9fbb4d2f888 --- /dev/null +++ b/paddle/fluid/compiler/paddle2piano/vartype_utils.cc @@ -0,0 +1,82 @@ +/* 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/compiler/paddle2piano/vartype_utils.h" + +#include +#include + +#include "paddle/fluid/framework/data_type.h" +#include "paddle/fluid/platform/enforce.h" + +namespace paddle { +namespace piano { +namespace utils { + +using framework::proto::VarType; + +namespace { +const std::unordered_map& +GetVarType2NoteTypeMap() { + static std::unordered_map + vartype2notetype = {{framework::proto::VarType::BOOL, note::B1}, + {framework::proto::VarType::INT8, note::S8}, + {framework::proto::VarType::INT16, note::S16}, + {framework::proto::VarType::INT32, note::S32}, + {framework::proto::VarType::INT64, note::S64}, + {framework::proto::VarType::FP16, note::F16}, + {framework::proto::VarType::FP32, note::F32}, + {framework::proto::VarType::FP64, note::F64}, + {framework::proto::VarType::UINT8, note::U8}, + {framework::proto::VarType::SIZE_T, note::U64}}; + return vartype2notetype; +} +} // namespace + +note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { + const auto& vartype2notetype = GetVarType2NoteTypeMap(); + PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), + "Unsupported value data type (%s)", + framework::DataTypeToString(type).c_str()); + return vartype2notetype.at(type); +} + +VarType::Type GetVarDataType(const framework::VarDesc* var) { + auto var_type = var->GetType(); + + // non-pod type list + static std::unordered_set non_pod_types = { + VarType::LOD_TENSOR, VarType::SELECTED_ROWS, VarType::LOD_TENSOR_ARRAY}; + if (non_pod_types.count(var_type) != 0) { + // if the value type is non-pod type + var_type = var->GetDataType(); + } + + // check whether value type is supported + if (GetVarType2NoteTypeMap().count(var_type) != 0) { + // if value type is supported type + return var_type; + } + + PADDLE_THROW(platform::errors::Unimplemented( + "Unsupported value data type (%s)", + framework::DataTypeToString(var_type).c_str())); + return framework::proto::VarType::RAW; +} + +} // namespace utils +} // namespace piano +} // namespace paddle diff --git a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h b/paddle/fluid/compiler/paddle2piano/vartype_utils.h similarity index 72% rename from paddle/fluid/compiler/paddle2piano/vartype2notetype.h rename to paddle/fluid/compiler/paddle2piano/vartype_utils.h index 2fcda81d38324..6ce34e983680b 100644 --- a/paddle/fluid/compiler/paddle2piano/vartype2notetype.h +++ b/paddle/fluid/compiler/paddle2piano/vartype_utils.h @@ -18,12 +18,18 @@ limitations under the License. */ #include "paddle/fluid/compiler/piano/note/note.pb.h" #include "paddle/fluid/framework/framework.pb.h" +#include "paddle/fluid/framework/var_desc.h" namespace paddle { namespace piano { +namespace utils { -extern note::ElementTypeProto VarType2NoteType( - framework::proto::VarType::Type type); +// get var's data type +framework::proto::VarType::Type GetVarDataType(const framework::VarDesc* var); +// convert framework VarType to piano NoteType +note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type); + +} // namespace utils } // namespace piano } // namespace paddle From 03b2738804b1f16b06ed8150d03545dcb439df10 Mon Sep 17 00:00:00 2001 From: jiangcheng Date: Thu, 2 Sep 2021 08:38:47 +0000 Subject: [PATCH 15/15] fix some potential problem --- paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc | 6 +++--- paddle/fluid/compiler/paddle2piano/piano_scope.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc index b5e9949325b4c..303580f2761f7 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc +++ b/paddle/fluid/compiler/paddle2piano/piano_graph_executor.cc @@ -56,7 +56,7 @@ std::unique_ptr PianoGraphExecutor::CreateInputOperand( // store into PianoScope scope->SetOperand(var_name, op); } - return std::move(scope); + return scope; } GraphNodeVec PianoGraphExecutor::SortInternalCluster() const { @@ -138,11 +138,11 @@ note::ModuleProto PianoGraphExecutor::operator()() const { symbolization::NoteBuilder builder(builder_name); // Step2: create graph's input operand - auto&& scope = CreateInputOperand(&builder); + auto scope = CreateInputOperand(&builder); // Step3: topo sort graph // rvalue references avoid useless copy - auto&& cluster_sorted = SortInternalCluster(); + const auto& cluster_sorted = SortInternalCluster(); // Step4: get PianoOpKernel and run compile RunCompile(cluster_sorted, scope.get(), &builder); diff --git a/paddle/fluid/compiler/paddle2piano/piano_scope.h b/paddle/fluid/compiler/paddle2piano/piano_scope.h index eb62785f9d3b0..18b12e05aeb04 100644 --- a/paddle/fluid/compiler/paddle2piano/piano_scope.h +++ b/paddle/fluid/compiler/paddle2piano/piano_scope.h @@ -123,12 +123,13 @@ class PianoScope { private: explicit PianoScope(const PianoScope* parent) : parent_(parent) {} - DISABLE_COPY_AND_ASSIGN(PianoScope); - std::unordered_map operands_; const PianoScope* parent_; mutable std::vector> kids_; + + // keep this macro in the last line + DISABLE_COPY_AND_ASSIGN(PianoScope); }; } // namespace piano