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/resize_npu.h"
18 #include <memory>
19 #include "src/litert/delegate/npu/npu_converter_utils.h"
20 #include "src/litert/delegate/npu/npu_manager.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 ResizeNPUOp::IsSupport(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
24 const std::vector<mindspore::MSTensor> &out_tensors) {
25 auto resize_prim = primitive->value_as_Resize();
26 if (resize_prim == nullptr) {
27 MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
28 return RET_ERROR;
29 }
30 resize_method_ = resize_prim->method();
31 if (resize_method_ != schema::ResizeMethod_LINEAR && resize_method_ != schema::ResizeMethod_NEAREST) {
32 MS_LOG(WARNING) << "Unsupported resize method type: " << resize_method_;
33 return RET_NOT_SUPPORT;
34 }
35 CHECK_LESS_RETURN(in_tensors.size(), 1);
36 CHECK_LESS_RETURN(out_tensors.size(), 1);
37 if (in_tensors[0].Shape()[NHWC_H] > out_tensors[0].Shape()[NHWC_H] ||
38 in_tensors[0].Shape()[NHWC_W] > out_tensors[0].Shape()[NHWC_W]) {
39 MS_LOG(WARNING) << "Npu resize does not support reduction.";
40 return RET_NOT_SUPPORT;
41 }
42 is_support_v2_ = NPUManager::CheckDDKVerGreatEqual("100.500.010.010");
43 is_support_scale_ = NPUManager::CheckDDKVerGreatEqual("100.320.012.043");
44 return RET_OK;
45 }
46
Init(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)47 int ResizeNPUOp::Init(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
48 const std::vector<mindspore::MSTensor> &out_tensors) {
49 CHECK_LESS_RETURN(in_tensors.at(0).Shape().size(), DIMENSION_4D);
50 auto org_height = static_cast<float>(in_tensors.at(0).Shape().at(NHWC_H));
51 auto org_width = static_cast<float>(in_tensors.at(0).Shape().at(NHWC_W));
52 CHECK_LESS_RETURN(out_tensors.at(0).Shape().size(), DIMENSION_4D);
53 auto new_height = static_cast<int>(out_tensors.at(0).Shape().at(NHWC_H));
54 auto new_width = static_cast<int>(out_tensors.at(0).Shape().at(NHWC_W));
55
56 ge::TensorPtr size_tensor = std::make_shared<hiai::Tensor>();
57 if (is_support_scale_) {
58 ge::TensorDesc size_tensor_desc(ge::Shape({NPU_SHAPE_SIZE}), ge::FORMAT_ND, ge::DT_FLOAT);
59 size_tensor->SetTensorDesc(size_tensor_desc);
60 std::vector<float> data_value = {1, 1, new_height / org_height, new_width / org_width};
61 size_tensor->SetData(reinterpret_cast<uint8_t *>(data_value.data()), NPU_SHAPE_SIZE * sizeof(float));
62 } else {
63 ge::TensorDesc size_tensor_desc(ge::Shape({DIMENSION_2D}), ge::FORMAT_ND, ge::DT_INT32);
64 size_tensor->SetTensorDesc(size_tensor_desc);
65 std::vector<int> data_value = {new_height, new_width};
66 size_tensor->SetData(reinterpret_cast<uint8_t *>(data_value.data()), DIMENSION_2D * sizeof(int));
67 }
68 out_size_ = new (std::nothrow) hiai::op::Const(name_ + "_size");
69 if (out_size_ == nullptr) {
70 MS_LOG(ERROR) << "create const NPU op failed for " << name_;
71 return RET_ERROR;
72 }
73 out_size_->set_attr_value(size_tensor);
74
75 auto resize_prim = primitive->value_as_Resize();
76 if (resize_prim == nullptr) {
77 MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
78 return RET_ERROR;
79 }
80 auto ret = SelectResizeOp(resize_prim);
81 if (ret != RET_OK) {
82 MS_LOG(ERROR) << "Select Resize op failed!";
83 return RET_ERROR;
84 }
85 return RET_OK;
86 }
87
SelectResizeOp(const mindspore::schema::Resize * prim)88 int ResizeNPUOp::SelectResizeOp(const mindspore::schema::Resize *prim) {
89 if (resize_method_ == schema::ResizeMethod_LINEAR) {
90 auto resize_bilinear = new (std::nothrow) hiai::op::ResizeBilinearV2(name_);
91 if (resize_bilinear == nullptr) {
92 MS_LOG(ERROR) << " resize_ is nullptr.";
93 return RET_ERROR;
94 }
95 resize_bilinear->set_attr_align_corners(prim->coordinate_transform_mode() ==
96 schema::CoordinateTransformMode_ALIGN_CORNERS);
97 resize_bilinear->set_attr_half_pixel_centers(prim->coordinate_transform_mode() ==
98 schema::CoordinateTransformMode_HALF_PIXEL);
99 resize_bilinear->set_input_size(*out_size_);
100 resize_ = resize_bilinear;
101 } else if (resize_method_ == schema::ResizeMethod_NEAREST) {
102 if (is_support_v2_) {
103 auto resize_nearest_v2 = new (std::nothrow) hiai::op::ResizeNearestNeighborV2(name_);
104 if (resize_nearest_v2 == nullptr) {
105 MS_LOG(ERROR) << " resize_ is nullptr.";
106 return RET_ERROR;
107 }
108 resize_nearest_v2->set_attr_align_corners(prim->coordinate_transform_mode() ==
109 schema::CoordinateTransformMode_ALIGN_CORNERS);
110 resize_nearest_v2->set_input_size(*out_size_);
111 resize_ = resize_nearest_v2;
112 } else {
113 auto resize_nearest = new (std::nothrow) hiai::op::ResizeNearestNeighbor(name_);
114 if (resize_nearest == nullptr) {
115 MS_LOG(ERROR) << " resize_ is nullptr.";
116 return RET_ERROR;
117 }
118 resize_nearest->set_input_size(*out_size_);
119 resize_ = resize_nearest;
120 }
121 } else {
122 MS_LOG(WARNING) << "Unsupported resize method type:" << resize_method_;
123 return RET_ERROR;
124 }
125 return RET_OK;
126 }
127
SetNPUInputs(const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors,const std::vector<ge::Operator * > & npu_inputs)128 int ResizeNPUOp::SetNPUInputs(const std::vector<mindspore::MSTensor> &in_tensors,
129 const std::vector<mindspore::MSTensor> &out_tensors,
130 const std::vector<ge::Operator *> &npu_inputs) {
131 CHECK_LESS_RETURN(npu_inputs.size(), 1);
132 if (resize_method_ == schema::ResizeMethod_LINEAR) {
133 auto resize_bilinear = reinterpret_cast<hiai::op::ResizeBilinearV2 *>(resize_);
134 resize_bilinear->set_input_x(*npu_inputs[0]);
135 } else if (resize_method_ == schema::ResizeMethod_NEAREST) {
136 if (is_support_v2_) {
137 auto resize_nearest_v2 = reinterpret_cast<hiai::op::ResizeNearestNeighborV2 *>(resize_);
138 resize_nearest_v2->set_input_x(*npu_inputs[0]);
139 } else {
140 auto resize_nearest = reinterpret_cast<hiai::op::ResizeNearestNeighbor *>(resize_);
141 resize_nearest->set_input_x(*npu_inputs[0]);
142 }
143 } else {
144 MS_LOG(WARNING) << "Unsupported resize method type:" << resize_method_;
145 return RET_ERROR;
146 }
147 return RET_OK;
148 }
149
GetNPUOp()150 ge::Operator *ResizeNPUOp::GetNPUOp() { return this->resize_; }
151
~ResizeNPUOp()152 ResizeNPUOp::~ResizeNPUOp() {
153 if (resize_ != nullptr) {
154 delete resize_;
155 resize_ = nullptr;
156 }
157 if (out_size_ != nullptr) {
158 delete out_size_;
159 out_size_ = nullptr;
160 }
161 }
162 } // namespace mindspore::lite
163