• 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/delegate/npu/op/scale_npu.h"
18 #include <memory>
19 #include "src/delegate/npu/npu_converter_utils.h"
20 
21 namespace mindspore {
22 constexpr int INPUT_INDEX = 0;
23 constexpr int SCALE_INDEX = 1;
24 constexpr int BIAS_INDEX = 2;
25 
IsSupport(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)26 int ScaleNPUOp::IsSupport(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
27                           const std::vector<mindspore::MSTensor> &out_tensors) {
28   auto scale_prim = primitive->value_as_ScaleFusion();
29   if (scale_prim == nullptr) {
30     MS_LOG(ERROR) << "Get null primitive value for op: " << name_;
31     return RET_ERROR;
32   }
33   axis_ = scale_prim->axis();
34   if (axis_ < 0) {
35     axis_ = axis_ + in_tensors[INPUT_INDEX].Shape().size();
36   }
37   if (axis_ != NHWC_C && axis_ != NCHW_C) {
38     if (in_tensors.size() <= BIAS_INDEX) {
39       MS_LOG(INFO) << "Npu Scale op does not support axis: " << axis_ << ", try to convert to Mul op.";
40       use_mul_ = true;
41     } else {
42       MS_LOG(WARNING) << "Npu Scale axis attr only support 1 or channel, now is " << axis_;
43       return RET_NOT_SUPPORT;
44     }
45   }
46   return RET_OK;
47 }
48 
Init(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)49 int ScaleNPUOp::Init(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
50                      const std::vector<mindspore::MSTensor> &out_tensors) {
51   if (!use_mul_) {
52     // note that Scale only support the default axis(i.e., 1), setting axis is meaningless.
53     op_ = new (std::nothrow) hiai::op::Scale(name_);
54   } else {
55     op_ = new (std::nothrow) hiai::op::Mul(name_);
56   }
57   if (op_ == nullptr) {
58     MS_LOG(ERROR) << name_ << " op is nullptr";
59     return RET_ERROR;
60   }
61 
62   auto scale_prim = primitive->value_as_ScaleFusion();
63   if (scale_prim == nullptr) {
64     MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
65     return RET_ERROR;
66   }
67   act_type_ = scale_prim->activation_type();
68   if (act_type_ != schema::ActivationType_NO_ACTIVATION) {
69     auto ret = SetActivation(op_);
70     if (ret != RET_OK) {
71       MS_LOG(ERROR) << "New activation npu operator for op " << name_ << " failed.";
72       return ret;
73     }
74   }
75   return RET_OK;
76 }
77 
SetNPUInputs(const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors,const std::vector<ge::Operator * > & npu_inputs)78 int ScaleNPUOp::SetNPUInputs(const std::vector<mindspore::MSTensor> &in_tensors,
79                              const std::vector<mindspore::MSTensor> &out_tensors,
80                              const std::vector<ge::Operator *> &npu_inputs) {
81   MS_ASSERT(in_tensors.size() > SCALE_INDEX);
82   if (use_mul_) {
83     auto ret = ConvertScaleToMul(npu_inputs, op_, in_tensors);
84     if (ret != RET_OK) {
85       MS_LOG(ERROR) << "Convert Scale to Mul failed, op name: " << name_;
86     }
87     return ret;
88   }
89 
90   auto scale_op = reinterpret_cast<hiai::op::Scale *>(op_);
91   scale_op->set_input_x(*npu_inputs.at(INPUT_INDEX));
92   scale_op->set_input_scale(*npu_inputs.at(SCALE_INDEX));
93   if (in_tensors.size() > BIAS_INDEX && in_tensors[BIAS_INDEX] != nullptr) {
94     scale_op->set_input_bias(*npu_inputs.at(BIAS_INDEX));
95   }
96   return RET_OK;
97 }
98 
GetNPUOp()99 ge::Operator *ScaleNPUOp::GetNPUOp() {
100   if (act_type_ == schema::ActivationType_NO_ACTIVATION) {
101     return op_;
102   } else {
103     return act_;
104   }
105 }
106 
SetActivation(const ge::Operator * input)107 int ScaleNPUOp::SetActivation(const ge::Operator *input) {
108   act_ = new (std::nothrow) hiai::op::Activation(name_ + "_act");
109   if (act_ == nullptr) {
110     MS_LOG(ERROR) << "New activation npu operator for op " << name_ << " failed.";
111     return RET_ERROR;
112   }
113   act_->set_input_x(*input);
114 
115   auto act_mode = ConverterToNPUActivationMode(act_type_);
116   if (act_mode == ACTIVATION_INVALID) {
117     MS_LOG(ERROR) << "Unsupported activation type for scale op " << name_;
118     return RET_ERROR;
119   }
120   act_->set_attr_mode(act_mode);
121   return RET_OK;
122 }
123 
ConvertScaleToMul(const std::vector<ge::Operator * > & npu_inputs,ge::Operator * cur_op,const std::vector<mindspore::MSTensor> & in_tensors)124 int ScaleNPUOp::ConvertScaleToMul(const std::vector<ge::Operator *> &npu_inputs, ge::Operator *cur_op,
125                                   const std::vector<mindspore::MSTensor> &in_tensors) {
126   auto input_shape = in_tensors[INPUT_INDEX].Shape();
127   auto scale_shape = in_tensors[SCALE_INDEX].Shape();
128   auto mul_op = reinterpret_cast<hiai::op::Mul *>(cur_op);
129   mul_op->set_input_x1(*npu_inputs.at(INPUT_INDEX));
130   if (input_shape.size() == scale_shape.size()) {
131     mul_op->set_input_x2(*npu_inputs.at(SCALE_INDEX));
132   } else {
133     int valid_shape[4] = {1, 1, 1, 1};
134     for (size_t i = 0; i < scale_shape.size(); i++) {
135       valid_shape[axis_ + i] = static_cast<int>(scale_shape[i]);
136     }
137     reshape_ = new (std::nothrow) hiai::op::Reshape(name_ + "_reshape");
138     if (reshape_ == nullptr) {
139       MS_LOG(ERROR) << "New Reshape npu operator for op " << name_ << " failed.";
140       return RET_ERROR;
141     }
142     std::shared_ptr<ge::Tensor> shape_tensor = std::make_shared<ge::Tensor>();
143     if (shape_tensor == nullptr) {
144       MS_LOG(ERROR) << "new shape_tensor failed.";
145       return RET_ERROR;
146     }
147     ge::TensorDesc tensor_desc(ge::Shape({NPU_SHAPE_SIZE}), ge::FORMAT_ND, ge::DT_INT32);
148     shape_tensor->SetTensorDesc(tensor_desc);
149     shape_tensor->SetData(reinterpret_cast<const uint8_t *>(valid_shape), NPU_SHAPE_SIZE * sizeof(int));
150     shape_ = new (std::nothrow) hiai::op::Const(name_ + "_reshape_1");
151     if (shape_ == nullptr) {
152       MS_LOG(ERROR) << "New shape const for op " << name_ << " failed.";
153       return RET_ERROR;
154     }
155     shape_->set_attr_value(shape_tensor);
156     reshape_->set_input_x(*npu_inputs.at(SCALE_INDEX));
157     reshape_->set_input_shape(*shape_);
158     mul_op->set_input_x2(*reshape_);
159   }
160   return RET_OK;
161 }
162 
~ScaleNPUOp()163 ScaleNPUOp::~ScaleNPUOp() {
164   if (op_ != nullptr) {
165     delete op_;
166     op_ = nullptr;
167   }
168   if (scale_ != nullptr) {
169     delete scale_;
170     scale_ = nullptr;
171   }
172   if (bias_ != nullptr) {
173     delete bias_;
174     bias_ = nullptr;
175   }
176   if (act_ != nullptr) {
177     delete act_;
178     act_ = nullptr;
179   }
180   if (reshape_ != nullptr) {
181     delete reshape_;
182     reshape_ = nullptr;
183   }
184   if (shape_ != nullptr) {
185     delete shape_;
186     shape_ = nullptr;
187   }
188 }
189 }  // namespace mindspore
190