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