• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2020-2021 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/litert/delegate/npu/op/deconvolution_npu.h"
18 #include "src/litert/delegate/npu/npu_converter_utils.h"
19 #include "nnacl/op_base.h"
20 #include "src/common/log_util.h"
21 
22 namespace mindspore::lite {
IsSupport(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)23 int DeconvolutionNPUOp::IsSupport(const schema::Primitive *primitive,
24                                   const std::vector<mindspore::MSTensor> &in_tensors,
25                                   const std::vector<mindspore::MSTensor> &out_tensors) {
26   if (!in_tensors[1].IsConst()) {
27     MS_LOG(WARNING) << "NPU convolution does not support dynamic weight.";
28     return RET_NOT_SUPPORT;
29   }
30   auto deconv_prim = primitive->value_as_Conv2dTransposeFusion();
31   if (deconv_prim == nullptr) {
32     MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
33     return RET_ERROR;
34   }
35   if (static_cast<int>(deconv_prim->group()) != 1) {
36     MS_LOG(WARNING) << "Only support group equals 1 for npu deconvolution op";
37     return RET_NOT_SUPPORT;
38   }
39   return RET_OK;
40 }
41 
SetDeconvParam(const schema::Conv2dTransposeFusion * conv_prim)42 int DeconvolutionNPUOp::SetDeconvParam(const schema::Conv2dTransposeFusion *conv_prim) {
43   CHECK_NULL_RETURN(conv_prim);
44   CHECK_NULL_RETURN(deconv_);
45 
46   auto group = static_cast<int>(conv_prim->group());
47   CHECK_NULL_RETURN(conv_prim->stride());
48   CHECK_LESS_RETURN(conv_prim->stride()->size(), DIMENSION_2D);
49   auto stride_h = static_cast<int>(*(conv_prim->stride()->begin()));
50   auto stride_w = static_cast<int>(*(conv_prim->stride()->begin() + 1));
51   CHECK_NULL_RETURN(conv_prim->dilation());
52   CHECK_LESS_RETURN(conv_prim->dilation()->size(), DIMENSION_2D);
53   auto dilation_h = static_cast<int>(*(conv_prim->dilation()->begin()));
54   auto dilation_w = static_cast<int>(*(conv_prim->dilation()->begin() + 1));
55   deconv_->set_attr_strides(ge::AttrValue::LIST_INT({stride_h, stride_w}));
56   deconv_->set_attr_dilations(ge::AttrValue::LIST_INT({dilation_h, dilation_w}));
57   deconv_->set_attr_groups(group);
58 
59   if (conv_prim->pad_mode() == schema::PadMode_SAME) {
60     deconv_->set_attr_pad_mode(ge::AttrValue::STR{"SAME"});
61     deconv_->set_attr_pads(ge::AttrValue::LIST_INT({0, 0, 0, 0}));
62   } else if (conv_prim->pad_mode() == schema::PadMode_VALID) {
63     deconv_->set_attr_pad_mode(ge::AttrValue::STR{"VALID"});
64     deconv_->set_attr_pads(ge::AttrValue::LIST_INT({0, 0, 0, 0}));
65   } else {
66     deconv_->set_attr_pad_mode(ge::AttrValue::STR{"SPECIFIC"});
67     CHECK_NULL_RETURN(conv_prim->pad_list());
68     CHECK_LESS_RETURN(conv_prim->pad_list()->size(), DIMENSION_4D);
69     auto pad_u = static_cast<int>(*(conv_prim->pad_list()->begin() + PAD_UP));
70     auto pad_d = static_cast<int>(*(conv_prim->pad_list()->begin() + PAD_DOWN));
71     auto pad_l = static_cast<int>(*(conv_prim->pad_list()->begin() + PAD_LEFT));
72     auto pad_r = static_cast<int>(*(conv_prim->pad_list()->begin() + PAD_RIGHT));
73     deconv_->set_attr_pads(ge::AttrValue::LIST_INT({pad_u, pad_d, pad_l, pad_r}));
74   }
75   return RET_OK;
76 }
77 
Init(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)78 int DeconvolutionNPUOp::Init(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
79                              const std::vector<mindspore::MSTensor> &out_tensors) {
80   CHECK_NULL_RETURN(primitive);
81 
82   // set deconv attr param
83   deconv_ = new (std::nothrow) hiai::op::ConvTranspose(name_ + "_deconv");
84   if (deconv_ == nullptr) {
85     MS_LOG(ERROR) << "New deconvolution operator for deconvolution op " << name_ << " failed.";
86     return RET_ERROR;
87   }
88 
89   auto deconv_prim = primitive->value_as_Conv2dTransposeFusion();
90   if (deconv_prim == nullptr) {
91     MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
92     return RET_ERROR;
93   }
94   auto ret = SetDeconvParam(deconv_prim);
95   if (ret != RET_OK) {
96     MS_LOG(ERROR) << "Set npu op parameter for convolution op " << name_ << " failed.";
97     return RET_ERROR;
98   }
99   act_type_ = deconv_prim->activation_type();
100   if (act_type_ != schema::ActivationType_NO_ACTIVATION) {
101     ret = SetActivation(deconv_, act_type_);
102     if (ret != RET_OK) {
103       MS_LOG(ERROR) << "New activation npu operator for op " << name_ << " failed.";
104       return RET_ERROR;
105     }
106   }
107   // The shape should be specified not after op Init method since the tensor shape and format may be changed after pass.
108   auto output_shape = out_tensors.at(0).Shape();
109   auto output_batch = static_cast<int32_t>(output_shape.at(NHWC_N));
110   auto output_channel = static_cast<int32_t>(output_shape.at(NHWC_C));
111   auto output_height = static_cast<int32_t>(output_shape.at(NHWC_H));
112   auto output_width = static_cast<int32_t>(output_shape.at(NHWC_W));
113   out_shape_value_ = {output_batch, output_channel, output_height, output_width};
114   return RET_OK;
115 }
116 
SetNPUInputs(const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors,const std::vector<ge::Operator * > & npu_inputs)117 int DeconvolutionNPUOp::SetNPUInputs(const std::vector<mindspore::MSTensor> &in_tensors,
118                                      const std::vector<mindspore::MSTensor> &out_tensors,
119                                      const std::vector<ge::Operator *> &npu_inputs) {
120   CHECK_NULL_RETURN(deconv_);
121 
122   auto ret = InitWeightConst(in_tensors);
123   if (ret != RET_OK) {
124     MS_LOG(ERROR) << "Set weight and bias for deconvolution op " << name_ << " failed when running npu";
125     return RET_ERROR;
126   }
127   CHECK_NULL_RETURN(weight_);
128   deconv_->set_input_filter(*weight_);
129 
130   ge::TensorDesc out_shape_desc(ge::Shape({NPU_SHAPE_SIZE}), ge::FORMAT_NCHW, ge::DT_INT32);
131   ge::TensorPtr out_shape_tensor = std::make_shared<hiai::Tensor>(out_shape_desc);
132   out_shape_tensor->SetData(reinterpret_cast<uint8_t *>(out_shape_value_.data()), NPU_SHAPE_SIZE * sizeof(int32_t));
133   out_shape_ = new (std::nothrow) hiai::op::Const(name_ + "_output_shape");
134   if (out_shape_ == nullptr) {
135     MS_LOG(ERROR) << "create const NPU op failed for " << name_ + "_output_shape";
136     return RET_ERROR;
137   }
138   out_shape_->set_attr_value(out_shape_tensor);
139   deconv_->set_input_output_shape(*out_shape_);
140 
141   if (in_tensors.size() == CONV_INPUT_SIZE) {
142     ret = InitBiasConst(in_tensors);
143     if (ret != RET_OK) {
144       MS_LOG(ERROR) << "Set bias for deconvolution op " << name_ << " failed when running npu";
145       return RET_ERROR;
146     }
147     CHECK_NULL_RETURN(bias_);
148     deconv_->set_input_bias(*bias_);
149   }
150   CHECK_LESS_RETURN(npu_inputs.size(), 1);
151   deconv_->set_input_x(*npu_inputs[0]);
152   return RET_OK;
153 }
154 
GetNPUOp()155 ge::Operator *DeconvolutionNPUOp::GetNPUOp() {
156   if (act_type_ == schema::ActivationType_NO_ACTIVATION) {
157     return deconv_;
158   } else {
159     return act_;
160   }
161 }
162 
~DeconvolutionNPUOp()163 DeconvolutionNPUOp::~DeconvolutionNPUOp() {
164   if (deconv_ != nullptr) {
165     delete deconv_;
166     deconv_ = nullptr;
167   }
168   if (out_shape_ != nullptr) {
169     delete out_shape_;
170     out_shape_ = nullptr;
171   }
172 }
173 }  // namespace mindspore::lite
174