1 /**
2 * Copyright 2022 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 #include <include/errorcode.h>
17 #include "nnrt_model_kernel.h"
18 #include "nnrt_allocator.h"
19 #include "litert/cxx_api/tensor/tensor_impl.h"
20
21 namespace mindspore{
22 namespace {
23 constexpr auto kDynamicDims = "DynamicDims";
24 }
25
Prepare()26 int NNRTModelKernel::Prepare() {
27 auto nnrt_allocator = lite::NNRTAllocator::GetInstance();
28 if (nnrt_allocator == nullptr) {
29 MS_LOG(ERROR) << "Get NNRTAllocator failed";
30 return lite::RET_NULL_PTR;
31 }
32 nnrt_allocator->SetDeviceId(nnrt_device_info_.device_id_);
33 for (size_t i = 0; i < inputs_.size(); i++) {
34 inputs_[i].SetAllocator(nnrt_allocator);
35 }
36 for (size_t i = 0; i < outputs_.size(); i++) {
37 outputs_[i].SetAllocator(nnrt_allocator);
38 }
39 return lite::RET_OK;
40 }
41
ReSize()42 int NNRTModelKernel::ReSize() {
43 const auto &extensions = nnrt_device_info_.extensions_;
44 auto iter = std::find_if(extensions.begin(), extensions.end(), [](const lite::Extension &extension) {
45 return extension.name == kDynamicDims;
46 });
47 if (iter != extensions.end() && !iter->value.empty()) {
48 return lite::RET_OK;
49 }
50 MS_LOG(ERROR) << "NNRT only support the resize function when DynamicDims is enabled.";
51 return lite::RET_ERROR;
52 }
53
Execute()54 int NNRTModelKernel::Execute() {
55 MS_CHECK_TRUE_RET(this->outputs().empty() != true, lite::RET_ERROR);
56 zero_copy_ = IS_NNRT_ALLOCATOR(this->outputs()[Index0].allocator());
57
58 if (!zero_copy_) {
59 FreeNNTensor();
60 }
61 nn_input_tensors_.clear();
62 nn_output_tensors_.clear();
63 nn_input_tensor_descs_.clear();
64 nn_output_tensor_descs_.clear();
65
66 lite::STATUS ret_val = SetInputs();
67 if (ret_val != lite::RET_OK) {
68 MS_LOG(ERROR) << "NNRTModelKernel SetInputs failed, STATUS is " << ret_val;
69 return ret_val;
70 }
71 ret_val = SetOutputs();
72 if (ret_val != lite::RET_OK) {
73 MS_LOG(ERROR) << "NNRTModelKernel SetOutputs failed, STATUS is " << ret_val;
74 return ret_val;
75 }
76 MS_LOG(INFO) << "Running NNRtModel Kernel...";
77 OH_NN_ReturnCode ret_code;
78 ret_code = OH_NNExecutor_RunSync(oh_nn_executor_, nn_input_tensors_.data(), nn_input_tensors_.size(),
79 nn_output_tensors_.data(), nn_output_tensors_.size());
80
81 if (ret_code != OH_NN_SUCCESS) {
82 MS_LOG(ERROR) << "OH_NNExecutor_RunSync Run failed, OH_NN_ReturnCode = " << ret_code;
83 return lite::RET_ERROR;
84 }
85 MS_LOG(INFO) << "Run NNRtModel Kernel success.";
86
87 return lite::RET_OK;
88 }
89
SetInputs()90 int NNRTModelKernel::SetInputs() {
91 if (!zero_copy_) {
92 OH_NN_ReturnCode ret{OH_NN_FAILED};
93 size_t nn_input_count = 0;
94 ret = OH_NNExecutor_GetInputCount(oh_nn_executor_, &nn_input_count);
95 if (ret != OH_NN_SUCCESS) {
96 MS_LOG(ERROR) << "OH_NNExecutor_GetInputCount failed.";
97 return lite::RET_ERROR;
98 }
99 if (nn_input_count != inputs_.size()) {
100 MS_LOG(ERROR) << "input count is not equal between ms and nnrt.";
101 return lite::RET_ERROR;
102 }
103 for (size_t i = 0; i < nn_input_count; i++) {
104 NN_TensorDesc *tensor_desc_tmp = OH_NNExecutor_CreateInputTensorDesc(oh_nn_executor_, i);
105 if (tensor_desc_tmp == nullptr) {
106 MS_LOG(ERROR) << "OH_NNExecutor_CreateInputTensorDesc failed, i = " << i;
107 return lite::RET_ERROR;
108 }
109 nn_input_tensor_descs_.emplace_back(tensor_desc_tmp);
110 NN_Tensor *tensor_tmp = OH_NNTensor_Create(nnrt_device_info_.device_id_, tensor_desc_tmp);
111 if (tensor_tmp == nullptr) {
112 MS_LOG(ERROR) << "OH_NNTensor_Create input failed, i = " << i;
113 return lite::RET_ERROR;
114 }
115 nn_input_tensors_.emplace_back(tensor_tmp);
116 void *nn_data = OH_NNTensor_GetDataBuffer(nn_input_tensors_[i]);
117 size_t tensor_size;
118 ret = OH_NNTensorDesc_GetByteSize(tensor_desc_tmp, &tensor_size);
119 if (ret != OH_NN_SUCCESS || tensor_size != inputs_[i].DataSize()) {
120 MS_LOG(ERROR) << "NN_Tensor size is not equal to MSTensor, i = " << i;
121 return lite::RET_ERROR;
122 }
123 memcpy(nn_data, inputs_[i].MutableData(), inputs_[i].DataSize());
124 }
125 } else {
126 for (size_t i = 0; i < inputs_.size(); i++) {
127 if (inputs_[i].allocator() == nullptr) {
128 MS_LOG(ERROR) << "NNRTAllocator is nullptr, i = " << i;
129 return lite::RET_ERROR;
130 }
131 void *data = inputs_[i].MutableData();
132 NN_Tensor *tensor_tmp = reinterpret_cast<lite::NNRTAllocator *>(inputs_[i].allocator().get())->GetNNTensor(data);
133 if (tensor_tmp == nullptr) {
134 MS_LOG(ERROR) << "NNRTAllocator GetNNTensor failed, i = " << i;
135 return lite::RET_ERROR;
136 }
137 nn_input_tensors_.emplace_back(tensor_tmp);
138 }
139 }
140 return lite::RET_OK;
141 }
142
SetOutputs()143 int NNRTModelKernel::SetOutputs() {
144 if (!zero_copy_) {
145 OH_NN_ReturnCode ret{OH_NN_FAILED};
146 size_t nn_output_count = 0;
147 ret = OH_NNExecutor_GetOutputCount(oh_nn_executor_, &nn_output_count);
148 if (ret != OH_NN_SUCCESS) {
149 MS_LOG(ERROR) << "OH_NNExecutor_GetOutputCount failed.";
150 return lite::RET_ERROR;
151 }
152 if (nn_output_count != outputs_.size()) {
153 MS_LOG(ERROR) << "output count is not equal between ms and nnrt.";
154 return lite::RET_ERROR;
155 }
156 for (size_t i = 0; i < nn_output_count; i++) {
157 NN_TensorDesc *tensor_desc_tmp = OH_NNExecutor_CreateOutputTensorDesc(oh_nn_executor_, i);
158 if (tensor_desc_tmp == nullptr) {
159 MS_LOG(ERROR) << "OH_NNExecutor_CreateOutputTensorDesc failed, i = " << i;
160 return lite::RET_ERROR;
161 }
162 nn_output_tensor_descs_.emplace_back(tensor_desc_tmp);
163 NN_Tensor *tensor_tmp = OH_NNTensor_Create(nnrt_device_info_.device_id_, tensor_desc_tmp);
164 if (tensor_tmp == nullptr) {
165 MS_LOG(ERROR) << "OH_NNTensor_Create output failed, i = " << i;
166 return lite::RET_ERROR;
167 }
168 nn_output_tensors_.emplace_back(tensor_tmp);
169 auto data = OH_NNTensor_GetDataBuffer(nn_output_tensors_[i]);
170 reinterpret_cast<LiteTensorImpl *>(outputs_[i].impl().get())->lite_tensor()->FreeData();
171 outputs_[i].SetData(data, false);
172 }
173 } else {
174 for (size_t i = 0; i < outputs_.size(); i++) {
175 if (outputs_[i].allocator() == nullptr) {
176 MS_LOG(ERROR) << "NNRTAllocator is nullptr, i = " << i;
177 return lite::RET_ERROR;
178 }
179 void *data = outputs_[i].MutableData();
180 NN_Tensor *tensor_tmp = reinterpret_cast<lite::NNRTAllocator *>(outputs_[i].allocator().get())->GetNNTensor(data);
181 if (tensor_tmp == nullptr) {
182 MS_LOG(ERROR) << "NNRTAllocator GetNNTensor failed, i = " << i;
183 return lite::RET_ERROR;
184 }
185 nn_output_tensors_.emplace_back(tensor_tmp);
186 }
187 }
188 return lite::RET_OK;
189 }
190
FreeNNTensor()191 void NNRTModelKernel::FreeNNTensor() {
192 for (size_t i = 0; i < nn_input_tensors_.size(); i++) {
193 OH_NNTensor_Destroy(&nn_input_tensors_[i]);
194 OH_NNTensorDesc_Destroy(&nn_input_tensor_descs_[i]);
195 }
196 for (size_t i = 0; i < nn_output_tensors_.size(); i++) {
197 OH_NNTensor_Destroy(&nn_output_tensors_[i]);
198 OH_NNTensorDesc_Destroy(&nn_output_tensor_descs_[i]);
199 }
200 }
201
202 } // namespace mindspore
203