From f5fd8b2010f781f9ce6efba2c405c3921615797e Mon Sep 17 00:00:00 2001 From: Yin Zhenhua Date: Tue, 7 Apr 2020 12:17:13 +0000 Subject: [PATCH] add dropout op; add sigmoid and elementwise_mul to subgraph_bridge --- lite/kernels/mlu/bridges/CMakeLists.txt | 3 + lite/kernels/mlu/bridges/dropout_op.cc | 84 ++++++++++ lite/kernels/mlu/bridges/dropout_op_test.cc | 158 ++++++++++++++++++ lite/kernels/mlu/bridges/paddle_use_bridges.h | 3 + 4 files changed, 248 insertions(+) create mode 100644 lite/kernels/mlu/bridges/dropout_op.cc create mode 100644 lite/kernels/mlu/bridges/dropout_op_test.cc diff --git a/lite/kernels/mlu/bridges/CMakeLists.txt b/lite/kernels/mlu/bridges/CMakeLists.txt index 30d5571537..ceaac8ac32 100644 --- a/lite/kernels/mlu/bridges/CMakeLists.txt +++ b/lite/kernels/mlu/bridges/CMakeLists.txt @@ -19,6 +19,7 @@ lite_cc_library(subgraph_bridge_scale_op_mlu SRCS scale_op.cc DEPS ${subgraph_br lite_cc_library(subgraph_bridge_interp_op_mlu SRCS interpolate_op.cc DEPS ${subgraph_bridge_deps_mlu}) lite_cc_library(subgraph_bridge_concat_op_mlu SRCS concat_op.cc DEPS ${subgraph_bridge_deps_mlu}) lite_cc_library(subgraph_bridge_transpose_op_mlu SRCS transpose_op.cc DEPS ${subgraph_bridge_deps_mlu}) +lite_cc_library(subgraph_bridge_dropout_op_mlu SRCS dropout_op.cc DEPS ${subgraph_bridge_deps_mlu}) set(mlu_subgraph_bridges subgraph_bridge_registry subgraph_bridge_utility_mlu @@ -34,6 +35,7 @@ set(mlu_subgraph_bridges subgraph_bridge_scale_op_mlu subgraph_bridge_interp_op_mlu subgraph_bridge_concat_op_mlu + subgraph_bridge_dropout_op_mlu CACHE INTERNAL "mlu_subgraph_bridges") lite_cc_library(subgraph_test_helper_mlu SRCS test_helper.cc DEPS ${mlu_subgraph_bridges}) @@ -48,4 +50,5 @@ lite_cc_test(test_scale_converter_mlu SRCS scale_op_test.cc DEPS scope optimizer lite_cc_test(test_interp_converter_mlu SRCS interpolate_op_test.cc DEPS scope optimizer target_wrapper_host model_parser program ${mlu_subgraph_bridges} subgraph_compute_mlu subgraph_test_helper_mlu) lite_cc_test(test_concat_converter_mlu SRCS concat_op_test.cc DEPS scope optimizer target_wrapper_host model_parser program ${mlu_subgraph_bridges} subgraph_compute_mlu subgraph_test_helper_mlu) lite_cc_test(test_transpose_converter_mlu SRCS transpose_op_test.cc DEPS scope optimizer target_wrapper_host model_parser program ${mlu_subgraph_bridges} subgraph_compute_mlu subgraph_test_helper_mlu) +lite_cc_test(test_dropout_converter_mlu SRCS dropout_op_test.cc DEPS scope optimizer target_wrapper_host model_parser program ${mlu_subgraph_bridges} subgraph_compute_mlu subgraph_test_helper_mlu) message(STATUS "+++++ mlu_subgraph_bridges: ${mlu_subgraph_bridges}") diff --git a/lite/kernels/mlu/bridges/dropout_op.cc b/lite/kernels/mlu/bridges/dropout_op.cc new file mode 100644 index 0000000000..558d4018d7 --- /dev/null +++ b/lite/kernels/mlu/bridges/dropout_op.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2019 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 "lite/kernels/mlu/bridges/graph.h" +#include "lite/kernels/mlu/bridges/utility.h" +#include "lite/kernels/npu/bridges/registry.h" + +namespace paddle { +namespace lite { +namespace subgraph { +namespace mlu { + +int DropoutConverter(void* ctx, OpLite* op, KernelBase* kernel) { + CHECK(ctx != nullptr); + CHECK(op != nullptr); + auto graph = static_cast(ctx); + auto op_info = op->op_info(); + auto op_type = op_info->Type(); + auto scope = op->scope(); + VLOG(3) << "[MLU] Converting " + op_type + "..."; + + // Create act node and set params from op + auto x_var_name = op_info->Input("X").front(); + auto out_var_name = op_info->Output("Out").front(); + auto output = scope->FindVar(out_var_name)->GetMutable(); + auto output_dims = output->dims().Vectorize(); + auto output_tensor = graph->AddNode( + out_var_name, output_dims, CNML_TENSOR, CNML_NCHW, graph->FPType()); + + // if(op_info->HasAttr("is_test")){ + // auto is_test = op_info->GetAttr("is_test"); + // CHECK(is_test != true); // The dropout op has no training + // implementation, only inference implementation + // } + auto dropout_implementation = + op_info->GetAttr("dropout_implementation"); + auto dropout_prob = op_info->GetAttr("dropout_prob"); + float alpha = 1.0f - dropout_prob; + if (dropout_implementation == "upscale_in_train") { + alpha = 1.; + } + float beta = 0.; + + std::vector shape = {1, 1, 1, 1}; + + std::string prefix = string_format("_%p", op); + auto alpha_tensor = graph->AddNode( + "Alpha" + prefix, shape, CNML_CONST, CNML_NHWC, graph->FPType()); + auto beta_tensor = graph->AddNode( + "Beta" + prefix, shape, CNML_CONST, CNML_NHWC, graph->FPType()); + + graph->BindConstRawData("Alpha" + prefix, &alpha, 1); + graph->BindConstRawData("Beta" + prefix, &beta, 1); + + auto input_tensor = graph->GetNode(x_var_name); + cnmlBaseOp_t scale_op; + CNML_CALL(cnmlCreateScaleOp(&scale_op, + input_tensor->mlu_tensor(), + output_tensor->mlu_tensor(), + alpha_tensor->mlu_tensor(), + beta_tensor->mlu_tensor())); + graph->FuseOp(scale_op); + return SUCCESS; +} + +} // namespace mlu +} // namespace subgraph +} // namespace lite +} // namespace paddle + +REGISTER_SUBGRAPH_BRIDGE(dropout, + kMLU, + paddle::lite::subgraph::mlu::DropoutConverter); diff --git a/lite/kernels/mlu/bridges/dropout_op_test.cc b/lite/kernels/mlu/bridges/dropout_op_test.cc new file mode 100644 index 0000000000..44f03e3051 --- /dev/null +++ b/lite/kernels/mlu/bridges/dropout_op_test.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2019 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 "lite/operators/dropout_op.h" +#include +#include +#include "lite/core/op_registry.h" +#include "lite/kernels/mlu/bridges/test_helper.h" +#include "lite/kernels/npu/bridges/registry.h" + +namespace paddle { +namespace lite { +namespace subgraph { +namespace mlu { + +void dropout_ref(const std::shared_ptr op) { + Scope* scope = op->scope(); + const OpInfo* op_info = op->op_info(); + auto x = scope->FindVar(op_info->Input("X").front())->GetMutable(); + auto out = + scope->FindVar(op_info->Output("Out").front())->GetMutable(); + auto dropout_implementation = + op_info->GetAttr("dropout_implementation"); + auto dropout_prob = op_info->GetAttr("dropout_prob"); + float alpha = 1.0f - dropout_prob; + if (dropout_implementation == "upscale_in_train") { + alpha = 1.; + } + float beta = 0.; + + auto x_data = x->data(); + auto out_data = out->mutable_data(); + DDim x_dims = x->dims(); + DDim out_dims = out->dims(); + CHECK_EQ(x_dims.production(), out_dims.production()); + for (int i = 0; i < out_dims.production(); i++) { + out_data[i] = x_data[i] * alpha + beta; + } +} + +void test_dropout(int bs, + int ic, + int ih, + int iw, + std::string dropout_implementation, + float dropout_prob, + float bias) { + // prepare input&output variables + Scope scope; + std::string x_var_name("x"); + std::string out_var_name("out"); + std::string mask_var_name("mask"); + std::string out_ref_var_name("out_ref"); + auto* x = scope.Var(x_var_name)->GetMutable(); + auto* out = scope.Var(out_var_name)->GetMutable(); + auto* mask = scope.Var(mask_var_name)->GetMutable(); + auto* out_ref = scope.Var(out_ref_var_name)->GetMutable(); + x->Resize({bs, ic, ih, iw}); + + // initialize input&output data + FillTensor(x); + + // initialize op desc + bool is_test = true; + bool fix_seed = false; + int seed = 0; + cpp::OpDesc opdesc; + opdesc.SetType("dropout"); + opdesc.SetInput("X", {x_var_name}); + opdesc.SetOutput("Out", {out_var_name}); + opdesc.SetOutput("Mask", {mask_var_name}); + opdesc.SetAttr("is_test", is_test); + opdesc.SetAttr("fix_seed", fix_seed); + opdesc.SetAttr("seed", seed); + opdesc.SetAttr("dropout_implementation", dropout_implementation); + opdesc.SetAttr("dropout_prob", dropout_prob); + VLOG(6) << "mask: " << mask->dims()[0] << std::endl; + // create and convert op to MLU model, then run it on MLU + auto op = CreateOp(opdesc, &scope); + dropout_ref(op); + out_ref->CopyDataFrom(*out); + + Tensor input_trans; + input_trans.Resize({bs, ic, ih, iw}); + transpose(x->mutable_data(), + input_trans.mutable_data(), + {bs, ic, ih, iw}, + {0, 2, 3, 1}); + auto os = out->dims(); + out->Resize({static_cast(os[0]), + static_cast(os[2]), + static_cast(os[3]), + static_cast(os[1])}); + x->CopyDataFrom(input_trans); + x->Resize({bs, ih, iw, ic}); + + LaunchOp(op, {x_var_name}, {out_var_name}); + + // execute reference implementation and save to output tensor('out') + + // compare results + auto* out_data = out->mutable_data(); + auto* out_ref_data = out_ref->mutable_data(); + Tensor output_trans; + output_trans.Resize(os); + transpose(out_data, + output_trans.mutable_data(), + {static_cast(os[0]), + static_cast(os[2]), + static_cast(os[3]), + static_cast(os[1])}, + {0, 3, 1, 2}); + out_data = output_trans.mutable_data(); + for (int i = 0; i < out->dims().production(); i++) { + VLOG(5) << i; + EXPECT_NEAR(out_data[i], out_ref_data[i], 1e-5); + } +} + +TEST(MLUBridges, dropout) { + for (auto bs : {1, 3}) { + for (auto ic : {1, 3}) { + for (auto ih : {3, 4}) { + for (auto iw : {4, 3}) { + for (auto dropout_implementation : + {"downgrade_in_infer", "upscale_in_train"}) { + for (auto dropout_prob : {0.f, 1.0f}) { + VLOG(3) << "bs: " << bs << " ic: " << ic << " ih: " << ih + << " iw: " << iw + << " dropout_implementation: " << dropout_implementation + << " dropout_prob: " << dropout_prob; + test_dropout( + bs, ic, ih, iw, dropout_implementation, dropout_prob, 0.); + } + } + } + } + } + } +} + +} // namespace mlu +} // namespace subgraph +} // namespace lite +} // namespace paddle + +USE_SUBGRAPH_BRIDGE(dropout, kMLU); diff --git a/lite/kernels/mlu/bridges/paddle_use_bridges.h b/lite/kernels/mlu/bridges/paddle_use_bridges.h index c65c75b307..559b348cf4 100644 --- a/lite/kernels/mlu/bridges/paddle_use_bridges.h +++ b/lite/kernels/mlu/bridges/paddle_use_bridges.h @@ -28,3 +28,6 @@ USE_SUBGRAPH_BRIDGE(transpose, kMLU); USE_SUBGRAPH_BRIDGE(transpose2, kMLU); USE_SUBGRAPH_BRIDGE(concat, kMLU); USE_SUBGRAPH_BRIDGE(scale, kMLU); +USE_SUBGRAPH_BRIDGE(sigmoid, kMLU); +USE_SUBGRAPH_BRIDGE(elementwise_mul, kMLU); +USE_SUBGRAPH_BRIDGE(dropout, kMLU); -- GitLab