From 156146292577da961dc4be039c6cd0187a136086 Mon Sep 17 00:00:00 2001 From: zhengjun10 Date: Sat, 1 Aug 2020 19:37:29 +0800 Subject: [PATCH] add anf pass --- mindspore/lite/src/gllo/common/utils.cc | 68 +++++- mindspore/lite/src/gllo/common/utils.h | 19 +- .../src/gllo/fusion/conv_activation_fusion.cc | 34 +-- .../src/gllo/fusion/conv_activation_fusion.h | 7 +- .../src/gllo/fusion/conv_biasadd_fusion.cc | 163 ++++++++++---- .../src/gllo/fusion/conv_biasadd_fusion.h | 2 +- .../lite/src/gllo/fusion/conv_bn_fusion.cc | 141 ++++++++++++ .../lite/src/gllo/fusion/conv_bn_fusion.h | 31 +++ .../lite/src/gllo/fusion/conv_scale_fusion.cc | 131 ++++-------- .../lite/src/gllo/fusion/conv_scale_fusion.h | 21 +- .../src/gllo/fusion/conv_transform_fusion.cc | 201 ++++++++++++++++++ .../src/gllo/fusion/conv_transform_fusion.h | 37 ++++ mindspore/lite/test/CMakeLists.txt | 2 + mindspore/lite/tools/converter/CMakeLists.txt | 2 + .../lite/tools/converter/anf_transform.cc | 15 +- 15 files changed, 699 insertions(+), 175 deletions(-) create mode 100644 mindspore/lite/src/gllo/fusion/conv_bn_fusion.cc create mode 100644 mindspore/lite/src/gllo/fusion/conv_bn_fusion.h create mode 100644 mindspore/lite/src/gllo/fusion/conv_transform_fusion.cc create mode 100644 mindspore/lite/src/gllo/fusion/conv_transform_fusion.h diff --git a/mindspore/lite/src/gllo/common/utils.cc b/mindspore/lite/src/gllo/common/utils.cc index 9433a049181..17b781c1c68 100644 --- a/mindspore/lite/src/gllo/common/utils.cc +++ b/mindspore/lite/src/gllo/common/utils.cc @@ -22,11 +22,8 @@ using PrimitiveTValuePtr = std::shared_ptr; namespace mindspore { namespace opt { - bool AnfEqual(const BaseRef &a, const BaseRef &b) { - if (utils::isa(a) && utils::isa(b)) { - return true; - } else if (utils::isa(a) && utils::isa(b)) { + if (utils::isa(a) && utils::isa(b)) { auto a_node = utils::cast(a); auto b_node = utils::cast(b); MS_EXCEPTION_IF_NULL(a_node); @@ -80,6 +77,7 @@ bool AnfEqual(const BaseRef &a, const BaseRef &b) { auto b_value_node_ptr = b.m_ptr->cast(); return a_value_node_ptr->GetPrimitiveT()->value.type == b_value_node_ptr->GetPrimitiveT()->value.type; } + return a == b; } @@ -202,22 +200,72 @@ void CheckIfVarIsNull(const VarPtr &var) { } } +void CheckIfNodeIsParam(const AnfNodePtr &node) { + if (node != nullptr && !utils::isa(node)) { + MS_LOG(EXCEPTION) << "The Node is not param."; + } +} + void CheckInputSize(const CNodePtr &node, const int size) { if (node->inputs().size() != size) { MS_LOG(EXCEPTION) << "The input size of node must be " << size << ", but it is" << node->inputs().size(); } } -schema::PrimitiveType GetCNodeType(const CNodePtr &node) { - auto value_primitive = node->input(0); - auto value_node = value_primitive->cast(); - MS_ASSERT(value_node != nullptr); - auto value = value_node->value(); - MS_ASSERT(value != nullptr); +void CheckLeastInputSize(const CNodePtr &node, const int size) { + if (node->inputs().size() < size) { + MS_LOG(EXCEPTION) << "The input size of node must be " << size << ", but it is" << node->inputs().size(); + } +} + +AnfNodePtr AddNewBiasNode(float *bias_data, const FuncGraphPtr &func_graph, int kernel_num, + const ParamValueLitePtr &weight_tensor) { + auto bias_parameter = func_graph->add_parameter(); + MS_ASSERT(bias_parameter != nullptr); + std::vector shape = {kernel_num}; + auto abstract_tensor = std::make_shared(TypeIdToType(weight_tensor->tensor_type()), shape); + bias_parameter->set_abstract(abstract_tensor); + + ParamValueLitePtr param_value = std::make_shared(); + MS_ASSERT(param_value != nullptr); + param_value->set_tensor_addr(bias_data); + param_value->set_tensor_size(kernel_num * sizeof(float) / sizeof(uint8_t)); + bias_parameter->set_default_param(param_value); + return bias_parameter; +} + +schema::PrimitiveType GetCNodeType(const BaseRef &n) { + ValueNodePtr value_node; + if (utils::isa(n)) { + auto in = utils::cast(n); + value_node = in->input(0)->cast(); + } else if (utils::isa(n)) { + value_node = utils::cast(n); + } else { + MS_LOG(EXCEPTION) << "only value node or cnode has type"; + return schema::PrimitiveType_NONE; + } + MS_EXCEPTION_IF_NULL(value_node); + auto value = value_node->value(); + MS_ASSERT(value != nullptr); + if (utils::isa(value)) { auto primitive = value->cast(); MS_ASSERT(primitive != nullptr); return primitive->GetPrimitiveT()->value.type; + } + return schema::PrimitiveType_NONE; } +bool IsParamNode(const BaseRef &n) { + return utils::isa(n); +} + +bool IsConvNode(const BaseRef &n) { + if (utils::isa(n) || utils::isa(n)) { + auto type = opt::GetCNodeType(n); + return type == schema::PrimitiveType_Conv2D || type == schema::PrimitiveType_DepthwiseConv2D; + } + return false; +} } // namespace opt } // namespace mindspore diff --git a/mindspore/lite/src/gllo/common/utils.h b/mindspore/lite/src/gllo/common/utils.h index 3147bd329f4..91b73c0d31f 100644 --- a/mindspore/lite/src/gllo/common/utils.h +++ b/mindspore/lite/src/gllo/common/utils.h @@ -17,12 +17,16 @@ #ifndef MINDSPORE_LITE_SRC_PASS_COMMON_UTILS_H_ #define MINDSPORE_LITE_SRC_PASS_COMMON_UTILS_H_ +#include +#include #include "ir/anf.h" #include "ir/func_graph.h" #include "src/common/utils.h" #include "src/gllo/common/pattern_engine.h" #include "schema/inner/model_generated.h" +#include "src/param_value_lite.h" +using PrimitiveTValuePtr = std::shared_ptr; namespace mindspore { namespace opt { @@ -41,11 +45,20 @@ void CheckIfCNodeIsNull(const CNodePtr &node); void CheckIfVarIsNull(const VarPtr &var); -void CheckInputSize(const CNodePtr &node, const int size); +void CheckInputSize(const CNodePtr &node, int size); -schema::PrimitiveType GetCNodeType(const CNodePtr &node); +void CheckIfNodeIsParam(const AnfNodePtr &node); +void CheckLeastInputSize(const CNodePtr &node, int size); + +AnfNodePtr AddNewBiasNode(float *bias_data, const FuncGraphPtr &func_graph, int kernel_num, + const ParamValueLitePtr &weight_tensor); + +schema::PrimitiveType GetCNodeType(const BaseRef &node); + +bool IsParamNode(const BaseRef &n); + +bool IsConvNode(const BaseRef &n); } // namespace opt } // namespace mindspore #endif // MINDSPORE_LITE_SRC_PASS_COMMON_UTILS_H_ - diff --git a/mindspore/lite/src/gllo/fusion/conv_activation_fusion.cc b/mindspore/lite/src/gllo/fusion/conv_activation_fusion.cc index 46d1273f99c..784b607036c 100644 --- a/mindspore/lite/src/gllo/fusion/conv_activation_fusion.cc +++ b/mindspore/lite/src/gllo/fusion/conv_activation_fusion.cc @@ -14,23 +14,24 @@ * limitations under the License. */ -#include "src/gllo/fusion/conv_activation_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_activation_fusion.h" #include -#include "schema/inner/model_generated.h" -#include "src/ir/primitive_t_value.h" +#include "mindspore/lite/schema/inner/model_generated.h" +#include "mindspore/lite/src/ir/primitive_t_value.h" #include "mindspore/ccsrc/utils/utils.h" -#include "src/gllo/common/utils.h" +#include "mindspore/lite/src/gllo/common/utils.h" -namespace mindspore { -namespace opt { +namespace mindspore::opt { +namespace { +constexpr size_t kActivationInputsLength = 2; +} const BaseRef ConvActivationFusion::DefinePattern() const { - VarPtr X = std::make_shared(); - // conv2d inputs may be 2 or 3 inputs,match move to process + auto conv_var = std::make_shared(IsConvNode); auto prim = new schema::PrimitiveT(); prim->value.type = primitive_type; auto prim_value = std::make_shared(prim); - return VectorRef({prim_value, X}); + return VectorRef({prim_value, conv_var}); } const AnfNodePtr ConvActivationFusion::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, @@ -41,7 +42,7 @@ const AnfNodePtr ConvActivationFusion::Process(const FuncGraphPtr &func_graph, c CheckIfAnfNodeIsNull(node); auto act_node = node->cast(); CheckIfCNodeIsNull(act_node); - CheckInputSize(act_node, 2); + CheckInputSize(act_node, kActivationInputsLength); auto act_primitive = GetValueNode>(act_node->input(0)); if (act_primitive->GetPrimitiveT()->value.AsActivation()->type != activation_type) { @@ -52,13 +53,18 @@ const AnfNodePtr ConvActivationFusion::Process(const FuncGraphPtr &func_graph, c if (pre_node != nullptr && pre_node->isa()) { auto conv_node = pre_node->cast(); auto node_type = GetCNodeType(conv_node); - if (node_type == schema::PrimitiveType_Conv2D || node_type == schema::PrimitiveType_DepthwiseConv2D) { - auto primitiveT_value = GetValueNode>(conv_node->input(0)); + auto primitiveT_value = GetValueNode>(conv_node->input(0)); + MS_ASSERT(primitiveT_value); + if (node_type == schema::PrimitiveType_Conv2D) { primitiveT_value->GetPrimitiveT()->value.AsConv2D()->activationType = activation_type; return pre_node; + } else if (node_type == schema::PrimitiveType_DepthwiseConv2D) { + primitiveT_value->GetPrimitiveT()->value.AsDepthwiseConv2D()->activationType = activation_type; + return pre_node; + } else { + MS_LOG(EXCEPTION) << "conv activation pass match only conv2d or depthwise_conv2d "; } } return node; } -} // namespace opt -} // namespace mindspore +} // namespace mindspore::opt diff --git a/mindspore/lite/src/gllo/fusion/conv_activation_fusion.h b/mindspore/lite/src/gllo/fusion/conv_activation_fusion.h index a3e605db446..70aa2622433 100644 --- a/mindspore/lite/src/gllo/fusion/conv_activation_fusion.h +++ b/mindspore/lite/src/gllo/fusion/conv_activation_fusion.h @@ -17,16 +17,17 @@ #ifndef MINDSPORE_LITE_SRC_PASS_FUSION_CONV_ACTIVATION_FUSION_H_ #define MINDSPORE_LITE_SRC_PASS_FUSION_CONV_ACTIVATION_FUSION_H_ -#include "src/gllo/common/optimizer.h" +#include +#include "mindspore/lite/src/gllo/common/optimizer.h" namespace mindspore { namespace opt { class ConvActivationFusion : public PatternProcessPass { public: - explicit ConvActivationFusion(bool multigraph = true, + explicit ConvActivationFusion(bool multigraph = true, const std::string &name = "conv_activation_fusion", schema::PrimitiveType primitive = schema::PrimitiveType_LeakyReLU, schema::ActivationType activation = schema::ActivationType_LEAKY_RELU) : primitive_type( - primitive), activation_type(activation), PatternProcessPass("conv_activation_fusion", multigraph) {} + primitive), activation_type(activation), PatternProcessPass(name, multigraph) {} ~ConvActivationFusion() override = default; const BaseRef DefinePattern() const override; const AnfNodePtr Process(const FuncGraphPtr &, const AnfNodePtr &, const EquivPtr &) const override; diff --git a/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.cc b/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.cc index ca03d963675..d6ad80382b8 100644 --- a/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.cc +++ b/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.cc @@ -13,35 +13,116 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "src/gllo/fusion/conv_biasadd_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h" +#include #include -#include "schema/inner/model_generated.h" -#include "src/ir/primitive_t_value.h" +#include "mindspore/lite/schema/inner/model_generated.h" +#include "mindspore/lite/src/ir/primitive_t_value.h" #include "mindspore/ccsrc/utils/utils.h" -#include "src/gllo/common/utils.h" +#include "mindspore/lite/src/gllo/common/utils.h" -namespace mindspore { -namespace opt { +namespace mindspore::opt { +namespace { +constexpr size_t kAddInputsLength = 3; +constexpr size_t kAddWEIGHTINDEX = 2; +constexpr size_t kConvWeightIndex = 2; +constexpr size_t kConvBiasIndex = 3; +constexpr size_t kConvNoBiasLen = 3; +constexpr size_t kConvWithBiasLen = 4; +bool IsConvExtendNode(const BaseRef &n) { + if (utils::isa(n) || utils::isa(n)) { + auto type = opt::GetCNodeType(n); + return type == schema::PrimitiveType_Conv2D || type == schema::PrimitiveType_DepthwiseConv2D + || type == schema::PrimitiveType_DeConv2D; + } + return false; +} +bool IsAddNode(const BaseRef &n) { + if (utils::isa(n) || utils::isa(n)) { + auto type = opt::GetCNodeType(n); + return type == schema::PrimitiveType_Add || type == schema::PrimitiveType_BiasAdd; + } + return false; +} +int Get_Kenrnel_nums(const CNodePtr &conv_node) { + MS_ASSERT(conv_node != nullptr); + auto value_primitive = conv_node->input(0); + auto value_node = value_primitive->cast(); + MS_ASSERT(value_node != nullptr); + auto value = value_node->value(); + MS_ASSERT(value != nullptr); + auto primitive = value->cast(); + MS_ASSERT(primitive != nullptr); + auto type = primitive->GetPrimitiveT()->value.type; + if (type == schema::PrimitiveType_Conv2D) { + return primitive->GetPrimitiveT()->value.AsConv2D()->channelOut; + } else if (type == schema::PrimitiveType_DepthwiseConv2D) { + return primitive->GetPrimitiveT()->value.AsDepthwiseConv2D()->channelMultiplier + * primitive->GetPrimitiveT()->value.AsDepthwiseConv2D()->channelIn; + } else if (type == schema::PrimitiveType_DeConv2D) { + return primitive->GetPrimitiveT()->value.AsDeConv2D()->channelOut; + } else { + MS_LOG(ERROR) << "Unsupported opType, " << type; + return 0; + } +} +void GenConvNewBias(const FuncGraphPtr &func_graph, const CNodePtr &conv_node, const CNodePtr &bias_node) { + AnfNodePtr conv_bias_node = nullptr; + AnfNodePtr conv_weight_node = nullptr; + if (conv_node->inputs().size() == kConvNoBiasLen) { + conv_weight_node = conv_node->input(kConvWeightIndex); + } else if (conv_node->inputs().size() == kConvWithBiasLen) { + conv_weight_node = conv_node->input(kConvWeightIndex); + conv_bias_node = conv_node->input(kConvBiasIndex); + } else { + MS_LOG(EXCEPTION) << "conv node:" << conv_node->DebugString() << "inputs size must 3 or 4"; + } + auto kernel_nums = Get_Kenrnel_nums(conv_node); + if (kernel_nums <= 0) { + MS_LOG(EXCEPTION) << "kernel num less than 0"; + } + auto add_bias_data = new(std::nothrow) float[kernel_nums]; + auto bias_add_weight = bias_node->input(kAddWEIGHTINDEX); + CheckIfNodeIsParam(bias_add_weight); + auto add_weight_param = bias_add_weight->cast()->default_param(); + auto add_weight_tensor = std::dynamic_pointer_cast(add_weight_param); + auto add_weight_data = reinterpret_cast(add_weight_tensor->tensor_addr()); + + if (add_weight_tensor->tensor_shape().empty()) { + if (0 != memset_s(add_bias_data, kernel_nums * sizeof(float), *add_weight_data, kernel_nums * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset_s conv_bias_data failed"; + } + } else { + if (0 != memcpy_s(add_bias_data, kernel_nums * sizeof(float), add_weight_data, kernel_nums * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset_s conv_bias_data failed"; + } + } + if (conv_bias_node != nullptr) { + CheckIfNodeIsParam(conv_bias_node); + auto conv_bias_param = conv_bias_node->cast()->default_param(); + auto conv_bias_tensor = std::dynamic_pointer_cast(conv_bias_param); + if (conv_bias_tensor->tensor_shape().empty() || conv_bias_tensor->tensor_shape()[0] != kernel_nums) { + MS_LOG(EXCEPTION) << "conv_bias_node shape error"; + } + auto conv_bias_data = reinterpret_cast(conv_bias_tensor->tensor_addr()); + for (size_t i = 0; i < kernel_nums; i++) { + conv_bias_data[i] += add_bias_data[i]; + } + delete[] add_bias_data; + } else { + auto conv_weight_param = conv_weight_node->cast()->default_param(); + auto conv_weight_tensor = std::dynamic_pointer_cast(conv_weight_param); + auto conv_new_bias = AddNewBiasNode(add_bias_data, func_graph, kernel_nums, conv_weight_tensor); + conv_node->add_input(conv_new_bias); + } +} +} // namespace const BaseRef ConvBiasaddFusion::DefinePattern() const { - MS_LOG(DEBUG) << "Enter pattern"; - - VarPtr X = std::make_shared(); - VarPtr W = std::make_shared(); - VarPtr B = std::make_shared(); - CheckIfVarIsNull(X); - CheckIfVarIsNull(W); - CheckIfVarIsNull(B); - - auto prim1 = new schema::PrimitiveT(); - prim1->value.type = schema::PrimitiveType_BiasAdd; - auto prim11 = std::make_shared(prim1); - - auto prim2 = new schema::PrimitiveT(); - prim2->value.type = schema::PrimitiveType_Conv2D; - auto prim22 = std::make_shared(prim2); - - return VectorRef({prim11, VectorRef({prim22, X, W}), B}); + auto conv_var = std::make_shared(IsConvExtendNode); + auto add_var = std::make_shared(IsAddNode); + auto weight_var = std::make_shared(IsParamNode); + return VectorRef({add_var, conv_var, weight_var}); } const AnfNodePtr ConvBiasaddFusion::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, @@ -50,24 +131,28 @@ const AnfNodePtr ConvBiasaddFusion::Process(const FuncGraphPtr &func_graph, cons CheckIfFuncGraphIsNull(func_graph); CheckIfAnfNodeIsNull(node); - auto cnode = node->cast(); - CheckIfCNodeIsNull(cnode); - CheckInputSize(cnode, 3); // [op, conv_node, bias_node] + auto add_node = node->cast(); + CheckIfCNodeIsNull(add_node); + CheckInputSize(add_node, kAddInputsLength); - AnfNodePtr conv_node_anf = cnode->input(1); + AnfNodePtr conv_node_anf = add_node->input(1); CheckIfAnfNodeIsNull(conv_node_anf); auto conv_node = conv_node_anf->cast(); CheckIfCNodeIsNull(conv_node); - CheckInputSize(conv_node, 3); // [op, X, W] - - conv_node->add_input(cnode->input(2)); - - auto primitive = (lite::PrimitiveTValue *)(conv_node->input(0)->cast()->value().get()); - primitive->GetPrimitiveT()->value.AsConv2D()->hasBias = true; - - return conv_node_anf; + GenConvNewBias(func_graph, conv_node, add_node); + auto primitiveT_value = GetValueNode>(conv_node->input(0)); + MS_ASSERT(primitiveT_value); + auto type = primitiveT_value->GetPrimitiveT()->value.type; + if (type == schema::PrimitiveType_Conv2D) { + primitiveT_value->GetPrimitiveT()->value.AsConv2D()->hasBias = true;; + } else if (type == schema::PrimitiveType_DepthwiseConv2D) { + primitiveT_value->GetPrimitiveT()->value.AsDepthwiseConv2D()->hasBias = true; + } else if (type == schema::PrimitiveType_DeConv2D) { + primitiveT_value->GetPrimitiveT()->value.AsDeConv2D()->hasBias = true; + } else { + MS_LOG(EXCEPTION) << "Unsupported opType, " << type; + } + return conv_node; } - -} // namespace opt -} // namespace mindspore +} // namespace mindspore::opt diff --git a/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h b/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h index df0f393ad51..72d903feb41 100644 --- a/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h +++ b/mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h @@ -17,7 +17,7 @@ #ifndef MINDSPORE_LITE_SRC_PASS_FUSION_CONV_BIASADD_FUSION_H_ #define MINDSPORE_LITE_SRC_PASS_FUSION_CONV_BIASADD_FUSION_H_ -#include "src/gllo/common/optimizer.h" +#include "mindspore/lite/src/gllo/common/optimizer.h" namespace mindspore { namespace opt { diff --git a/mindspore/lite/src/gllo/fusion/conv_bn_fusion.cc b/mindspore/lite/src/gllo/fusion/conv_bn_fusion.cc new file mode 100644 index 00000000000..fced388e008 --- /dev/null +++ b/mindspore/lite/src/gllo/fusion/conv_bn_fusion.cc @@ -0,0 +1,141 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 + *conv_activation_fusion.h + * 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 "mindspore/lite/src/gllo/fusion/conv_bn_fusion.h" +#include +#include +#include "mindspore/lite/schema/inner/model_generated.h" +#include "mindspore/lite/src/ir/primitive_t_value.h" +#include "mindspore/ccsrc/utils/utils.h" +#include "mindspore/lite/src/gllo/common/utils.h" + +namespace mindspore::opt { +namespace { +constexpr size_t kCaffeBNMeanIndex = 2; +constexpr size_t kCaffeBNVarIndex = 3; +constexpr size_t kTFBNScaleIndex = 2; +constexpr size_t kTFBNBiasIndex = 3; +constexpr size_t kTFBNMeanIndex = 4; +constexpr size_t kTFBNVarIndex = 5; +constexpr const float EPS = 1e-8; +constexpr const float EPS_DEFAULT_FLOAT = 1e-5; +constexpr const float POW_NUM = 0.5; +bool IsBatchNode(const BaseRef &n) { + if (utils::isa(n) || utils::isa(n)) { + auto type = opt::GetCNodeType(n); + return type == schema::PrimitiveType_CaffeBatchNorm || type == schema::PrimitiveType_FusedBatchNorm; + } + return false; +} +void CalTransale(const AnfNodePtr &bn_scale_node, const AnfNodePtr &bn_var_node, float *trans_scale, float eps, + int kernel_num) { + auto bn_var_param = bn_var_node->cast()->default_param(); + auto bn_var_tensor = std::dynamic_pointer_cast(bn_var_param); + auto bn_var_data = reinterpret_cast(bn_var_tensor->tensor_addr()); + // cal transScale, tf : scale/sqrt(variance + eps); caffe : 1/sqrt(variance + eps) + if (memcpy_s(trans_scale, kernel_num * sizeof(float), bn_var_data, kernel_num * sizeof(float)) != 0) { + MS_LOG(EXCEPTION) << "memcpy_s transScale error"; + return; + } + // 1/sqrt(variance + eps) + for (int32_t i = 0; i < kernel_num; i++) { + float tmp = trans_scale[i] + eps; + tmp = pow(tmp, POW_NUM); + trans_scale[i] = 1 / tmp; + } + if (bn_scale_node != nullptr) { + auto bn_scale_param = bn_scale_node->cast()->default_param(); + auto bn_scale_tensor = std::dynamic_pointer_cast(bn_scale_param); + auto bn_scale_data = reinterpret_cast(bn_scale_tensor->tensor_addr()); + // scale/sqrt(variance + eps) + for (int32_t i = 0; i < kernel_num; i++) { + trans_scale[i] *= bn_scale_data[i]; + } + } +} +void CalTransBias(const AnfNodePtr &bn_mean_node, const AnfNodePtr &bn_bias_node, const float *trans_scale, + float *trans_bias, int kernel_num) { + auto bn_mean_param = bn_mean_node->cast()->default_param(); + auto bn_mean_tensor = std::dynamic_pointer_cast(bn_mean_param); + auto bn_mean_data = reinterpret_cast(bn_mean_tensor->tensor_addr()); + // cal transBias, tf : -scale*mean/sqrt(variance + eps) + bias; caffe : -mean/sqrt(variance + eps) + // -mean/sqrt(variance + eps) + for (int32_t i = 0; i < kernel_num; i++) { + trans_bias[i] = -bn_mean_data[i] * trans_scale[i]; + } + + if (bn_bias_node != nullptr) { + auto bn_bias_param = bn_bias_node->cast()->default_param(); + auto bn_bias_tensor = std::dynamic_pointer_cast(bn_bias_param); + auto bn_bias_data = reinterpret_cast(bn_bias_tensor->tensor_addr()); + // -scale*mean/sqrt(variance + eps) + bias + for (int32_t i = 0; i < kernel_num; i++) { + trans_bias[i] += bn_bias_data[i]; + } + } +} +} // namespace +const BaseRef ConvBatchNormFusion::DefinePattern() const { + auto conv_var = std::make_shared(IsConvNode); + auto bn_var = std::make_shared(IsBatchNode); + auto bn_mean_var = std::make_shared(IsParamNode); + auto bn_variable_var = std::make_shared(IsParamNode); + auto bn_other_var = std::make_shared(); + return VectorRef({bn_var, conv_var, bn_mean_var, bn_variable_var, bn_other_var});; +} +// BatchNorm weight Tensor definition: +// caffe +// estimated_mean --0 +// estimated_variance --1 +// tensorflow +// scale -- 0 +// bias --1 +// estimated_mean --2 +// estimated_variance --3 +const void ConvBatchNormFusion::InitTransParam(const CNodePtr &bn_node, int kernel_num, float *trans_scale, + float *trans_bias) const { + MS_ASSERT(bn_node != nullptr); + AnfNodePtr bn_mean_node = nullptr; + AnfNodePtr bn_variance_node = nullptr; + AnfNodePtr bn_scale_node = nullptr; + AnfNodePtr bn_bias_node = nullptr; + float eps = 0; + auto primitiveT_value = GetValueNode>(bn_node->input(0)); + if (GetCNodeType(bn_node) == schema::PrimitiveType_CaffeBatchNorm) { + bn_mean_node = bn_node->input(kCaffeBNMeanIndex); + bn_variance_node = bn_node->input(kCaffeBNVarIndex); + CheckIfNodeIsParam(bn_mean_node); + CheckIfNodeIsParam(bn_variance_node); + eps = primitiveT_value->GetPrimitiveT()->value.AsCaffeBatchNorm()->epsilon; + } else if (GetCNodeType(bn_node) == schema::PrimitiveType_FusedBatchNorm) { + bn_scale_node = bn_node->input(kTFBNScaleIndex); + bn_bias_node = bn_node->input(kTFBNBiasIndex); + bn_mean_node = bn_node->input(kTFBNMeanIndex); + bn_variance_node = bn_node->input(kTFBNVarIndex); + eps = primitiveT_value->GetPrimitiveT()->value.AsFusedBatchNorm()->epsilon; + } else { + MS_LOG(EXCEPTION) << "not caffe or tf batchnorm op."; + } + CheckIfNodeIsParam(bn_mean_node); + CheckIfNodeIsParam(bn_variance_node); + if (eps < EPS) { + eps = EPS_DEFAULT_FLOAT; + } + + CalTransale(bn_scale_node, bn_variance_node, trans_scale, eps, kernel_num); + CalTransBias(bn_mean_node, bn_bias_node, trans_scale, trans_bias, kernel_num); +} +} // namespace mindspore::opt diff --git a/mindspore/lite/src/gllo/fusion/conv_bn_fusion.h b/mindspore/lite/src/gllo/fusion/conv_bn_fusion.h new file mode 100644 index 00000000000..c5a9dbc5ee5 --- /dev/null +++ b/mindspore/lite/src/gllo/fusion/conv_bn_fusion.h @@ -0,0 +1,31 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 + *conv_activation_fusion.h + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_LITE_SRC_PASS_FUSION_CONV_BN_FUSION_H_ +#define MINDSPORE_LITE_SRC_PASS_FUSION_CONV_BN_FUSION_H_ + +#include "mindspore/lite/src/gllo/fusion/conv_transform_fusion.h" + +namespace mindspore::opt { +class ConvBatchNormFusion : public ConvTransformFusion { + public: + explicit ConvBatchNormFusion(bool multigraph = true) : ConvTransformFusion(multigraph, "conv_batchnorm_fusion") {} + ~ConvBatchNormFusion() override = default; + const BaseRef DefinePattern() const override; + const void InitTransParam(const CNodePtr &, int, float *, float *) const override; +}; +} // namespace mindspore::opt +#endif // MINDSPORE_LITE_SRC_PASS_FUSION_CONV_BN_FUSION_H_ diff --git a/mindspore/lite/src/gllo/fusion/conv_scale_fusion.cc b/mindspore/lite/src/gllo/fusion/conv_scale_fusion.cc index 6d6d81d8b06..76a1693edb6 100644 --- a/mindspore/lite/src/gllo/fusion/conv_scale_fusion.cc +++ b/mindspore/lite/src/gllo/fusion/conv_scale_fusion.cc @@ -14,78 +14,51 @@ * limitations under the License. */ -#include "src/gllo/fusion/conv_scale_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_scale_fusion.h" #include -#include "schema/inner/model_generated.h" -#include "src/ir/primitive_t_value.h" -#include "src/param_value_lite.h" +#include "mindspore/lite/src/param_value_lite.h" +#include "mindspore/lite/schema/inner/model_generated.h" +#include "mindspore/lite/src/ir/primitive_t_value.h" #include "mindspore/ccsrc/utils/utils.h" -#include "src/gllo/common/utils.h" +#include "mindspore/lite/src/gllo/common/utils.h" #include "include/errorcode.h" -namespace mindspore { -namespace opt { +namespace mindspore::opt { +namespace { +constexpr size_t kScaleWeightIndex = 2; +constexpr size_t kScaleBiasIndex = 3; +constexpr size_t kScaleNoBiasLen = 3; +constexpr size_t kScaleWithBiasLen = 4; +bool IsScaleNode(const BaseRef &n) { + if (utils::isa(n) || utils::isa(n)) { + auto type = opt::GetCNodeType(n); + return type == schema::PrimitiveType_Scale; + } + return false; +} +} // namespace + const BaseRef ConvScaleFusion::DefinePattern() const { - VarPtr X = std::make_shared(); - // conv2d inputs may be 2 or 3 inputs,match move to process - auto prim = new schema::PrimitiveT(); - prim->value.type = schema::PrimitiveType_Scale; - auto prim_value = std::make_shared(prim); + auto conv_var = std::make_shared(IsConvNode); + auto bn_var = std::make_shared(IsScaleNode); + auto weight_var = std::make_shared(IsParamNode); + auto bias_var = std::make_shared(); - return VectorRef({prim_value, X}); + return VectorRef({bn_var, conv_var, weight_var, bias_var}); } - -const AnfNodePtr ConvScaleFusion::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, - const EquivPtr &) const { - MS_LOG(DEBUG) << "conv activation pass process"; - CheckIfFuncGraphIsNull(func_graph); - - CheckIfAnfNodeIsNull(node); - auto scale_node = node->cast(); - CheckIfCNodeIsNull(scale_node); - CheckInputSize(scale_node, 2); - - AnfNodePtr pre_node = scale_node->input(1); - CheckIfAnfNodeIsNull(pre_node); - if (pre_node != nullptr && pre_node->isa()) { - auto conv_node = pre_node->cast(); - auto node_type = GetCNodeType(conv_node); - if (node_type == schema::PrimitiveType_Conv2D || node_type == schema::PrimitiveType_DepthwiseConv2D) { - return DoFusion(conv_node, scale_node); - } - } - return node; -} -const AnfNodePtr ConvScaleFusion::DoFusion(const CNodePtr &conv_node, const CNodePtr &scale_node) const { - if (scale_node->inputs().size() == 3) { - GetTransParam(scale_node->input(2), nullptr); - } else if (scale_node->inputs().size() == 4) { - // todo add bias fusion zhengjun10 - GetTransParam(scale_node->input(2), scale_node->input(3)); +const void ConvScaleFusion::InitTransParam(const CNodePtr &scale_node, int kernel_num, float *trans_scale, + float *trans_bias) const { + MS_ASSERT(scale_node != nullptr); + AnfNodePtr scale_weight_node; + AnfNodePtr scale_bias_node; + if (scale_node->inputs().size() == kScaleNoBiasLen) { + scale_weight_node = scale_node->input(kScaleWeightIndex); + } else if (scale_node->inputs().size() == kScaleWithBiasLen) { + scale_weight_node = scale_node->input(kScaleWeightIndex); + scale_bias_node = scale_node->input(kScaleBiasIndex); } else { - MS_LOG(ERROR) << "scale inputs size is error:" << scale_node->DebugString(); - return nullptr; + MS_LOG(EXCEPTION) << "Scale should has 2 or 3 input tensors, current inputs is" << scale_node->inputs().size(); } - - AnfNodePtr conv_weight_node; - if (conv_node->inputs().size() == 3) { - conv_weight_node = conv_node->input(2); - } else { - MS_LOG(ERROR) << "scale inputs size is error:" << scale_node->DebugString(); - return nullptr; - } - auto conv_weight_param = conv_weight_node->cast()->default_param(); - auto weight_value = std::dynamic_pointer_cast(conv_weight_param); - auto old_conv_weight = reinterpret_cast(weight_value->tensor_addr()); - - auto new_conv_weight = new(std::nothrow) float[weight_value->tensor_shape_size()]; - CalNewWeightTensor(old_conv_weight, new_conv_weight, weight_value->tensor_shape_size()); - weight_value->set_tensor_addr(new_conv_weight); - return conv_node; -} - -const lite::STATUS ConvScaleFusion::GetTransParam(const AnfNodePtr &scale_weight_node, - const AnfNodePtr &scale_bias_node) const { if (!scale_weight_node->isa()) { MS_LOG(EXCEPTION) << "scale weight node not paramter node"; } @@ -96,31 +69,17 @@ const lite::STATUS ConvScaleFusion::GetTransParam(const AnfNodePtr &scale_weight auto weight_value = std::dynamic_pointer_cast(scale_weight_param); auto weight_data = reinterpret_cast(weight_value->tensor_addr()); - if (0 != memcpy_s(trans_scale, kernel_nums * sizeof(float), weight_data, kernel_nums * sizeof(float))) { - MS_LOG(ERROR) << "memcpy_s transScale failed"; - return lite::RET_ERROR; + if (0 != memcpy_s(trans_scale, kernel_num * sizeof(float), weight_data, kernel_num * sizeof(float))) { + MS_LOG(EXCEPTION) << "memcpy_s transScale failed"; } - return lite::RET_OK; -} -const lite::STATUS ConvScaleFusion::CalNewWeightTensor(const float *oldWeightTensor, float *newWeightTensor, - const size_t tensor_shape_size) const { - MS_ASSERT(oldWeightTensor != nullptr); - if (0 != memset_s(newWeightTensor, tensor_shape_size * sizeof(float), 0, tensor_shape_size * sizeof(float))) { - MS_LOG(ERROR) << "memset newWeightData failed"; - return lite::RET_ERROR; - } - if (kernel_nums == 0) { - MS_LOG(ERROR) << "kernel nums is 0"; - return lite::RET_ERROR; - } - auto kernel_size = tensor_shape_size / kernel_nums; - for (size_t i = 0; i < kernel_nums; i++) { - for (size_t j = 0; j < kernel_size; j++) { - newWeightTensor[i * kernel_size + j] = oldWeightTensor[i * kernel_size + j] * trans_scale[i]; + if (scale_bias_node != nullptr) { + auto scale_bias_param = scale_bias_node->cast()->default_param(); + auto bias_value = std::dynamic_pointer_cast(scale_bias_param); + auto bias_data = reinterpret_cast(bias_value->tensor_addr()); + if (0 != memcpy_s(trans_bias, kernel_num * sizeof(float), bias_data, kernel_num * sizeof(float))) { + MS_LOG(EXCEPTION) << "memcpy_s transScale failed"; } } - return lite::RET_OK; } -} // namespace opt -} // namespace mindspore +} // namespace mindspore::opt diff --git a/mindspore/lite/src/gllo/fusion/conv_scale_fusion.h b/mindspore/lite/src/gllo/fusion/conv_scale_fusion.h index 8012fc2a03a..35b5d794417 100644 --- a/mindspore/lite/src/gllo/fusion/conv_scale_fusion.h +++ b/mindspore/lite/src/gllo/fusion/conv_scale_fusion.h @@ -17,24 +17,15 @@ #ifndef MINDSPORE_LITE_SRC_PASS_FUSION_CONV_SCALE_FUSION_H_ #define MINDSPORE_LITE_SRC_PASS_FUSION_CONV_SCALE_FUSION_H_ -#include "src/gllo/common/optimizer.h" +#include "mindspore/lite/src/gllo/fusion/conv_transform_fusion.h" -namespace mindspore { -namespace opt { -class ConvScaleFusion : public PatternProcessPass { +namespace mindspore::opt { +class ConvScaleFusion : public ConvTransformFusion { public: - explicit ConvScaleFusion(bool multigraph = true) : PatternProcessPass("conv_scale_fusion", multigraph) {} + explicit ConvScaleFusion(bool multigraph = true) : ConvTransformFusion(multigraph, "conv_scale_fusion") {} ~ConvScaleFusion() override = default; const BaseRef DefinePattern() const override; - const AnfNodePtr Process(const FuncGraphPtr &, const AnfNodePtr &, const EquivPtr &) const override; - const AnfNodePtr DoFusion(const CNodePtr &, const CNodePtr &) const; - const lite::STATUS GetTransParam(const AnfNodePtr &, const AnfNodePtr &) const; - const lite::STATUS CalNewWeightTensor(const float *, float *, const size_t) const; - private: - float *trans_scale = nullptr; - int kernel_nums = 0; + const void InitTransParam(const CNodePtr &, int, float *, float *) const override; }; -} // namespace opt -} // namespace mindspore +} // namespace mindspore::opt #endif // MINDSPORE_LITE_SRC_PASS_FUSION_CONV_SCALE_FUSION_H_ - diff --git a/mindspore/lite/src/gllo/fusion/conv_transform_fusion.cc b/mindspore/lite/src/gllo/fusion/conv_transform_fusion.cc new file mode 100644 index 00000000000..ef40cf2d71a --- /dev/null +++ b/mindspore/lite/src/gllo/fusion/conv_transform_fusion.cc @@ -0,0 +1,201 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 + *conv_activation_fusion.h + * 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 "mindspore/lite/src/gllo/fusion/conv_transform_fusion.h" +#include +#include "mindspore/lite/src/param_value_lite.h" +#include "mindspore/lite/schema/inner/model_generated.h" +#include "mindspore/lite/src/ir/primitive_t_value.h" +#include "mindspore/ccsrc/utils/utils.h" +#include "mindspore/lite/src/gllo/common/utils.h" +#include "include/errorcode.h" + +namespace mindspore::opt { +namespace { +constexpr size_t kConvWeightIndex = 2; +constexpr size_t kConvBiasIndex = 3; +constexpr size_t kConvNoBiasLen = 3; +constexpr size_t kConvWithBiasLen = 4; + +int Get_Kenrnel_nums(const CNodePtr &conv_node) { + MS_ASSERT(conv_node != nullptr); + auto value_primitive = conv_node->input(0); + auto value_node = value_primitive->cast(); + MS_ASSERT(value_node != nullptr); + auto value = value_node->value(); + MS_ASSERT(value != nullptr); + auto primitive = value->cast(); + MS_ASSERT(primitive != nullptr); + auto type = primitive->GetPrimitiveT()->value.type; + if (type == schema::PrimitiveType_Conv2D) { + return primitive->GetPrimitiveT()->value.AsConv2D()->channelOut; + } else if (type == schema::PrimitiveType_DepthwiseConv2D) { + return primitive->GetPrimitiveT()->value.AsDepthwiseConv2D()->channelMultiplier + * primitive->GetPrimitiveT()->value.AsDepthwiseConv2D()->channelIn; + } else { + MS_LOG(ERROR) << "Unsupported opType, " << type; + return 0; + } +} +} // namespace + +const AnfNodePtr ConvTransformFusion::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, + const EquivPtr &) const { + MS_LOG(DEBUG) << "conv activation pass process"; + CheckIfFuncGraphIsNull(func_graph); + + CheckIfAnfNodeIsNull(node); + // transform node means scale,bn + auto transform_node = node->cast(); + CheckIfCNodeIsNull(transform_node); + CheckLeastInputSize(transform_node, 2); + + auto pre_node = transform_node->input(1); + auto conv_node = pre_node->cast(); + + int kernel_nums = Get_Kenrnel_nums(conv_node); + if (kernel_nums <= 0) { + MS_LOG(ERROR) << "Unsupported conv node, " << conv_node->DebugString(); + return node; + } + auto trans_scale = new(std::nothrow) float[kernel_nums]; + auto trans_bias = new(std::nothrow) float[kernel_nums]; + GenTransParam(transform_node, kernel_nums, trans_scale, trans_bias); + GenNewConvTensor(func_graph, conv_node, kernel_nums, trans_scale, trans_bias); + delete[] trans_bias; + delete[] trans_scale; + return pre_node; +} + +const void ConvTransformFusion::GenTransParam(const CNodePtr &transform_node, int kernel_nums, + float *trans_scale, float *trans_bias) const { + if (trans_scale == nullptr) { + MS_LOG(EXCEPTION) << "new transScale failed"; + } + if (trans_bias == nullptr) { + MS_LOG(EXCEPTION) << "new transBias failed"; + } + if (0 != memset_s(trans_scale, kernel_nums * sizeof(float), 0, kernel_nums * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset transScale failed"; + } + if (0 != memset_s(trans_bias, kernel_nums * sizeof(float), 0, kernel_nums * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset transBias failed"; + } + + InitTransParam(transform_node, kernel_nums, trans_scale, trans_bias); +} + +const void ConvTransformFusion::GenNewConvTensor(const FuncGraphPtr &func_graph, const CNodePtr &conv_node, + int kernel_num, const float *trans_scale, const float *trans_bias) +const { + MS_ASSERT(conv_node != nullptr); + AnfNodePtr conv_weight_node = nullptr; + AnfNodePtr conv_bias_node = nullptr; + if (conv_node->inputs().size() == kConvNoBiasLen) { + conv_weight_node = conv_node->input(kConvWeightIndex); + } else if (conv_node->inputs().size() == kConvWithBiasLen) { + conv_weight_node = conv_node->input(kConvWeightIndex); + conv_bias_node = conv_node->input(kConvBiasIndex); + } else { + MS_LOG(ERROR) << "conv node:" << conv_node->DebugString() << "inputs size must 3 or 4"; + return; + } + if (!conv_weight_node->isa()) { + MS_LOG(EXCEPTION) << "scale weight node not paramter node"; + } + if (conv_bias_node != nullptr && !conv_bias_node->isa()) { + MS_LOG(EXCEPTION) << "scale bias node not paramter node"; + } + + auto conv_weight_param = conv_weight_node->cast()->default_param(); + auto weight_tensor = std::dynamic_pointer_cast(conv_weight_param); + auto weight_data = reinterpret_cast(weight_tensor->tensor_addr()); + if (kernel_num <= 0) { + MS_LOG(EXCEPTION) << "kernel num less than 0"; + } + auto kernel_size = weight_tensor->tensor_shape_size() / kernel_num; + + CalNewWeightTensor(weight_data, kernel_num, kernel_size, trans_scale); + + float *bias_data = nullptr; + // conv has bias,bias_flag true + bool bias_flag = false; + if (conv_bias_node != nullptr) { + auto bias_weight_param = conv_weight_node->cast()->default_param(); + auto bias_tensor = std::dynamic_pointer_cast(bias_weight_param); + bias_data = reinterpret_cast(bias_tensor->tensor_addr()); + bias_flag = true; + } else { + bias_data = new(std::nothrow) float[kernel_num]; + } + CalNewBiasTensor(bias_data, kernel_num, bias_flag, trans_scale, trans_bias); + if (!bias_flag) { + auto bias_node = AddNewBiasNode(bias_data, func_graph, kernel_num, weight_tensor); + conv_node->add_input(bias_node); + } +} +const void ConvTransformFusion::CalNewWeightTensor(float *weight_data, int kernel_num, int kernel_size, + const float *trans_scale) const { + MS_ASSERT(weight_data != nullptr); + auto tmp_weight_data = new(std::nothrow) float[kernel_num * kernel_size]; + MS_ASSERT(new_weight_data != nullptr); + auto data_size = kernel_num * kernel_size * sizeof(float); + if (0 != memset_s(tmp_weight_data, data_size, 0, data_size)) { + MS_LOG(EXCEPTION) << "memset newWeightData failed"; + return; + } + + for (size_t i = 0; i < kernel_num; i++) { + for (size_t j = 0; j < kernel_size; j++) { + tmp_weight_data[i * kernel_size + j] = weight_data[i * kernel_size + j] * trans_scale[i]; + } + } + + auto ret = memcpy_s(weight_data, data_size, tmp_weight_data, data_size); + if (ret != EOK) { + MS_LOG(EXCEPTION) << "memcpy error: " << ret; + } + + delete[] tmp_weight_data; +} +const void ConvTransformFusion::CalNewBiasTensor(float *bias_data, int kernel_num, bool bias_flag, + const float *trans_scale, const float *trans_bias) const { + MS_ASSERT(bias_data != nullptr); + if (bias_flag) { + auto tmp_bias_data = new(std::nothrow) float[kernel_num]; + if (0 != memset_s(bias_data, kernel_num * sizeof(float), 0, kernel_num * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset bias data failed"; + } + for (size_t i = 0; i < kernel_num; i++) { + tmp_bias_data[i] = bias_data[i] * trans_scale[i] + trans_bias[i]; + } + + auto ret = memcpy_s(bias_data, kernel_num * sizeof(float), tmp_bias_data, kernel_num * sizeof(float)); + if (ret != EOK) { + MS_LOG(EXCEPTION) << "memcpy error: " << ret; + } + delete[] tmp_bias_data; + } else { + if (0 != memset_s(bias_data, kernel_num * sizeof(float), 0, kernel_num * sizeof(float))) { + MS_LOG(EXCEPTION) << "memset bias data failed"; + } + auto ret = memcpy_s(bias_data, kernel_num * sizeof(float), trans_bias, kernel_num * sizeof(float)); + if (ret != EOK) { + MS_LOG(EXCEPTION) << "memcpy error: " << ret; + } + } +} +} // namespace mindspore::opt diff --git a/mindspore/lite/src/gllo/fusion/conv_transform_fusion.h b/mindspore/lite/src/gllo/fusion/conv_transform_fusion.h new file mode 100644 index 00000000000..98bb3618a7d --- /dev/null +++ b/mindspore/lite/src/gllo/fusion/conv_transform_fusion.h @@ -0,0 +1,37 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 + *conv_activation_fusion.h + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_LITE_SRC_PASS_FUSION_CONV_TRANSFORM_FUSION_H_ +#define MINDSPORE_LITE_SRC_PASS_FUSION_CONV_TRANSFORM_FUSION_H_ + +#include +#include "mindspore/lite/src/gllo/common/optimizer.h" + +namespace mindspore::opt { +class ConvTransformFusion : public PatternProcessPass { + public: + explicit ConvTransformFusion(bool multigraph = true, const std::string &name = "conv_transform_fusion") + : PatternProcessPass(name, multigraph) {} + ~ConvTransformFusion() override = default; + const AnfNodePtr Process(const FuncGraphPtr &, const AnfNodePtr &, const EquivPtr &) const override; + const void GenTransParam(const CNodePtr &, int, float *, float *) const; + virtual const void InitTransParam(const CNodePtr &, int, float *, float *) const = 0; + const void GenNewConvTensor(const FuncGraphPtr &, const CNodePtr &, int, const float *, const float *) const; + const void CalNewWeightTensor(float *, int, int, const float *) const; + const void CalNewBiasTensor(float *, int, bool, const float *, const float *) const; +}; +} // namespace mindspore::opt +#endif // MINDSPORE_LITE_SRC_PASS_FUSION_CONV_TRANSFORM_FUSION_H_ diff --git a/mindspore/lite/test/CMakeLists.txt b/mindspore/lite/test/CMakeLists.txt index e01e4079ade..b44bc668f2a 100644 --- a/mindspore/lite/test/CMakeLists.txt +++ b/mindspore/lite/test/CMakeLists.txt @@ -199,7 +199,9 @@ if(BUILD_CONVERTER) ${LITE_DIR}/src/gllo/common/utils.cc ${LITE_DIR}/src/gllo/fusion/conv_biasadd_fusion.cc ${LITE_DIR}/src/gllo/fusion/conv_activation_fusion.cc + ${LITE_DIR}/src/gllo/fusion/conv_transform_fusion.cc ${LITE_DIR}/src/gllo/fusion/conv_scale_fusion.cc + ${LITE_DIR}/src/gllo/fusion/conv_bn_fusion.cc ) endif() ### train diff --git a/mindspore/lite/tools/converter/CMakeLists.txt b/mindspore/lite/tools/converter/CMakeLists.txt index c28483ca158..74fc5c16b46 100644 --- a/mindspore/lite/tools/converter/CMakeLists.txt +++ b/mindspore/lite/tools/converter/CMakeLists.txt @@ -79,7 +79,9 @@ file(GLOB_RECURSE CONVERTER_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/common/utils.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/fusion/conv_biasadd_fusion.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/fusion/conv_activation_fusion.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/fusion/conv_transform_fusion.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/fusion/conv_scale_fusion.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/gllo/fusion/conv_bn_fusion.cc ) add_subdirectory(parser/caffe) diff --git a/mindspore/lite/tools/converter/anf_transform.cc b/mindspore/lite/tools/converter/anf_transform.cc index 8684ddac7e8..7afab29e18e 100644 --- a/mindspore/lite/tools/converter/anf_transform.cc +++ b/mindspore/lite/tools/converter/anf_transform.cc @@ -18,8 +18,10 @@ #include #include #include "utils/log_adapter.h" -#include "src/gllo/fusion/conv_biasadd_fusion.h" - +#include "mindspore/lite/src/gllo/fusion/conv_biasadd_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_activation_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_scale_fusion.h" +#include "mindspore/lite/src/gllo/fusion/conv_bn_fusion.h" using std::string; namespace mindspore { @@ -34,8 +36,13 @@ FuncGraphPtr AnfTransform::Transform(const FuncGraphPtr &old_graph) { // return old_graph; auto optimizer = std::make_shared(); auto pm = std::make_shared(); - auto pass = std::make_shared(); - pm->AddPass(pass); + pm->AddPass(std::make_shared()); + pm->AddPass(std::make_shared()); + pm->AddPass(std::make_shared()); + pm->AddPass(std::make_shared(true, "conv_relu", schema::PrimitiveType_Activation, + schema::ActivationType_RELU)); + pm->AddPass(std::make_shared(true, "conv_relu6", schema::PrimitiveType_Activation, + schema::ActivationType_RELU6)); optimizer->AddPassManager(pm); FuncGraphPtr new_graph = optimizer->Optimize(old_graph); return new_graph;