1be168c0dSopenharmony_ciFrom 03c31305a6a6c8a4b39d5fb734e312a747828672 Mon Sep 17 00:00:00 2001
2be168c0dSopenharmony_ciFrom: chengfeng27 <chengfeng27@huawei.com>
3be168c0dSopenharmony_ciDate: Sat, 1 Jun 2024 17:46:33 +0800
4be168c0dSopenharmony_ciSubject: fix output DataSize 0, heap-buffer-overflow
5be168c0dSopenharmony_ci
6be168c0dSopenharmony_ci---
7be168c0dSopenharmony_ci include/c_api/tensor_c.h                      |  15 ++
8be168c0dSopenharmony_ci mindspore/lite/BUILD.gn                       |   1 +
9be168c0dSopenharmony_ci mindspore/lite/src/litert/c_api/model_c.cc    |  40 ++++-
10be168c0dSopenharmony_ci mindspore/lite/src/litert/c_api/tensor_c.cc   |  32 ++++
11be168c0dSopenharmony_ci .../lite/src/litert/c_api/type_c_private.h    |   3 +
12be168c0dSopenharmony_ci .../src/litert/cxx_api/model/model_impl.cc    |  77 +++++++-
13be168c0dSopenharmony_ci .../litert/delegate/nnrt/nnrt_allocator.cc    | 168 ++++++++++++++++++
14be168c0dSopenharmony_ci .../src/litert/delegate/nnrt/nnrt_allocator.h |  64 +++++++
15be168c0dSopenharmony_ci .../litert/delegate/nnrt/nnrt_model_kernel.cc |  50 +++++-
16be168c0dSopenharmony_ci .../litert/delegate/nnrt/nnrt_model_kernel.h  |   3 +
17be168c0dSopenharmony_ci .../litert/kernel/cpu/nnacl/nnacl_kernel.cc   |   2 +-
18be168c0dSopenharmony_ci mindspore/lite/src/litert/mindrt_executor.cc  |  14 +-
19be168c0dSopenharmony_ci 12 files changed, 458 insertions(+), 11 deletions(-)
20be168c0dSopenharmony_ci create mode 100644 mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.cc
21be168c0dSopenharmony_ci create mode 100644 mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.h
22be168c0dSopenharmony_ci
23be168c0dSopenharmony_cidiff --git a/include/c_api/tensor_c.h b/include/c_api/tensor_c.h
24be168c0dSopenharmony_ciindex 6d2aaab6..2f641725 100644
25be168c0dSopenharmony_ci--- a/include/c_api/tensor_c.h
26be168c0dSopenharmony_ci+++ b/include/c_api/tensor_c.h
27be168c0dSopenharmony_ci@@ -154,6 +154,21 @@ OH_AI_API int64_t OH_AI_TensorGetElementNum(const OH_AI_TensorHandle tensor);
28be168c0dSopenharmony_ci /// \return The data size of the tensor.
29be168c0dSopenharmony_ci OH_AI_API size_t OH_AI_TensorGetDataSize(const OH_AI_TensorHandle tensor);
30be168c0dSopenharmony_ci 
31be168c0dSopenharmony_ci+/// \brief Obtain allocator for the tensor.
32be168c0dSopenharmony_ci+///
33be168c0dSopenharmony_ci+/// \param[in] tensor Tensor object handle.
34be168c0dSopenharmony_ci+///
35be168c0dSopenharmony_ci+/// \return The pointer of allocator.
36be168c0dSopenharmony_ci+OH_AI_API void *OH_AI_TensorGetAllocator(OH_AI_TensorHandle tensor);
37be168c0dSopenharmony_ci+
38be168c0dSopenharmony_ci+/// \brief Set allocator for the tensor.
39be168c0dSopenharmony_ci+///
40be168c0dSopenharmony_ci+/// \param[in] tensor Tensor object handle.
41be168c0dSopenharmony_ci+/// \param[in] allocator A pointer to the allocator.
42be168c0dSopenharmony_ci+///
43be168c0dSopenharmony_ci+/// \return OH_AI_STATUS_SUCCESS if success, or detail error code if failed.
44be168c0dSopenharmony_ci+OH_AI_API OH_AI_Status OH_AI_TensorSetAllocator(OH_AI_TensorHandle tensor, void *allocator);
45be168c0dSopenharmony_ci+
46be168c0dSopenharmony_ci #ifdef __cplusplus
47be168c0dSopenharmony_ci }
48be168c0dSopenharmony_ci #endif
49be168c0dSopenharmony_cidiff --git a/mindspore/lite/BUILD.gn b/mindspore/lite/BUILD.gn
50be168c0dSopenharmony_ciindex 5866e335..58ee5e51 100644
51be168c0dSopenharmony_ci--- a/mindspore/lite/BUILD.gn
52be168c0dSopenharmony_ci+++ b/mindspore/lite/BUILD.gn
53be168c0dSopenharmony_ci@@ -443,6 +443,7 @@ ohos_shared_library("mindspore_lib") {
54be168c0dSopenharmony_ci       "src/litert/delegate/nnrt/checker/primitive_check.cc",
55be168c0dSopenharmony_ci       "src/litert/delegate/nnrt/nnrt_delegate.cc",
56be168c0dSopenharmony_ci       "src/litert/delegate/nnrt/nnrt_model_kernel.cc",
57be168c0dSopenharmony_ci+      "src/litert/delegate/nnrt/nnrt_allocator.cc",
58be168c0dSopenharmony_ci     ]
59be168c0dSopenharmony_ci     include_dirs += [
60be168c0dSopenharmony_ci       "src/delegate/nnrt/include",
61be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/c_api/model_c.cc b/mindspore/lite/src/litert/c_api/model_c.cc
62be168c0dSopenharmony_ciindex 9da52d76..20e1c227 100644
63be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/c_api/model_c.cc
64be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/c_api/model_c.cc
65be168c0dSopenharmony_ci@@ -14,6 +14,7 @@
66be168c0dSopenharmony_ci  * limitations under the License.
67be168c0dSopenharmony_ci  */
68be168c0dSopenharmony_ci #include "include/c_api/model_c.h"
69be168c0dSopenharmony_ci+#include "type_c_private.h"
70be168c0dSopenharmony_ci #include <vector>
71be168c0dSopenharmony_ci #include <cstdint>
72be168c0dSopenharmony_ci #include "include/api/context.h"
73be168c0dSopenharmony_ci@@ -37,6 +38,11 @@ public:
74be168c0dSopenharmony_ci     for (auto out : outputs_train_) {
75be168c0dSopenharmony_ci       delete out;
76be168c0dSopenharmony_ci     }
77be168c0dSopenharmony_ci+
78be168c0dSopenharmony_ci+    // In zero copy scene where user will call set or get allocator function, but when model is destroyed, the allocator
79be168c0dSopenharmony_ci+    // table will not be freed, and its size continues to grow causing memory leak, so when ModelC is destroyed, clean
80be168c0dSopenharmony_ci+    // allocator table.
81be168c0dSopenharmony_ci+    CleanAllocatorTable();
82be168c0dSopenharmony_ci   }
83be168c0dSopenharmony_ci 
84be168c0dSopenharmony_ci   MSTensor **GetInputs(size_t *input_num);
85be168c0dSopenharmony_ci@@ -246,10 +252,42 @@ OH_AI_Status OH_AI_ModelPredict(OH_AI_ModelHandle model, const OH_AI_TensorHandl
86be168c0dSopenharmony_ci   mindspore::MSKernelCallBack after_call_back = impl->TransCallBack(after);
87be168c0dSopenharmony_ci 
88be168c0dSopenharmony_ci   std::vector<mindspore::MSTensor> ms_tensor_outputs;
89be168c0dSopenharmony_ci+
90be168c0dSopenharmony_ci+  bool all_has_data = false;
91be168c0dSopenharmony_ci+
92be168c0dSopenharmony_ci+  size_t output_num;
93be168c0dSopenharmony_ci+  (void)impl->GetOutputs(&output_num);
94be168c0dSopenharmony_ci+  auto handle_num = outputs->handle_num;
95be168c0dSopenharmony_ci+  if (handle_num == output_num) {
96be168c0dSopenharmony_ci+    MS_LOG(INFO) << "use user provided output";
97be168c0dSopenharmony_ci+    for (size_t i = 0; i < output_num; i++) {
98be168c0dSopenharmony_ci+      if (outputs->handle_list[i] == nullptr) {
99be168c0dSopenharmony_ci+        MS_LOG(ERROR) << "user provided output array handle_list[" << i << "] is nullptr";
100be168c0dSopenharmony_ci+        return OH_AI_STATUS_LITE_NULLPTR;
101be168c0dSopenharmony_ci+      }
102be168c0dSopenharmony_ci+      ms_tensor_outputs.push_back(*static_cast<mindspore::MSTensor *>(outputs->handle_list[i]));
103be168c0dSopenharmony_ci+    }
104be168c0dSopenharmony_ci+
105be168c0dSopenharmony_ci+    all_has_data = std::all_of(ms_tensor_outputs.begin(), ms_tensor_outputs.end(), [](const mindspore::MSTensor &t) {
106be168c0dSopenharmony_ci+      return t.Data() != nullptr;
107be168c0dSopenharmony_ci+    });
108be168c0dSopenharmony_ci+
109be168c0dSopenharmony_ci+    if (!all_has_data) {
110be168c0dSopenharmony_ci+      ms_tensor_outputs.clear();
111be168c0dSopenharmony_ci+    }
112be168c0dSopenharmony_ci+
113be168c0dSopenharmony_ci+  }
114be168c0dSopenharmony_ci+
115be168c0dSopenharmony_ci   auto ret = impl->model_->Predict(ms_tensor_inputs, &ms_tensor_outputs, before_call_back, after_call_back);
116be168c0dSopenharmony_ci   if (!ret.IsOk()) {
117be168c0dSopenharmony_ci     MS_LOG(ERROR) << "Predict fail, ret :" << ret;
118be168c0dSopenharmony_ci+    return static_cast<OH_AI_Status>(ret.StatusCode());
119be168c0dSopenharmony_ci   }
120be168c0dSopenharmony_ci+
121be168c0dSopenharmony_ci+  if (handle_num == output_num && all_has_data) {
122be168c0dSopenharmony_ci+    return OH_AI_STATUS_SUCCESS;
123be168c0dSopenharmony_ci+  }
124be168c0dSopenharmony_ci+
125be168c0dSopenharmony_ci   outputs->handle_list = reinterpret_cast<OH_AI_TensorHandle *>(impl->GetOutputs(&outputs->handle_num));
126be168c0dSopenharmony_ci   return static_cast<OH_AI_Status>(ret.StatusCode());
127be168c0dSopenharmony_ci }
128be168c0dSopenharmony_ci@@ -345,7 +383,7 @@ char **OH_AI_TrainCfgGetLossName(OH_AI_TrainCfgHandle train_cfg, size_t *num) {
129be168c0dSopenharmony_ci   auto impl = static_cast<mindspore::TrainCfg *>(train_cfg);
130be168c0dSopenharmony_ci   auto loss_name = impl->GetLossName();
131be168c0dSopenharmony_ci   *num = loss_name.size();
132be168c0dSopenharmony_ci-  char **name = static_cast<char **>(malloc(loss_name.size()));
133be168c0dSopenharmony_ci+  char **name = static_cast<char **>(malloc(loss_name.size() * sizeof(char *)));
134be168c0dSopenharmony_ci   if (name == nullptr) {
135be168c0dSopenharmony_ci     MS_LOG(ERROR) << "Failed to malloc loss_name.";
136be168c0dSopenharmony_ci     return nullptr;
137be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/c_api/tensor_c.cc b/mindspore/lite/src/litert/c_api/tensor_c.cc
138be168c0dSopenharmony_ciindex 4b1e6aff..fc3814dd 100644
139be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/c_api/tensor_c.cc
140be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/c_api/tensor_c.cc
141be168c0dSopenharmony_ci@@ -13,11 +13,18 @@
142be168c0dSopenharmony_ci  * See the License for the specific language governing permissions and
143be168c0dSopenharmony_ci  * limitations under the License.
144be168c0dSopenharmony_ci  */
145be168c0dSopenharmony_ci+#include <unordered_map>
146be168c0dSopenharmony_ci #include "include/c_api/tensor_c.h"
147be168c0dSopenharmony_ci #include "include/api/status.h"
148be168c0dSopenharmony_ci #include "src/tensor.h"
149be168c0dSopenharmony_ci #include "src/litert/cxx_api/tensor/tensor_impl.h"
150be168c0dSopenharmony_ci 
151be168c0dSopenharmony_ci+static std::unordered_map<void *, std::weak_ptr<mindspore::Allocator>> allocator_table;
152be168c0dSopenharmony_ci+
153be168c0dSopenharmony_ci+void CleanAllocatorTable() {
154be168c0dSopenharmony_ci+  allocator_table.clear();
155be168c0dSopenharmony_ci+}
156be168c0dSopenharmony_ci+
157be168c0dSopenharmony_ci OH_AI_TensorHandle OH_AI_TensorCreate(const char *name, OH_AI_DataType type, const int64_t *shape, size_t shape_num,
158be168c0dSopenharmony_ci                                       const void *data, size_t data_len) {
159be168c0dSopenharmony_ci   if (name == nullptr || shape == nullptr) {
160be168c0dSopenharmony_ci@@ -208,3 +215,28 @@ size_t OH_AI_TensorGetDataSize(const OH_AI_TensorHandle tensor) {
161be168c0dSopenharmony_ci   auto impl = static_cast<mindspore::MSTensor *>(tensor);
162be168c0dSopenharmony_ci   return impl->DataSize();
163be168c0dSopenharmony_ci }
164be168c0dSopenharmony_ci+
165be168c0dSopenharmony_ci+OH_AI_Status OH_AI_TensorSetAllocator(OH_AI_TensorHandle tensor, void *allocator) {
166be168c0dSopenharmony_ci+  if (tensor == nullptr) {
167be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "param is nullptr.";
168be168c0dSopenharmony_ci+    return OH_AI_STATUS_LITE_NULLPTR;
169be168c0dSopenharmony_ci+  }
170be168c0dSopenharmony_ci+  auto impl = static_cast<mindspore::MSTensor *>(tensor);
171be168c0dSopenharmony_ci+  if (allocator_table.count(allocator) == 0) {
172be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "the input allocator does not belong to framework";
173be168c0dSopenharmony_ci+    return OH_AI_STATUS_LITE_PARAM_INVALID;
174be168c0dSopenharmony_ci+  }
175be168c0dSopenharmony_ci+  std::static_pointer_cast<mindspore::LiteTensorImpl>(impl->impl())->set_own_data(true);
176be168c0dSopenharmony_ci+  impl->SetAllocator(allocator_table[allocator].lock());
177be168c0dSopenharmony_ci+  return OH_AI_STATUS_SUCCESS;
178be168c0dSopenharmony_ci+}
179be168c0dSopenharmony_ci+
180be168c0dSopenharmony_ci+void *OH_AI_TensorGetAllocator(const OH_AI_TensorHandle tensor) {
181be168c0dSopenharmony_ci+  if (tensor == nullptr) {
182be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "param is nullptr.";
183be168c0dSopenharmony_ci+    return nullptr;
184be168c0dSopenharmony_ci+  }
185be168c0dSopenharmony_ci+  auto impl = static_cast<mindspore::MSTensor *>(tensor);
186be168c0dSopenharmony_ci+  allocator_table[impl->allocator().get()] = impl->allocator();
187be168c0dSopenharmony_ci+  return impl->allocator().get();
188be168c0dSopenharmony_ci+}
189be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/c_api/type_c_private.h b/mindspore/lite/src/litert/c_api/type_c_private.h
190be168c0dSopenharmony_ciindex 2d3b3883..1a76820d 100644
191be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/c_api/type_c_private.h
192be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/c_api/type_c_private.h
193be168c0dSopenharmony_ci@@ -36,5 +36,8 @@ struct NNRTDeviceDesc {
194be168c0dSopenharmony_ci 
195be168c0dSopenharmony_ci #ifdef __cplusplus
196be168c0dSopenharmony_ci }
197be168c0dSopenharmony_ci+
198be168c0dSopenharmony_ci+void CleanAllocatorTable();
199be168c0dSopenharmony_ci+
200be168c0dSopenharmony_ci #endif
201be168c0dSopenharmony_ci #endif  // MINDSPORE_LITE_SRC_LITERT_C_API_TYPE_C_PRIVATE_H_
202be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/cxx_api/model/model_impl.cc b/mindspore/lite/src/litert/cxx_api/model/model_impl.cc
203be168c0dSopenharmony_ciindex 78b1ca67..02533dc3 100644
204be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/cxx_api/model/model_impl.cc
205be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/cxx_api/model/model_impl.cc
206be168c0dSopenharmony_ci@@ -463,7 +463,60 @@ Status ModelImpl::Predict(const std::vector<MSTensor> &inputs, std::vector<MSTen
207be168c0dSopenharmony_ci           input->set_shape(truncate_shape);
208be168c0dSopenharmony_ci #endif
209be168c0dSopenharmony_ci         }
210be168c0dSopenharmony_ci-        input->set_data(user_input.MutableData());
211be168c0dSopenharmony_ci+        if (user_input.allocator() == input->allocator()) {
212be168c0dSopenharmony_ci+          input->set_data(user_input.MutableData());
213be168c0dSopenharmony_ci+          input->set_own_data(false);
214be168c0dSopenharmony_ci+        } else {
215be168c0dSopenharmony_ci+          void *user_data = user_input.MutableData();
216be168c0dSopenharmony_ci+          if (user_data == nullptr) {
217be168c0dSopenharmony_ci+            MS_LOG(ERROR) << "user data is nullptr";
218be168c0dSopenharmony_ci+            return kLiteNullptr;
219be168c0dSopenharmony_ci+          }
220be168c0dSopenharmony_ci+          void *input_data = input->MutableData();
221be168c0dSopenharmony_ci+          if (input_data == nullptr) {
222be168c0dSopenharmony_ci+            MS_LOG(ERROR) << "input data is nullptr";
223be168c0dSopenharmony_ci+            return kLiteNullptr;
224be168c0dSopenharmony_ci+          }
225be168c0dSopenharmony_ci+          memcpy(input_data, user_data, input->Size());
226be168c0dSopenharmony_ci+        }
227be168c0dSopenharmony_ci+      }
228be168c0dSopenharmony_ci+    }
229be168c0dSopenharmony_ci+  }
230be168c0dSopenharmony_ci+
231be168c0dSopenharmony_ci+  auto ori_output_tensors = GetOutputs();
232be168c0dSopenharmony_ci+  std::vector<bool> copy_output_data;
233be168c0dSopenharmony_ci+  copy_output_data.resize(ori_output_tensors.size(), false);
234be168c0dSopenharmony_ci+  if (outputs->empty()) {
235be168c0dSopenharmony_ci+    MS_LOG(INFO) << "user provided output is empty";
236be168c0dSopenharmony_ci+  } else if (outputs->size() != ori_output_tensors.size()) {
237be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "user provided output size is not equal to model's output size";
238be168c0dSopenharmony_ci+    return kLiteError;
239be168c0dSopenharmony_ci+  } else {
240be168c0dSopenharmony_ci+    for (size_t i = 0; i < ori_output_tensors.size(); i++) {
241be168c0dSopenharmony_ci+      auto ori_output = ori_output_tensors[i];
242be168c0dSopenharmony_ci+      auto lite_impl = std::static_pointer_cast<LiteTensorImpl>(ori_output.impl());
243be168c0dSopenharmony_ci+      MS_CHECK_TRUE_RET(lite_impl != nullptr, kLiteNullptr);
244be168c0dSopenharmony_ci+      auto ori_out_tensor = static_cast<lite::Tensor *>(lite_impl->lite_tensor());
245be168c0dSopenharmony_ci+      MS_CHECK_TRUE_RET(ori_out_tensor != nullptr, kLiteNullptr);
246be168c0dSopenharmony_ci+
247be168c0dSopenharmony_ci+      auto user_output = (*outputs)[i];
248be168c0dSopenharmony_ci+      auto user_lite_impl = std::static_pointer_cast<LiteTensorImpl>(user_output.impl());
249be168c0dSopenharmony_ci+      MS_CHECK_TRUE_RET(user_lite_impl != nullptr, kLiteNullptr);
250be168c0dSopenharmony_ci+      auto user_out_tensor = user_lite_impl->lite_tensor();
251be168c0dSopenharmony_ci+      if (ori_out_tensor == user_out_tensor) {
252be168c0dSopenharmony_ci+        continue;
253be168c0dSopenharmony_ci+      }
254be168c0dSopenharmony_ci+
255be168c0dSopenharmony_ci+      void *user_out_data = nullptr;
256be168c0dSopenharmony_ci+      if (user_output.DataSize() > 0) {
257be168c0dSopenharmony_ci+        user_out_data = user_output.MutableData();
258be168c0dSopenharmony_ci+      }
259be168c0dSopenharmony_ci+      if (ori_out_tensor->allocator() == user_output.allocator() && user_out_data != nullptr) {
260be168c0dSopenharmony_ci+        MS_LOG(INFO) << "use user data";
261be168c0dSopenharmony_ci+        ori_out_tensor->set_data(user_out_data);
262be168c0dSopenharmony_ci+        ori_out_tensor->set_own_data(false);
263be168c0dSopenharmony_ci+      } else {
264be168c0dSopenharmony_ci+        copy_output_data[i] = true;
265be168c0dSopenharmony_ci       }
266be168c0dSopenharmony_ci     }
267be168c0dSopenharmony_ci   }
268be168c0dSopenharmony_ci@@ -474,6 +527,28 @@ Status ModelImpl::Predict(const std::vector<MSTensor> &inputs, std::vector<MSTen
269be168c0dSopenharmony_ci     return ret;
270be168c0dSopenharmony_ci   }
271be168c0dSopenharmony_ci   MS_LOG(DEBUG) << "Run graph success.";
272be168c0dSopenharmony_ci+
273be168c0dSopenharmony_ci+  for (size_t i = 0; i < copy_output_data.size(); i++) {
274be168c0dSopenharmony_ci+    if (!copy_output_data[i]) {
275be168c0dSopenharmony_ci+      continue;
276be168c0dSopenharmony_ci+    }
277be168c0dSopenharmony_ci+    auto ori_output = ori_output_tensors[i];
278be168c0dSopenharmony_ci+    auto ori_out_data = ori_output.MutableData();
279be168c0dSopenharmony_ci+    MS_CHECK_TRUE_RET(ori_out_data != nullptr, kLiteNullptr);
280be168c0dSopenharmony_ci+    auto user_output = (*outputs)[i];
281be168c0dSopenharmony_ci+    MS_CHECK_TRUE_RET(user_output.MutableData() != nullptr, kLiteNullptr);
282be168c0dSopenharmony_ci+    if (user_output.DataSize() >= ori_output.DataSize()) {
283be168c0dSopenharmony_ci+      memcpy(user_output.MutableData(), ori_out_data, ori_output.DataSize());
284be168c0dSopenharmony_ci+    } else {
285be168c0dSopenharmony_ci+      MS_LOG(ERROR) << "user out data size is less than model's output data size";
286be168c0dSopenharmony_ci+      return kLiteError;
287be168c0dSopenharmony_ci+    }
288be168c0dSopenharmony_ci+  }
289be168c0dSopenharmony_ci+
290be168c0dSopenharmony_ci+  if (outputs->size() == ori_output_tensors.size()) {
291be168c0dSopenharmony_ci+    return kSuccess;
292be168c0dSopenharmony_ci+  }
293be168c0dSopenharmony_ci+
294be168c0dSopenharmony_ci   auto res = GetOutputs();
295be168c0dSopenharmony_ci   if (res.empty()) {
296be168c0dSopenharmony_ci     MS_LOG(DEBUG) << "Empty outputs.";
297be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.cc b/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.cc
298be168c0dSopenharmony_cinew file mode 100644
299be168c0dSopenharmony_ciindex 00000000..f79c1682
300be168c0dSopenharmony_ci--- /dev/null
301be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.cc
302be168c0dSopenharmony_ci@@ -0,0 +1,168 @@
303be168c0dSopenharmony_ci+/**
304be168c0dSopenharmony_ci+ * Copyright 2023 Huawei Technologies Co., Ltd
305be168c0dSopenharmony_ci+ *
306be168c0dSopenharmony_ci+ * Licensed under the Apache License, Version 2.0 (the "License");
307be168c0dSopenharmony_ci+ * you may not use this file except in compliance with the License.
308be168c0dSopenharmony_ci+ * You may obtain a copy of the License at
309be168c0dSopenharmony_ci+ *
310be168c0dSopenharmony_ci+ * http://www.apache.org/licenses/LICENSE-2.0
311be168c0dSopenharmony_ci+ *
312be168c0dSopenharmony_ci+ * Unless required by applicable law or agreed to in writing, software
313be168c0dSopenharmony_ci+ * distributed under the License is distributed on an "AS IS" BASIS,
314be168c0dSopenharmony_ci+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
315be168c0dSopenharmony_ci+ * See the License for the specific language governing permissions and
316be168c0dSopenharmony_ci+ * limitations under the License.
317be168c0dSopenharmony_ci+ */
318be168c0dSopenharmony_ci+
319be168c0dSopenharmony_ci+#include <memory>
320be168c0dSopenharmony_ci+#include <atomic>
321be168c0dSopenharmony_ci+#include <unordered_map>
322be168c0dSopenharmony_ci+#include <map>
323be168c0dSopenharmony_ci+#include <mutex>
324be168c0dSopenharmony_ci+#include "src/litert/delegate/nnrt/nnrt_allocator.h"
325be168c0dSopenharmony_ci+#include "src/common/log.h"
326be168c0dSopenharmony_ci+#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h"
327be168c0dSopenharmony_ci+
328be168c0dSopenharmony_ci+namespace mindspore {
329be168c0dSopenharmony_ci+namespace lite {
330be168c0dSopenharmony_ci+NNRTAllocator::~NNRTAllocator() {
331be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
332be168c0dSopenharmony_ci+  for (auto &it : allocated_list_) {
333be168c0dSopenharmony_ci+    auto membuf = it.second;
334be168c0dSopenharmony_ci+    if (memory_category_ == NNRT_INPUT) {
335be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyInputMemory(executor_, index_, &(membuf->memory_));
336be168c0dSopenharmony_ci+    } else {
337be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyOutputMemory(executor_, index_, &(membuf->memory_));
338be168c0dSopenharmony_ci+    }
339be168c0dSopenharmony_ci+    free(membuf);
340be168c0dSopenharmony_ci+  }
341be168c0dSopenharmony_ci+  allocated_list_.clear();
342be168c0dSopenharmony_ci+
343be168c0dSopenharmony_ci+  for (auto &it : free_list_) {
344be168c0dSopenharmony_ci+    auto membuf = it.second;
345be168c0dSopenharmony_ci+    if (memory_category_ == NNRT_INPUT) {
346be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyInputMemory(executor_, index_, &(membuf->memory_));
347be168c0dSopenharmony_ci+    } else {
348be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyOutputMemory(executor_, index_, &(membuf->memory_));
349be168c0dSopenharmony_ci+    }
350be168c0dSopenharmony_ci+    free(membuf);
351be168c0dSopenharmony_ci+  }
352be168c0dSopenharmony_ci+  free_list_.clear();
353be168c0dSopenharmony_ci+}
354be168c0dSopenharmony_ci+
355be168c0dSopenharmony_ci+void *NNRTAllocator::Malloc(size_t size) {
356be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
357be168c0dSopenharmony_ci+  auto iter = free_list_.lower_bound(size);
358be168c0dSopenharmony_ci+  if (iter != free_list_.end()) {
359be168c0dSopenharmony_ci+    auto membuf = iter->second;
360be168c0dSopenharmony_ci+    membuf->ref_count_ = 0;
361be168c0dSopenharmony_ci+    (void)free_list_.erase(iter);
362be168c0dSopenharmony_ci+    allocated_list_[membuf->memory_->data] = membuf;
363be168c0dSopenharmony_ci+    return membuf->memory_->data;
364be168c0dSopenharmony_ci+  }
365be168c0dSopenharmony_ci+
366be168c0dSopenharmony_ci+  auto membuf = new (std::nothrow) MemBuf();
367be168c0dSopenharmony_ci+  if (membuf == nullptr) {
368be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "new Membuf failed.";
369be168c0dSopenharmony_ci+    return nullptr;
370be168c0dSopenharmony_ci+  }
371be168c0dSopenharmony_ci+
372be168c0dSopenharmony_ci+  membuf->ref_count_ = 0;
373be168c0dSopenharmony_ci+  if (memory_category_ == NNRT_INPUT) {
374be168c0dSopenharmony_ci+    membuf->memory_ = OH_NNExecutor_AllocateInputMemory(executor_, index_, size);
375be168c0dSopenharmony_ci+  } else {
376be168c0dSopenharmony_ci+    membuf->memory_ = OH_NNExecutor_AllocateOutputMemory(executor_, index_, size);
377be168c0dSopenharmony_ci+  }
378be168c0dSopenharmony_ci+
379be168c0dSopenharmony_ci+  if (membuf->memory_ == nullptr) {
380be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "malloc OH_NN_Memory return nullptr";
381be168c0dSopenharmony_ci+    return nullptr;
382be168c0dSopenharmony_ci+  }
383be168c0dSopenharmony_ci+  if (membuf->memory_->data == nullptr) {
384be168c0dSopenharmony_ci+    MS_LOG(ERROR) << "malloc OH_NN_Memory return nullptr";
385be168c0dSopenharmony_ci+    if (memory_category_ == NNRT_INPUT) {
386be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyInputMemory(executor_, index_, &(membuf->memory_));
387be168c0dSopenharmony_ci+    } else {
388be168c0dSopenharmony_ci+      OH_NNExecutor_DestroyOutputMemory(executor_, index_, &(membuf->memory_));
389be168c0dSopenharmony_ci+    }
390be168c0dSopenharmony_ci+    return nullptr;
391be168c0dSopenharmony_ci+  }
392be168c0dSopenharmony_ci+
393be168c0dSopenharmony_ci+  allocated_list_[membuf->memory_->data] = membuf;
394be168c0dSopenharmony_ci+  return membuf->memory_->data;
395be168c0dSopenharmony_ci+}
396be168c0dSopenharmony_ci+
397be168c0dSopenharmony_ci+void NNRTAllocator::Free(void *ptr) {
398be168c0dSopenharmony_ci+  if (ptr == nullptr) {
399be168c0dSopenharmony_ci+    return;
400be168c0dSopenharmony_ci+  }
401be168c0dSopenharmony_ci+
402be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
403be168c0dSopenharmony_ci+  auto iter = allocated_list_.find(ptr);
404be168c0dSopenharmony_ci+  if (iter == allocated_list_.end()) {
405be168c0dSopenharmony_ci+    return;
406be168c0dSopenharmony_ci+  }
407be168c0dSopenharmony_ci+  auto membuf = iter->second;
408be168c0dSopenharmony_ci+  membuf->ref_count_ = 0;
409be168c0dSopenharmony_ci+  (void)allocated_list_.erase(iter);
410be168c0dSopenharmony_ci+  (void)free_list_.insert(std::make_pair(membuf->memory_->length, membuf));
411be168c0dSopenharmony_ci+}
412be168c0dSopenharmony_ci+
413be168c0dSopenharmony_ci+int NNRTAllocator::RefCount(void *ptr) {
414be168c0dSopenharmony_ci+  if (ptr == nullptr) {
415be168c0dSopenharmony_ci+    return -1;
416be168c0dSopenharmony_ci+  }
417be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
418be168c0dSopenharmony_ci+  auto iter = allocated_list_.find(ptr);
419be168c0dSopenharmony_ci+  if (iter != allocated_list_.end()) {
420be168c0dSopenharmony_ci+    auto membuf = iter->second;
421be168c0dSopenharmony_ci+    int ref_count = std::atomic_load(&membuf->ref_count_);
422be168c0dSopenharmony_ci+    return ref_count;
423be168c0dSopenharmony_ci+  }
424be168c0dSopenharmony_ci+  return -1;
425be168c0dSopenharmony_ci+}
426be168c0dSopenharmony_ci+
427be168c0dSopenharmony_ci+int NNRTAllocator::SetRefCount(void *ptr, int ref_count) {
428be168c0dSopenharmony_ci+  if (ptr == nullptr) {
429be168c0dSopenharmony_ci+    return -1;
430be168c0dSopenharmony_ci+  }
431be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
432be168c0dSopenharmony_ci+  auto iter = allocated_list_.find(ptr);
433be168c0dSopenharmony_ci+  if (iter != allocated_list_.end()) {
434be168c0dSopenharmony_ci+    auto membuf = iter->second;
435be168c0dSopenharmony_ci+    std::atomic_store(&membuf->ref_count_, ref_count);
436be168c0dSopenharmony_ci+    return ref_count;
437be168c0dSopenharmony_ci+  }
438be168c0dSopenharmony_ci+  return -1;
439be168c0dSopenharmony_ci+}
440be168c0dSopenharmony_ci+
441be168c0dSopenharmony_ci+int NNRTAllocator::DecRefCount(void *ptr, int ref_count) {
442be168c0dSopenharmony_ci+  if (ptr == nullptr) {
443be168c0dSopenharmony_ci+    return -1;
444be168c0dSopenharmony_ci+  }
445be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
446be168c0dSopenharmony_ci+  auto iter = allocated_list_.find(ptr);
447be168c0dSopenharmony_ci+  if (iter != allocated_list_.end()) {
448be168c0dSopenharmony_ci+    auto membuf = iter->second;
449be168c0dSopenharmony_ci+    auto ref = std::atomic_fetch_sub(&membuf->ref_count_, ref_count);
450be168c0dSopenharmony_ci+    return ref;
451be168c0dSopenharmony_ci+  }
452be168c0dSopenharmony_ci+  return -1;
453be168c0dSopenharmony_ci+}
454be168c0dSopenharmony_ci+
455be168c0dSopenharmony_ci+int NNRTAllocator::IncRefCount(void *ptr, int ref_count) {
456be168c0dSopenharmony_ci+  if (ptr == nullptr) {
457be168c0dSopenharmony_ci+    return -1;
458be168c0dSopenharmony_ci+  }
459be168c0dSopenharmony_ci+  std::lock_guard<std::mutex> locker(mutex_);
460be168c0dSopenharmony_ci+  auto iter = allocated_list_.find(ptr);
461be168c0dSopenharmony_ci+  if (iter != allocated_list_.end()) {
462be168c0dSopenharmony_ci+    auto membuf = iter->second;
463be168c0dSopenharmony_ci+    auto ref = std::atomic_fetch_add(&membuf->ref_count_, ref_count);
464be168c0dSopenharmony_ci+    return ref;
465be168c0dSopenharmony_ci+  }
466be168c0dSopenharmony_ci+  return -1;
467be168c0dSopenharmony_ci+}
468be168c0dSopenharmony_ci+
469be168c0dSopenharmony_ci+}  // namespace lite
470be168c0dSopenharmony_ci+}  // namespace mindspore
471be168c0dSopenharmony_ci\ No newline at end of file
472be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.h b/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.h
473be168c0dSopenharmony_cinew file mode 100644
474be168c0dSopenharmony_ciindex 00000000..f6721369
475be168c0dSopenharmony_ci--- /dev/null
476be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/delegate/nnrt/nnrt_allocator.h
477be168c0dSopenharmony_ci@@ -0,0 +1,64 @@
478be168c0dSopenharmony_ci+/**
479be168c0dSopenharmony_ci+* Copyright 2023 Huawei Technologies Co., Ltd
480be168c0dSopenharmony_ci+*
481be168c0dSopenharmony_ci+* Licensed under the Apache License, Version 2.0 (the "License");
482be168c0dSopenharmony_ci+* you may not use this file except in compliance with the License.
483be168c0dSopenharmony_ci+* You may obtain a copy of the License at
484be168c0dSopenharmony_ci+*
485be168c0dSopenharmony_ci+* http://www.apache.org/licenses/LICENSE-2.0
486be168c0dSopenharmony_ci+*
487be168c0dSopenharmony_ci+* Unless required by applicable law or agreed to in writing, software
488be168c0dSopenharmony_ci+* distributed under the License is distributed on an "AS IS" BASIS,
489be168c0dSopenharmony_ci+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
490be168c0dSopenharmony_ci+* See the License for the specific language governing permissions and
491be168c0dSopenharmony_ci+* limitations under the License.
492be168c0dSopenharmony_ci+ */
493be168c0dSopenharmony_ci+#ifndef MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_NNRT_NNRT_ALLOCATOR_H_
494be168c0dSopenharmony_ci+#define MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_NNRT_NNRT_ALLOCATOR_H_
495be168c0dSopenharmony_ci+
496be168c0dSopenharmony_ci+#include <vector>
497be168c0dSopenharmony_ci+#include <map>
498be168c0dSopenharmony_ci+#include <atomic>
499be168c0dSopenharmony_ci+#include <unordered_map>
500be168c0dSopenharmony_ci+#include <map>
501be168c0dSopenharmony_ci+#include <mutex>
502be168c0dSopenharmony_ci+#include "include/api/allocator.h"
503be168c0dSopenharmony_ci+struct OH_NN_Memory;
504be168c0dSopenharmony_ci+struct OH_NNExecutor;
505be168c0dSopenharmony_ci+
506be168c0dSopenharmony_ci+namespace mindspore {
507be168c0dSopenharmony_ci+namespace lite {
508be168c0dSopenharmony_ci+enum MemoryCategory { NNRT_INPUT, NNRT_OUTPUT };
509be168c0dSopenharmony_ci+
510be168c0dSopenharmony_ci+class NNRTAllocator : public Allocator {
511be168c0dSopenharmony_ci+ public:
512be168c0dSopenharmony_ci+  NNRTAllocator(OH_NNExecutor *executor, int index, MemoryCategory memory_category)
513be168c0dSopenharmony_ci+      : index_(index), memory_category_(memory_category), executor_(executor) {}
514be168c0dSopenharmony_ci+  ~NNRTAllocator() override;
515be168c0dSopenharmony_ci+
516be168c0dSopenharmony_ci+  void *Malloc(size_t size) override;
517be168c0dSopenharmony_ci+  void Free(void *ptr) override;
518be168c0dSopenharmony_ci+  int RefCount(void *ptr) override;
519be168c0dSopenharmony_ci+  int SetRefCount(void *ptr, int ref_count) override;
520be168c0dSopenharmony_ci+  int DecRefCount(void *ptr, int ref_count) override;
521be168c0dSopenharmony_ci+  int IncRefCount(void *ptr, int ref_count) override;
522be168c0dSopenharmony_ci+
523be168c0dSopenharmony_ci+ private:
524be168c0dSopenharmony_ci+  struct MemBuf {
525be168c0dSopenharmony_ci+    std::atomic_int ref_count_{0};
526be168c0dSopenharmony_ci+    OH_NN_Memory *memory_{nullptr};
527be168c0dSopenharmony_ci+  };
528be168c0dSopenharmony_ci+
529be168c0dSopenharmony_ci+  int index_{0};
530be168c0dSopenharmony_ci+  MemoryCategory memory_category_{NNRT_INPUT};
531be168c0dSopenharmony_ci+  OH_NNExecutor *executor_{nullptr};
532be168c0dSopenharmony_ci+  std::mutex mutex_;
533be168c0dSopenharmony_ci+  // <membuf->memory_->data, membuf>
534be168c0dSopenharmony_ci+  std::unordered_map<void *, MemBuf *> allocated_list_;
535be168c0dSopenharmony_ci+  std::multimap<size_t, MemBuf *> free_list_;
536be168c0dSopenharmony_ci+};
537be168c0dSopenharmony_ci+
538be168c0dSopenharmony_ci+}  // namespace lite
539be168c0dSopenharmony_ci+}  // namespace mindspore
540be168c0dSopenharmony_ci+
541be168c0dSopenharmony_ci+#endif  // MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_NNRT_NNRT_ALLOCATOR_H_
542be168c0dSopenharmony_ci\ No newline at end of file
543be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.cc b/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.cc
544be168c0dSopenharmony_ciindex 67443e08..f83632dd 100644
545be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.cc
546be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.cc
547be168c0dSopenharmony_ci@@ -15,8 +15,33 @@
548be168c0dSopenharmony_ci  */
549be168c0dSopenharmony_ci #include <include/errorcode.h>
550be168c0dSopenharmony_ci #include "nnrt_model_kernel.h"
551be168c0dSopenharmony_ci-int mindspore::NNRTModelKernel::Prepare() { return 0; }
552be168c0dSopenharmony_ci+#include "nnrt_allocator.h"
553be168c0dSopenharmony_ci+#include "litert/cxx_api/tensor/tensor_impl.h"
554be168c0dSopenharmony_ci+int mindspore::NNRTModelKernel::Prepare() {
555be168c0dSopenharmony_ci+  for (size_t i = 0; i < inputs_.size(); i++) {
556be168c0dSopenharmony_ci+    auto nnrt_allocator = std::make_shared<lite::NNRTAllocator>(oh_nn_executor, i, lite::NNRT_INPUT);
557be168c0dSopenharmony_ci+    if (nnrt_allocator == nullptr) {
558be168c0dSopenharmony_ci+      MS_LOG(ERROR) << "Create NNRTAllocator failed";
559be168c0dSopenharmony_ci+      return lite::RET_NULL_PTR;
560be168c0dSopenharmony_ci+    }
561be168c0dSopenharmony_ci+    inputs_[i].SetAllocator(nnrt_allocator);
562be168c0dSopenharmony_ci+  }
563be168c0dSopenharmony_ci+  for (size_t i = 0; i < outputs_.size(); i++) {
564be168c0dSopenharmony_ci+    auto nnrt_allocator = std::make_shared<lite::NNRTAllocator>(oh_nn_executor, i, lite::NNRT_OUTPUT);
565be168c0dSopenharmony_ci+    if (nnrt_allocator == nullptr) {
566be168c0dSopenharmony_ci+      MS_LOG(ERROR) << "Create NNRTAllocator failed";
567be168c0dSopenharmony_ci+      return lite::RET_NULL_PTR;
568be168c0dSopenharmony_ci+    }
569be168c0dSopenharmony_ci+    outputs_[i].SetAllocator(nnrt_allocator);
570be168c0dSopenharmony_ci+  }
571be168c0dSopenharmony_ci+  return lite::RET_OK;
572be168c0dSopenharmony_ci+}
573be168c0dSopenharmony_ci+
574be168c0dSopenharmony_ci int mindspore::NNRTModelKernel::Execute() {
575be168c0dSopenharmony_ci+  MS_CHECK_TRUE_RET(this->outputs().empty() != true, lite::RET_ERROR);
576be168c0dSopenharmony_ci+  zero_copy_ = this->outputs()[Index0].allocator() != nullptr;
577be168c0dSopenharmony_ci+
578be168c0dSopenharmony_ci+
579be168c0dSopenharmony_ci   lite::STATUS ret_val = PrepareInputs();
580be168c0dSopenharmony_ci   if (ret_val != lite::RET_OK) {
581be168c0dSopenharmony_ci     MS_LOG(ERROR) << "NNRTModelKernel PrepareInputs failed, STATUS is " << ret_val;
582be168c0dSopenharmony_ci@@ -142,9 +167,17 @@ int mindspore::NNRTModelKernel::PrepareInputs() {
583be168c0dSopenharmony_ci     oprend->dimensions = dimensions_list.data();
584be168c0dSopenharmony_ci     oprend->quantParam = quant_param;
585be168c0dSopenharmony_ci     oprend->type = OH_NN_TENSOR;
586be168c0dSopenharmony_ci-    MS_LOG_INFO << "input tensor: " << tensor.Name() << ", data: " << (void *)tensor.MutableData() << ", size: " << tensor.DataSize();
587be168c0dSopenharmony_ci-    OH_NN_ReturnCode ret_code =
588be168c0dSopenharmony_ci-      OH_NNExecutor_SetInput(oh_nn_executor, i, oprend, tensor.MutableData(), tensor.DataSize());
589be168c0dSopenharmony_ci+    MS_LOG_INFO << "input tensor: " << tensor.Name() << ", data: " << (void *)tensor.MutableData()
590be168c0dSopenharmony_ci+                << ", size: " << tensor.DataSize();
591be168c0dSopenharmony_ci+
592be168c0dSopenharmony_ci+    OH_NN_ReturnCode ret_code;
593be168c0dSopenharmony_ci+    if (zero_copy_) {
594be168c0dSopenharmony_ci+      OH_NN_Memory mem{tensor.MutableData(), tensor.DataSize()};
595be168c0dSopenharmony_ci+      ret_code = OH_NNExecutor_SetInputWithMemory(oh_nn_executor, i, oprend, &mem);
596be168c0dSopenharmony_ci+    } else {
597be168c0dSopenharmony_ci+      ret_code = OH_NNExecutor_SetInput(oh_nn_executor, i, oprend, tensor.MutableData(), tensor.DataSize());
598be168c0dSopenharmony_ci+    }
599be168c0dSopenharmony_ci+
600be168c0dSopenharmony_ci     delete (oprend);
601be168c0dSopenharmony_ci 
602be168c0dSopenharmony_ci     if (!tmp_quant_param.empty()) {
603be168c0dSopenharmony_ci@@ -165,7 +198,14 @@ int mindspore::NNRTModelKernel::TransferOutputs() {
604be168c0dSopenharmony_ci   auto output_tensors = this->outputs();
605be168c0dSopenharmony_ci   for (size_t i = 0; i < output_tensors.size(); i++) {
606be168c0dSopenharmony_ci     auto tensor = output_tensors[i];
607be168c0dSopenharmony_ci-    OH_NN_ReturnCode ret_code = OH_NNExecutor_SetOutput(oh_nn_executor, i, tensor.MutableData(), tensor.DataSize());
608be168c0dSopenharmony_ci+
609be168c0dSopenharmony_ci+    OH_NN_ReturnCode ret_code;
610be168c0dSopenharmony_ci+    if (zero_copy_) {
611be168c0dSopenharmony_ci+      OH_NN_Memory mem{tensor.MutableData(), tensor.DataSize()};
612be168c0dSopenharmony_ci+      ret_code = OH_NNExecutor_SetOutputWithMemory(oh_nn_executor, i, &mem);
613be168c0dSopenharmony_ci+    } else {
614be168c0dSopenharmony_ci+      ret_code = OH_NNExecutor_SetOutput(oh_nn_executor, i, tensor.MutableData(), tensor.DataSize());
615be168c0dSopenharmony_ci+    }
616be168c0dSopenharmony_ci     if (ret_code != OH_NN_SUCCESS) {
617be168c0dSopenharmony_ci       MS_LOG(ERROR) << "NNExecutor SetOutput failed, current out tensor is" << tensor.Name()
618be168c0dSopenharmony_ci                     << ", OH_NN_ReturnCode = " << ret_code;
619be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.h b/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.h
620be168c0dSopenharmony_ciindex ea15f7ca..4f2d4f19 100644
621be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.h
622be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/delegate/nnrt/nnrt_model_kernel.h
623be168c0dSopenharmony_ci@@ -51,6 +51,9 @@ class NNRTModelKernel : public kernel::Kernel {
624be168c0dSopenharmony_ci 
625be168c0dSopenharmony_ci  protected:
626be168c0dSopenharmony_ci   OH_NNExecutor *oh_nn_executor = nullptr;
627be168c0dSopenharmony_ci+
628be168c0dSopenharmony_ci+ private:
629be168c0dSopenharmony_ci+  bool zero_copy_{false};
630be168c0dSopenharmony_ci };
631be168c0dSopenharmony_ci }  // namespace mindspore
632be168c0dSopenharmony_ci 
633be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/kernel/cpu/nnacl/nnacl_kernel.cc b/mindspore/lite/src/litert/kernel/cpu/nnacl/nnacl_kernel.cc
634be168c0dSopenharmony_ciindex 813a6467..6cedc8c9 100644
635be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/kernel/cpu/nnacl/nnacl_kernel.cc
636be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/kernel/cpu/nnacl/nnacl_kernel.cc
637be168c0dSopenharmony_ci@@ -105,7 +105,7 @@ int NNACLKernel::OptimizeDataCopy() {
638be168c0dSopenharmony_ci 
639be168c0dSopenharmony_ci   if (input_tensor->allocator() == nullptr || input_tensor->allocator() != output_tensor->allocator() ||
640be168c0dSopenharmony_ci       input_tensor->allocator() != ms_context_->allocator || /* runtime allocator */
641be168c0dSopenharmony_ci-      op_parameter_->is_train_session_) {
642be168c0dSopenharmony_ci+      op_parameter_->is_train_session_ || !output_tensor->own_data()) {
643be168c0dSopenharmony_ci     return NNACLKernel::Run();
644be168c0dSopenharmony_ci   }
645be168c0dSopenharmony_ci 
646be168c0dSopenharmony_cidiff --git a/mindspore/lite/src/litert/mindrt_executor.cc b/mindspore/lite/src/litert/mindrt_executor.cc
647be168c0dSopenharmony_ciindex e5cd720c..5c08cedf 100644
648be168c0dSopenharmony_ci--- a/mindspore/lite/src/litert/mindrt_executor.cc
649be168c0dSopenharmony_ci+++ b/mindspore/lite/src/litert/mindrt_executor.cc
650be168c0dSopenharmony_ci@@ -295,14 +295,22 @@ void MindrtExecutor::FreeOutputTensor() {
651be168c0dSopenharmony_ci     if (dst_tensor->data_type() == kNumberTypeGLUInt && src_tensor->data_type() == kNumberTypeGLUInt) {
652be168c0dSopenharmony_ci       continue;
653be168c0dSopenharmony_ci     }
654be168c0dSopenharmony_ci-    if (dst_tensor->allocator() != nullptr) {
655be168c0dSopenharmony_ci+
656be168c0dSopenharmony_ci+    if ((dst_tensor->allocator() != nullptr && dst_tensor->own_data()) || dst_tensor->data() == nullptr) {
657be168c0dSopenharmony_ci+      MS_LOG(DEBUG) << "free data";
658be168c0dSopenharmony_ci       dst_tensor->FreeData();
659be168c0dSopenharmony_ci-    } else {
660be168c0dSopenharmony_ci-      if (dst_tensor->data_type() == src_tensor->data_type()) {
661be168c0dSopenharmony_ci+    } else if (dst_tensor->data() != nullptr && dst_tensor->data_type() == src_tensor->data_type()) {
662be168c0dSopenharmony_ci+      if (dst_tensor->allocator() == nullptr) {
663be168c0dSopenharmony_ci         /* user set graph-output-tensor from outside */
664be168c0dSopenharmony_ci+        MS_LOG(DEBUG) << "user set graph-output-tensor from outside";
665be168c0dSopenharmony_ci         src_tensor->set_data(dst_tensor->data());
666be168c0dSopenharmony_ci         src_tensor->set_own_data(false);
667be168c0dSopenharmony_ci         src_tensor->set_allocator(nullptr);
668be168c0dSopenharmony_ci+      } else if (dst_tensor->allocator() == src_tensor->allocator()) {
669be168c0dSopenharmony_ci+        /* nnrt npu zero copy scene */
670be168c0dSopenharmony_ci+        MS_LOG(DEBUG) << "zero copy data";
671be168c0dSopenharmony_ci+        src_tensor->set_data(dst_tensor->data());
672be168c0dSopenharmony_ci+        src_tensor->set_own_data(dst_tensor->own_data());
673be168c0dSopenharmony_ci       }
674be168c0dSopenharmony_ci     }
675be168c0dSopenharmony_ci   }
676be168c0dSopenharmony_ci-- 
677be168c0dSopenharmony_ci2.17.1
678be168c0dSopenharmony_ci
679