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/resize_npu.h"
18 #include <memory>
19 #include "src/delegate/npu/npu_converter_utils.h"
20
21 namespace mindspore {
22 constexpr int RESIZE_INPUT_SIZE = 2;
23 constexpr int SHAPE_SIZE = 2;
24
IsSupport(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)25 int ResizeNPUOp::IsSupport(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
26 const std::vector<mindspore::MSTensor> &out_tensors) {
27 auto resize_prim = primitive->value_as_Resize();
28 if (resize_prim == nullptr) {
29 MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
30 return RET_ERROR;
31 }
32 resize_method_ = resize_prim->method();
33 if (resize_method_ != schema::ResizeMethod_LINEAR && resize_method_ != schema::ResizeMethod_NEAREST) {
34 MS_LOG(WARNING) << "Unsupported resize method type: " << resize_method_;
35 return RET_NOT_SUPPORT;
36 }
37
38 if (in_tensors[0].Shape()[NHWC_H] > out_tensors[0].Shape()[NHWC_H] ||
39 in_tensors[0].Shape()[NHWC_W] > out_tensors[0].Shape()[NHWC_W]) {
40 MS_LOG(WARNING) << "Npu resize does not support reduction.";
41 return RET_NOT_SUPPORT;
42 }
43 return RET_OK;
44 }
45
Init(const schema::Primitive * primitive,const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors)46 int ResizeNPUOp::Init(const schema::Primitive *primitive, const std::vector<mindspore::MSTensor> &in_tensors,
47 const std::vector<mindspore::MSTensor> &out_tensors) {
48 auto resize_prim = primitive->value_as_Resize();
49 if (resize_prim == nullptr) {
50 MS_LOG(ERROR) << "Get null primitive value for op ." << name_;
51 return RET_ERROR;
52 }
53 if (in_tensors.size() == 1) {
54 new_height_ = resize_prim->new_height();
55 new_width_ = resize_prim->new_width();
56 } else if (in_tensors.size() == RESIZE_INPUT_SIZE) {
57 auto out_size = in_tensors.at(1).Data();
58 if (out_size == nullptr) {
59 MS_LOG(ERROR) << "Out size is not assigned";
60 return RET_ERROR;
61 }
62 new_height_ = out_tensors.at(0).Shape().at(NHWC_H);
63 new_width_ = out_tensors.at(0).Shape().at(NHWC_W);
64 } else {
65 MS_LOG(ERROR) << "Get resize op new_height and new_width error.";
66 return RET_ERROR;
67 }
68
69 ge::TensorDesc sizeTensorDesc(ge::Shape({SHAPE_SIZE}), ge::FORMAT_NCHW, ge::DT_INT32);
70 ge::TensorPtr sizeTensor = std::make_shared<hiai::Tensor>(sizeTensorDesc);
71 vector<int32_t> dataValue = {static_cast<int32_t>(new_height_), static_cast<int32_t>(new_width_)};
72 sizeTensor->SetData(reinterpret_cast<uint8_t *>(dataValue.data()), SHAPE_SIZE * sizeof(int32_t));
73 out_size_ = new (std::nothrow) hiai::op::Const(name_ + "_size");
74 if (out_size_ == nullptr) {
75 MS_LOG(ERROR) << "create const NPU op failed for " << name_;
76 return RET_ERROR;
77 }
78 out_size_->set_attr_value(sizeTensor);
79
80 if (resize_method_ == schema::ResizeMethod_LINEAR) {
81 auto resize_bilinear = new (std::nothrow) hiai::op::ResizeBilinearV2(name_);
82 if (resize_bilinear == nullptr) {
83 MS_LOG(ERROR) << " resize_ is nullptr.";
84 return RET_ERROR;
85 }
86 resize_bilinear->set_attr_align_corners(resize_prim->coordinate_transform_mode() ==
87 schema::CoordinateTransformMode_ALIGN_CORNERS);
88 resize_bilinear->set_input_size(*out_size_);
89 resize_bilinear->set_attr_half_pixel_centers(resize_prim->preserve_aspect_ratio());
90 resize_ = resize_bilinear;
91 } else if (resize_method_ == schema::ResizeMethod_NEAREST) {
92 auto resize_nearest = new (std::nothrow) hiai::op::ResizeNearestNeighborV2(name_);
93 if (resize_nearest == nullptr) {
94 MS_LOG(ERROR) << " resize_ is nullptr.";
95 return RET_ERROR;
96 }
97 resize_nearest->set_attr_align_corners(resize_prim->coordinate_transform_mode() ==
98 schema::CoordinateTransformMode_ALIGN_CORNERS);
99 resize_nearest->set_input_size(*out_size_);
100 resize_ = resize_nearest;
101 } else {
102 MS_LOG(WARNING) << "Unsupported resize method type:" << resize_method_;
103 return RET_ERROR;
104 }
105 return RET_OK;
106 }
107
SetNPUInputs(const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors,const std::vector<ge::Operator * > & npu_inputs)108 int ResizeNPUOp::SetNPUInputs(const std::vector<mindspore::MSTensor> &in_tensors,
109 const std::vector<mindspore::MSTensor> &out_tensors,
110 const std::vector<ge::Operator *> &npu_inputs) {
111 if (resize_method_ == schema::ResizeMethod_LINEAR) {
112 auto resize_bilinear = reinterpret_cast<hiai::op::ResizeBilinearV2 *>(resize_);
113 resize_bilinear->set_input_x(*npu_inputs[0]);
114 } else if (resize_method_ == schema::ResizeMethod_NEAREST) {
115 auto resize_nearest = reinterpret_cast<hiai::op::ResizeNearestNeighborV2 *>(resize_);
116 resize_nearest->set_input_x(*npu_inputs[0]);
117 } else {
118 MS_LOG(WARNING) << "Unsupported resize method type:" << resize_method_;
119 return RET_ERROR;
120 }
121 return RET_OK;
122 }
123
GetNPUOp()124 ge::Operator *ResizeNPUOp::GetNPUOp() { return this->resize_; }
125
~ResizeNPUOp()126 ResizeNPUOp::~ResizeNPUOp() {
127 if (resize_ != nullptr) {
128 delete resize_;
129 resize_ = nullptr;
130 }
131 if (out_size_ != nullptr) {
132 delete out_size_;
133 out_size_ = nullptr;
134 }
135 }
136 } // namespace mindspore
137