From dd7b1cc473ca99763946e76d1d2e081c2d3c762b Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Tue, 12 Dec 2023 14:58:37 +0800 Subject: [PATCH 01/11] nnrt new Signed-off-by: wangchuanxia --- BUILD.gn | 5 +- frameworks/BUILD.gn | 59 +- frameworks/native/execution_plan.cpp | 94 -- frameworks/native/executor.h | 88 +- frameworks/native/hdi_device_v1_0.cpp | 59 +- frameworks/native/hdi_device_v1_0.h | 4 + frameworks/native/hdi_device_v2_0.cpp | 54 +- frameworks/native/hdi_device_v2_0.h | 4 + frameworks/native/hdi_prepared_model_v1_0.cpp | 112 +- frameworks/native/hdi_prepared_model_v1_0.h | 5 + frameworks/native/hdi_prepared_model_v2_0.cpp | 119 +- frameworks/native/hdi_prepared_model_v2_0.h | 5 + frameworks/native/hdi_returncode_utils.h | 5 +- frameworks/native/inner_model.cpp | 115 +- frameworks/native/inner_model.h | 8 +- frameworks/native/memory_manager.h | 2 +- frameworks/native/neural_network_core.cpp | 690 +++++++++++ frameworks/native/neural_network_runtime.cpp | 658 +++-------- .../native/neural_network_runtime_compat.cpp | 229 ++++ frameworks/native/nn_tensor.cpp | 155 ++- frameworks/native/nn_tensor.h | 16 +- .../native/{executor.cpp => nnexecutor.cpp} | 630 ++++++++-- frameworks/native/nnexecutor.h | 113 ++ frameworks/native/nntensor.cpp | 356 ++++++ frameworks/native/nntensor.h | 61 + frameworks/native/ops/conv2d_builder.cpp | 1 + .../native/ops/conv2d_transpose_builder.cpp | 1 + .../ops/depthwise_conv2d_native_builder.cpp | 1 + frameworks/native/ops/ops_validation.cpp | 33 + frameworks/native/ops/ops_validation.h | 29 + frameworks/native/ops/pooling_builder.cpp | 1 + .../native/ops/strided_slice_builder.cpp | 2 +- frameworks/native/ops_builder.cpp | 4 +- frameworks/native/ops_builder.h | 2 +- frameworks/native/ops_registry.h | 2 +- frameworks/native/prepared_model.h | 7 +- frameworks/native/quant_param.cpp | 71 ++ .../{execution_plan.h => quant_param.h} | 40 +- frameworks/native/tensor.h | 44 + frameworks/native/tensor_desc.cpp | 203 ++++ frameworks/native/tensor_desc.h | 55 + frameworks/native/transform.cpp | 1 - frameworks/native/transform.h | 2 +- frameworks/native/validation.cpp | 12 +- frameworks/native/validation.h | 3 +- .../c/neural_network_runtime_inner.h | 2 +- interfaces/kits/c/BUILD.gn | 34 - .../libneural_network_runtime.ndk.json | 0 .../neural_network_core.h | 1030 +++++++++++++++++ .../neural_network_runtime.h | 327 ++++++ .../neural_network_runtime_compat.h} | 541 ++------- .../neural_network_runtime_type.h | 123 +- 52 files changed, 4825 insertions(+), 1392 deletions(-) delete mode 100644 frameworks/native/execution_plan.cpp create mode 100644 frameworks/native/neural_network_core.cpp create mode 100644 frameworks/native/neural_network_runtime_compat.cpp rename frameworks/native/{executor.cpp => nnexecutor.cpp} (45%) create mode 100644 frameworks/native/nnexecutor.h create mode 100644 frameworks/native/nntensor.cpp create mode 100644 frameworks/native/nntensor.h create mode 100644 frameworks/native/ops/ops_validation.cpp create mode 100644 frameworks/native/ops/ops_validation.h create mode 100644 frameworks/native/quant_param.cpp rename frameworks/native/{execution_plan.h => quant_param.h} (42%) create mode 100644 frameworks/native/tensor.h create mode 100644 frameworks/native/tensor_desc.cpp create mode 100644 frameworks/native/tensor_desc.h delete mode 100644 interfaces/kits/c/BUILD.gn rename interfaces/kits/c/{ => neural_network_runtime}/libneural_network_runtime.ndk.json (100%) create mode 100644 interfaces/kits/c/neural_network_runtime/neural_network_core.h create mode 100644 interfaces/kits/c/neural_network_runtime/neural_network_runtime.h rename interfaces/kits/c/{neural_network_runtime.h => neural_network_runtime/neural_network_runtime_compat.h} (35%) rename interfaces/kits/c/{ => neural_network_runtime}/neural_network_runtime_type.h (96%) diff --git a/BUILD.gn b/BUILD.gn index 0e8e877..3244274 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -14,7 +14,10 @@ import("//build/ohos.gni") group("nnrt_target") { - deps = [ "frameworks:libneural_network_runtime" ] + deps = [ + "frameworks:libneural_network_core", + "frameworks:libneural_network_runtime", + ] } group("nnrt_test_target") { diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index b5dee03..90d5d4c 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -22,25 +22,27 @@ config("nnrt_config") { } nnrt_sources = [ - "native/compilation.cpp", - "native/device_discover_v1_0.cpp", - "native/device_discover_v2_0.cpp", - "native/device_manager.cpp", - "native/device_registrar.cpp", - "native/execution_plan.cpp", - "native/executor.cpp", "native/hdi_device_v1_0.cpp", "native/hdi_device_v2_0.cpp", "native/hdi_prepared_model_v1_0.cpp", "native/hdi_prepared_model_v2_0.cpp", "native/inner_model.cpp", "native/memory_manager.cpp", + "native/neural_network_runtime_compat.cpp", "native/neural_network_runtime.cpp", "native/nn_tensor.cpp", + "native/nnexecutor.cpp", + "native/nntensor.cpp", "native/ops_builder.cpp", "native/ops_registry.cpp", "native/transform.cpp", "native/validation.cpp", + "native/quant_param.cpp", + "native/nnbackend.cpp", + "native/nncompiler.cpp", + "native/nncompiled_cache.cpp", + "native/register_hdi_device_v1_0.cpp", + "native/register_hdi_device_v2_0.cpp", ] ops_sources = [ @@ -70,6 +72,7 @@ ops_sources = [ "native/ops/maxpool_builder.cpp", "native/ops/mul_builder.cpp", "native/ops/onehot_builder.cpp", + "native/ops/ops_validation.cpp", "native/ops/pad_builder.cpp", "native/ops/pooling_builder.cpp", "native/ops/pow_builder.cpp", @@ -130,7 +133,49 @@ ohos_shared_library("libneural_network_runtime") { "mindspore:mindir", ] + deps = [ + ":libneural_network_core" + ] + subsystem_name = "ai" innerapi_tags = [ "ndk" ] part_name = "neural_network_runtime" } + +nnrt_core_sources = [ + "native/neural_network_core.cpp", + "native/tensor_desc.cpp", + "native/validation.cpp", + "native/backend_registrar.cpp", + "native/backend_manager.cpp", + "native/utils.cpp", +] + +ohos_shared_library("libneural_network_core") { + sources = nnrt_core_sources + output_extension = "so" + include_dirs = [ + "..", + "//third_party/mindspore/mindspore-src/source/mindspore/lite/mindir/include", + "../../third_party/bounds_checking_function/include", + ] + + install_images = [ + "system", + "updater", + ] + + public_configs = [ ":nnrt_config" ] + all_dependent_configs = [ ":nnrt_config" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "hitrace:libhitracechain", + ] + + subsystem_name = "ai" + innerapi_tags = [ "ndk" ] + part_name = "neural_network_runtime" +} + diff --git a/frameworks/native/execution_plan.cpp b/frameworks/native/execution_plan.cpp deleted file mode 100644 index 18fd280..0000000 --- a/frameworks/native/execution_plan.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "execution_plan.h" - -#include - -#include "common/log.h" -#include "cpp_type.h" - - -namespace OHOS { -namespace NeuralNetworkRuntime { -OH_NN_ReturnCode ExecutionPlan::GetInputDimRanges(std::vector>& minInputDims, - std::vector>& maxInputDims) -{ - OH_NN_ReturnCode ret = m_preparedModel->GetInputDimRanges(minInputDims, maxInputDims); - if (ret != OH_NN_SUCCESS) { - LOGE("ExecutionPlan GetInputDimRanges() failed."); - return ret; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode ExecutionPlan::Run(const std::vector>& inputTensors, - std::vector>& outputTensors) -{ - OH_NN_ReturnCode ret {OH_NN_FAILED}; - IOTensor tensor; - std::vector inputIOTensors; - size_t inputSize = inputTensors.size(); - size_t outputSize = outputTensors.size(); - for (size_t i = 0; i < inputSize; ++i) { - inputTensors[i]->ConvertToIOTensor(tensor); - inputIOTensors.emplace_back(std::move(tensor)); - } - - std::vector outputIOTensors; - for (size_t i = 0; i < outputSize; ++i) { - outputTensors[i]->ConvertToIOTensor(tensor); - outputIOTensors.emplace_back(std::move(tensor)); - } - - std::vector> outputsDims; - std::vector isSufficientDataBuffer; - ret = m_preparedModel->Run(inputIOTensors, outputIOTensors, outputsDims, isSufficientDataBuffer); - if (ret != OH_NN_SUCCESS) { - LOGE("PrepardModel Run() failed."); - return ret; - } - - // Set the output NNTensor's dimensions from output IOTensor if it is dynamic. - // NNTensor::SetDimensions will check if the tensor buffer is enough for the new dimensions. - if (outputsDims.size() != outputSize) { - LOGE("ExecutionPlan run failed, size of outputsDims is not equal to outputTensors."); - return OH_NN_INVALID_PARAMETER; - } - for (size_t i = 0; i < outputSize; ++i) { - ret = outputTensors[i]->SetDimensions(outputsDims[i]); - if (ret != OH_NN_SUCCESS) { - LOGE("Run failed, error happened when setting output tensor's dimensions, output id: %zu.", i); - return ret; - } - } - - return OH_NN_SUCCESS; -} - - -std::shared_ptr ExecutionPlan::GetInputDevice() const -{ - return m_device; -} - - -std::shared_ptr ExecutionPlan::GetOutputDevice() const -{ - return m_device; -} -} // NeuralNetworkRuntime -} // OHOS \ No newline at end of file diff --git a/frameworks/native/executor.h b/frameworks/native/executor.h index c7b2061..ba06e67 100644 --- a/frameworks/native/executor.h +++ b/frameworks/native/executor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,58 +16,46 @@ #ifndef NEURAL_NETWORK_RUNTIME_EXECUTOR_H #define NEURAL_NETWORK_RUNTIME_EXECUTOR_H -#include "compilation.h" -#include "execution_plan.h" -#include "nn_tensor.h" -#include "interfaces/kits/c/neural_network_runtime.h" -#include "device.h" +#include +#include + +#include "compiler.h" +#include "tensor_desc.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { class Executor { public: - explicit Executor(const Compilation* compilation); - ~Executor(); - - OH_NN_ReturnCode SetInput(uint32_t index, const OH_NN_Tensor& nnTensor, const void* buffer, size_t length); - OH_NN_ReturnCode SetInputFromMemory(uint32_t index, const OH_NN_Tensor& nnTensor, const OH_NN_Memory& memory); - OH_NN_ReturnCode SetOutput(uint32_t index, void* buffer, size_t length); - OH_NN_ReturnCode SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory); - OH_NN_ReturnCode GetOutputShape(uint32_t index, int32_t** dimensions, uint32_t& dimensionCount); - - OH_NN_ReturnCode CreateInputMemory(uint32_t index, size_t length, OH_NN_Memory** memory); - OH_NN_ReturnCode CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory); - OH_NN_ReturnCode DestroyInputMemory(uint32_t index, OH_NN_Memory** memory); - OH_NN_ReturnCode DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory); - - OH_NN_ReturnCode Run(); - -private: - OH_NN_ReturnCode BuildInputTensor(uint32_t index, const OH_NN_Tensor& nnTensor, - std::shared_ptr inputTensor) const; - OH_NN_ReturnCode SetInputTensorWithCurrentBuffer(uint32_t index, std::shared_ptr inputTensor, - const void* buffer, size_t dataLength, size_t curBufferLength); - void SetInputTensorWithNewBuffer(uint32_t index, std::shared_ptr inputTensor, - const void* inputBuffer, size_t length, bool isInnerMem); - OH_NN_ReturnCode CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const; - -private: - struct ExeTensor { - std::shared_ptr tensor; - void* userBuffer; - size_t userBufferLength; - bool isInnerMem; - }; - bool m_isRun {false}; - std::vector> m_modelInputs; - std::vector> m_modelOutputs; - std::shared_ptr m_executionPlan {nullptr}; - std::unordered_map> m_outputDimensions; - std::unordered_map m_inputTensors; - std::unordered_map m_outputTensors; - std::unordered_map> m_inputCreatedMem; - std::unordered_map> m_outputCreatedMem; + Executor() = default; + Executor(Compiler* compiler); + virtual ~Executor() = default; + + virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, + size_t** minInputDims, + size_t** maxInputDims, + size_t* shapeNum) const = 0; + virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) const = 0; + + virtual size_t GetInputNum() const = 0; + virtual size_t GetOutputNum() const = 0; + virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) const = 0; + virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) const = 0; + + virtual OH_NN_ReturnCode SetOnRunDone(NN_OnRunDone onRunDone) = 0; + virtual OH_NN_ReturnCode SetOnServiceDied(NN_OnServiceDied onServiceDied) = 0; + virtual OH_NN_ReturnCode RunSync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize) = 0; + virtual OH_NN_ReturnCode RunAsync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize, + int32_t timeout, + void* userData) = 0; + virtual size_t GetBackendID() = 0; }; -} // namespace NeuralNetworkRuntime -} // namespace OHOS -#endif \ No newline at end of file +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_EXECUTOR_H diff --git a/frameworks/native/hdi_device_v1_0.cpp b/frameworks/native/hdi_device_v1_0.cpp index 3a4582e..62f3112 100644 --- a/frameworks/native/hdi_device_v1_0.cpp +++ b/frameworks/native/hdi_device_v1_0.cpp @@ -94,7 +94,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetDeviceName(std::string& name) auto ret = m_iDevice->GetDeviceName(name); if (ret != HDF_SUCCESS) { LOGE("Get HDI device name failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -104,7 +104,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetVendorName(std::string& name) auto ret = m_iDevice->GetVendorName(name); if (ret != HDF_SUCCESS) { LOGE("Get HDI device vendor name failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -114,7 +114,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetVersion(std::string& version) auto ret = m_iDevice->GetVersion(m_hdiVersion.first, m_hdiVersion.second); if (ret != HDF_SUCCESS) { LOGE("Get HDI version failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } version = 'v' + std::to_string(m_hdiVersion.first) + '_' + std::to_string(m_hdiVersion.second); return OH_NN_SUCCESS; @@ -126,7 +126,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetDeviceType(OH_NN_DeviceType& deviceType) auto ret = m_iDevice->GetDeviceType(iDeviceType); if (ret != HDF_SUCCESS) { LOGE("Get HDI device type failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } deviceType = TransHDIDeviceV1_0Type(iDeviceType); @@ -139,7 +139,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetDeviceStatus(DeviceStatus& status) auto ret = m_iDevice->GetDeviceStatus(iDeviceStatus); if (ret != HDF_SUCCESS) { LOGE("Get HDI device status failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } status = TransHDIDeviceV1_0Status(iDeviceStatus); return OH_NN_SUCCESS; @@ -181,7 +181,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetSupportedOperation(std::shared_ptrIsFloat16PrecisionSupported(isSupported); if (ret != HDF_SUCCESS) { LOGE("Query fp16 precision supported failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -201,7 +201,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::IsPerformanceModeSupported(bool& isSupported) auto ret = m_iDevice->IsPerformanceModeSupported(isSupported); if (ret != HDF_SUCCESS) { LOGE("Query performance mode supported failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -211,7 +211,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::IsPrioritySupported(bool& isSupported) auto ret = m_iDevice->IsPrioritySupported(isSupported); if (ret != HDF_SUCCESS) { LOGE("Query priority supported failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -221,7 +221,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::IsDynamicInputSupported(bool& isSupported) auto ret = m_iDevice->IsDynamicInputSupported(isSupported); if (ret != HDF_SUCCESS) { LOGE("Query dynamic input supported failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -231,7 +231,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::IsModelCacheSupported(bool& isSupported) auto ret = m_iDevice->IsModelCacheSupported(isSupported); if (ret != HDF_SUCCESS) { LOGE("Query cache model supported failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; } @@ -324,7 +324,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::PrepareModelFromModelCache(const std::vectorPrepareModelFromModelCache(iBuffers, iModelConfig, iPreparedModel); if (hdiRet != HDF_SUCCESS) { LOGE("Prepare model from cache failed. ErrorCode=%d", hdiRet); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } preparedModel = CreateSharedPtr(iPreparedModel); @@ -357,6 +357,41 @@ void* HDIDeviceV1_0::AllocateBuffer(size_t length) return addr; } +OH_NN_ReturnCode HDIDeviceV1_0::AllocateBuffer(size_t length, int& fd) +{ + if (length == 0) { + LOGE("The length param is invalid, length=0"); + return OH_NN_INVALID_PARAMETER; + } + + V1_0::SharedBuffer buffer; + auto ret = m_iDevice->AllocateBuffer(length, buffer); + if (ret != HDF_SUCCESS) { + LOGE("Allocate buffer error. ErrorCode: %d", ret); + return OH_NN_MEMORY_ERROR; + } + + fd = buffer.fd; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode HDIDeviceV1_0::ReleaseBuffer(int fd, size_t length) +{ + V1_0::SharedBuffer hdiBuffer {fd, length, 0, length}; + auto deviceResult = m_iDevice->ReleaseBuffer(hdiBuffer); + if (deviceResult != HDF_SUCCESS) { + LOGE("Device release buffer error. ErrorCode: %d", deviceResult); + return OH_NN_MEMORY_ERROR; + } + return OH_NN_SUCCESS; +} + + +void* HDIDeviceV1_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +{ + return AllocateBuffer(length); +} + void* HDIDeviceV1_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) { return AllocateBuffer(length); diff --git a/frameworks/native/hdi_device_v1_0.h b/frameworks/native/hdi_device_v1_0.h index 77a9d85..a7167ba 100644 --- a/frameworks/native/hdi_device_v1_0.h +++ b/frameworks/native/hdi_device_v1_0.h @@ -59,9 +59,13 @@ public: std::shared_ptr& preparedModel) override; void* AllocateBuffer(size_t length) override; + void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) override; void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) override; OH_NN_ReturnCode ReleaseBuffer(const void* buffer) override; + OH_NN_ReturnCode AllocateBuffer(size_t length, int& fd) override; + OH_NN_ReturnCode ReleaseBuffer(int fd, size_t length) override; + private: OH_NN_ReturnCode ReleaseSharedBuffer(const V1_0::SharedBuffer& buffer); diff --git a/frameworks/native/hdi_device_v2_0.cpp b/frameworks/native/hdi_device_v2_0.cpp index e55d6a6..8b4dc35 100644 --- a/frameworks/native/hdi_device_v2_0.cpp +++ b/frameworks/native/hdi_device_v2_0.cpp @@ -130,7 +130,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetDeviceName(std::string& name) { auto ret = m_iDevice->GetDeviceName(name); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get HDI device name failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get HDI device name failed"); } return OH_NN_SUCCESS; } @@ -139,7 +139,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetVendorName(std::string& name) { auto ret = m_iDevice->GetVendorName(name); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get HDI vendor name failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get HDI vendor name failed"); } return OH_NN_SUCCESS; } @@ -148,7 +148,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetVersion(std::string& version) { auto ret = m_iDevice->GetVersion(m_hdiVersion.first, m_hdiVersion.second); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get HDI version failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get HDI version failed"); } version = 'v' + std::to_string(m_hdiVersion.first) + '_' + std::to_string(m_hdiVersion.second); return OH_NN_SUCCESS; @@ -159,7 +159,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetDeviceType(OH_NN_DeviceType& deviceType) V2_0::DeviceType iDeviceType; auto ret = m_iDevice->GetDeviceType(iDeviceType); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get HDI device type failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get HDI device type failed"); } deviceType = TransHDIDeviceV2_0Type(iDeviceType); @@ -171,7 +171,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetDeviceStatus(DeviceStatus& status) V2_0::DeviceStatus iDeviceStatus; auto ret = m_iDevice->GetDeviceStatus(iDeviceStatus); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get HDI device status failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get HDI device status failed"); } status = TransHDIDeviceV2_0Status(iDeviceStatus); return OH_NN_SUCCESS; @@ -225,7 +225,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetSupportedOperation(std::shared_ptrIsFloat16PrecisionSupported(isSupported); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Query fp16 precision supported failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Query fp16 precision supported failed"); } return OH_NN_SUCCESS; } @@ -243,7 +243,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::IsPerformanceModeSupported(bool& isSupported) { auto ret = m_iDevice->IsPerformanceModeSupported(isSupported); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Query performance mode supported failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Query performance mode supported failed"); } return OH_NN_SUCCESS; } @@ -252,7 +252,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::IsPrioritySupported(bool& isSupported) { auto ret = m_iDevice->IsPrioritySupported(isSupported); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Query priority supported failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Query priority supported failed"); } return OH_NN_SUCCESS; } @@ -261,7 +261,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::IsDynamicInputSupported(bool& isSupported) { auto ret = m_iDevice->IsDynamicInputSupported(isSupported); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Query dynamic input supported failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Query dynamic input supported failed"); } return OH_NN_SUCCESS; } @@ -270,7 +270,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::IsModelCacheSupported(bool& isSupported) { auto ret = m_iDevice->IsModelCacheSupported(isSupported); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Query cache model supported failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Query cache model supported failed"); } return OH_NN_SUCCESS; } @@ -392,6 +392,38 @@ void* HDIDeviceV2_0::AllocateBuffer(size_t length) return addr; } +OH_NN_ReturnCode HDIDeviceV2_0::AllocateBuffer(size_t length, int& fd) +{ + if (length == 0) { + LOGE("The length param is invalid, length=0"); + return OH_NN_INVALID_PARAMETER; + } + + V2_0::SharedBuffer buffer; + auto ret = m_iDevice->AllocateBuffer(length, buffer); + if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { + return CheckReturnCode(ret, OH_NN_MEMORY_ERROR, "Allocate buffer error"); + } + + fd = buffer.fd; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode HDIDeviceV2_0::ReleaseBuffer(int fd, size_t length) +{ + V2_0::SharedBuffer hdiBuffer {fd, length, 0, length}; + auto deviceResult = m_iDevice->ReleaseBuffer(hdiBuffer); + if (deviceResult != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { + return CheckReturnCode(deviceResult, OH_NN_FAILED, "Device release buffer error"); + } + return OH_NN_SUCCESS; +} + +void* HDIDeviceV2_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +{ + return AllocateBuffer(length); +} + void* HDIDeviceV2_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) { return AllocateBuffer(length); diff --git a/frameworks/native/hdi_device_v2_0.h b/frameworks/native/hdi_device_v2_0.h index d3c3461..b8dc5f8 100644 --- a/frameworks/native/hdi_device_v2_0.h +++ b/frameworks/native/hdi_device_v2_0.h @@ -59,9 +59,13 @@ public: std::shared_ptr& preparedModel) override; void* AllocateBuffer(size_t length) override; + void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) override; void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) override; OH_NN_ReturnCode ReleaseBuffer(const void* buffer) override; + OH_NN_ReturnCode AllocateBuffer(size_t length, int& fd) override; + OH_NN_ReturnCode ReleaseBuffer(int fd, size_t length) override; + private: OH_NN_ReturnCode ReleaseSharedBuffer(const V2_0::SharedBuffer& buffer); OH_NN_ReturnCode GetOfflineModelFromLiteGraph(std::shared_ptr graph, diff --git a/frameworks/native/hdi_prepared_model_v1_0.cpp b/frameworks/native/hdi_prepared_model_v1_0.cpp index d697ea3..e3211ce 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.cpp +++ b/frameworks/native/hdi_prepared_model_v1_0.cpp @@ -17,6 +17,7 @@ #include "common/log.h" #include "memory_manager.h" +#include "nntensor.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -91,6 +92,71 @@ V1_0::IOTensor TransIOTensor(const IOTensor& tensor) return iTensor; } + +OH_NN_ReturnCode TransIOTensor(const NN_Tensor* tensor, V1_0::IOTensor& ioTensor) +{ + if (tensor == nullptr) { + LOGE("TransIOTensor failed, failed to transform to v1_0 IOTensor."); + return OH_NN_NULL_PTR; + } + + const NNTensor2_0* nnTensor = reinterpret_cast(tensor); + TensorDesc* nnTensorDesc = nnTensor->GetTensorDesc(); + if (nnTensorDesc == nullptr) { + LOGE("TransIOTensor failed, failed to get desc from tensor."); + return OH_NN_NULL_PTR; + } + + // convert name + const char* tensorName = nullptr; + OH_NN_ReturnCode ret = nnTensorDesc->GetName(&tensorName); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get name from desc."); + return ret; + } + ioTensor.name = tensorName; + + // convert data type + OH_NN_DataType dataType; + ret = nnTensorDesc->GetDataType(&dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get data type from desc."); + return ret; + } + ioTensor.dataType = TransDataType(dataType); + + // convert format + OH_NN_Format format; + ret = nnTensorDesc->GetFormat(&format); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get format from desc."); + return ret; + } + ioTensor.format = TransFormat(format); + + // convert shape + int32_t* shape = nullptr; + size_t shapeNum = 0; + ret = nnTensorDesc->GetShape(&shape, &shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get shape from desc."); + return ret; + } + ioTensor.dimensions.clear(); + for (size_t i = 0; i < shapeNum; ++i) { + ioTensor.dimensions.emplace_back(shape[i]); + } + + // convert data + if (!nnTensor->CheckTensorData()) { + LOGE("TransIOTensor failed, failed to check tensor data."); + return OH_NN_INVALID_PARAMETER; + } + V1_0::SharedBuffer iBuffer {nnTensor->GetFd(), nnTensor->GetSize(), nnTensor->GetOffset(), nnTensor->GetSize()}; + ioTensor.data = iBuffer; + + return OH_NN_SUCCESS; +} } // unamed namespace HDIPreparedModelV1_0::HDIPreparedModelV1_0(OHOS::sptr hdiPreparedModel) @@ -110,7 +176,7 @@ OH_NN_ReturnCode HDIPreparedModelV1_0::ExportModelCache(std::vector& mod auto ret = m_hdiPreparedModel->ExportModelCache(iBuffers); if (ret != HDF_SUCCESS) { LOGE("Export model cache failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_SAVE_CACHE_EXCEPTION; } auto memManager = MemoryManager::GetInstance(); @@ -155,7 +221,49 @@ OH_NN_ReturnCode HDIPreparedModelV1_0::Run(const std::vector& inputs, auto ret = m_hdiPreparedModel->Run(iInputTensors, iOutputTensors, outputsDims, isOutputBufferEnough); if (ret != HDF_SUCCESS || outputsDims.empty()) { LOGE("Run model failed. ErrorCode=%d", ret); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode HDIPreparedModelV1_0::Run(const std::vector& inputs, + const std::vector& outputs, std::vector>& outputsDims, + std::vector& isOutputBufferEnough) +{ + V1_0::IOTensor iTensor; + std::vector iInputTensors; + for (const auto& input: inputs) { + auto returnCode = TransIOTensor(input, iTensor); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Run failed, failed to transform to ioTensor."); + return OH_NN_FAILED; + } + if (iTensor.data.fd == INVALID_FD) { + LOGE("Transform inputs tensor failed, cannot find data file descriptor."); + return OH_NN_INVALID_PARAMETER; + } + iInputTensors.emplace_back(iTensor); + } + + std::vector iOutputTensors; + for (const auto& output: outputs) { + auto returnCode = TransIOTensor(output, iTensor); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Run failed, failed to transform to ioTensor."); + return OH_NN_FAILED; + } + if (iTensor.data.fd == INVALID_FD) { + LOGE("Transform outputs tensor failed, cannot find data file descriptor."); + return OH_NN_INVALID_PARAMETER; + } + iOutputTensors.emplace_back(iTensor); + } + + auto ret = m_hdiPreparedModel->Run(iInputTensors, iOutputTensors, outputsDims, isOutputBufferEnough); + if (ret != HDF_SUCCESS || outputsDims.empty()) { + LOGE("Run model failed. ErrorCode=%d", ret); + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; diff --git a/frameworks/native/hdi_prepared_model_v1_0.h b/frameworks/native/hdi_prepared_model_v1_0.h index b98a7ec..c1beeb7 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.h +++ b/frameworks/native/hdi_prepared_model_v1_0.h @@ -41,6 +41,11 @@ public: std::vector>& outputsDims, std::vector& isOutputBufferEnough) override; + OH_NN_ReturnCode Run(const std::vector& inputs, + const std::vector& outputs, + std::vector>& outputsDims, + std::vector& isOutputBufferEnough) override; + private: // first: major version, second: minor version std::pair m_hdiVersion; diff --git a/frameworks/native/hdi_prepared_model_v2_0.cpp b/frameworks/native/hdi_prepared_model_v2_0.cpp index 9b0f0a4..adca2bf 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.cpp +++ b/frameworks/native/hdi_prepared_model_v2_0.cpp @@ -18,6 +18,7 @@ #include "common/log.h" #include "hdi_returncode_utils.h" #include "memory_manager.h" +#include "nntensor.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -92,6 +93,71 @@ V2_0::IOTensor TransIOTensor(const IOTensor& tensor) return iTensor; } + +OH_NN_ReturnCode TransIOTensor(const NN_Tensor* tensor, V2_0::IOTensor& ioTensor) +{ + if (tensor == nullptr) { + LOGE("TransIOTensor failed, failed to transform to V2_0 IOTensor."); + return OH_NN_NULL_PTR; + } + + const NNTensor2_0* nnTensor = reinterpret_cast(tensor); + TensorDesc* nnTensorDesc = nnTensor->GetTensorDesc(); + if (nnTensorDesc == nullptr) { + LOGE("TransIOTensor failed, failed to get desc from tensor."); + return OH_NN_NULL_PTR; + } + + // convert name + const char* tensorName = nullptr; + OH_NN_ReturnCode ret = nnTensorDesc->GetName(&tensorName); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get name from desc."); + return ret; + } + ioTensor.name = tensorName; + + // convert data type + OH_NN_DataType dataType; + ret = nnTensorDesc->GetDataType(&dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get data type from desc."); + return ret; + } + ioTensor.dataType = TransDataType(dataType); + + // convert format + OH_NN_Format format; + ret = nnTensorDesc->GetFormat(&format); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get format from desc."); + return ret; + } + ioTensor.format = TransFormat(format); + + // convert shape + int32_t* shape = nullptr; + size_t shapeNum = 0; + ret = nnTensorDesc->GetShape(&shape, &shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("TransIOTensor failed, failed to get shape from desc."); + return ret; + } + ioTensor.dimensions.clear(); + for (size_t i = 0; i < shapeNum; ++i) { + ioTensor.dimensions.emplace_back(shape[i]); + } + + // convert data + if (!nnTensor->CheckTensorData()) { + LOGE("TransIOTensor failed, failed to check tensor data."); + return OH_NN_INVALID_PARAMETER; + } + V2_0::SharedBuffer iBuffer {nnTensor->GetFd(), nnTensor->GetSize(), nnTensor->GetOffset(), nnTensor->GetSize()}; + ioTensor.data = iBuffer; + + return OH_NN_SUCCESS; +} } // unamed namespace HDIPreparedModelV2_0::HDIPreparedModelV2_0(OHOS::sptr hdiPreparedModel) @@ -110,7 +176,7 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::ExportModelCache(std::vector& mod std::vector iBuffers; auto ret = m_hdiPreparedModel->ExportModelCache(iBuffers); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Export model cache failed"); + return CheckReturnCode(ret, OH_NN_SAVE_CACHE_EXCEPTION, "Export model cache failed"); } auto memManager = MemoryManager::GetInstance(); @@ -154,11 +220,56 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, auto ret = m_hdiPreparedModel->Run(iInputTensors, iOutputTensors, outputsDims); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Run model failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Run model failed"); + } + if (outputsDims.empty()) { + LOGE("Run failed, outputsDims is empty."); + return OH_NN_UNAVAILABLE_DEVICE; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, + const std::vector& outputs, std::vector>& outputsDims, + std::vector& isOutputBufferEnough) +{ + V2_0::IOTensor iTensor; + std::vector iInputTensors; + for (const auto& input: inputs) { + auto returnCode = TransIOTensor(input, iTensor); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Run failed, failed to transform to ioTensor."); + return OH_NN_FAILED; + } + if (iTensor.data.fd == INVALID_FD) { + LOGE("Transform inputs tensor failed, cannot find data file descriptor."); + return OH_NN_INVALID_PARAMETER; + } + iInputTensors.emplace_back(iTensor); + } + + std::vector iOutputTensors; + for (const auto& output: outputs) { + auto returnCode = TransIOTensor(output, iTensor); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Run failed, failed to transform to ioTensor."); + return OH_NN_FAILED; + } + if (iTensor.data.fd == INVALID_FD) { + LOGE("Transform outputs tensor failed, cannot find data file descriptor."); + return OH_NN_INVALID_PARAMETER; + } + iOutputTensors.emplace_back(iTensor); + } + + auto ret = m_hdiPreparedModel->Run(iInputTensors, iOutputTensors, outputsDims); + if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Run model failed"); } if (outputsDims.empty()) { LOGE("Run failed, outputsDims is empty."); - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; @@ -169,7 +280,7 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::GetInputDimRanges(std::vectorGetInputDimRanges(minInputDims, maxInputDims); if (ret != V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { - return CheckReturnCode(ret, OH_NN_UNAVALIDABLE_DEVICE, "Get input dim ranges failed"); + return CheckReturnCode(ret, OH_NN_UNAVAILABLE_DEVICE, "Get input dim ranges failed"); } return OH_NN_SUCCESS; diff --git a/frameworks/native/hdi_prepared_model_v2_0.h b/frameworks/native/hdi_prepared_model_v2_0.h index 9648eae..7f3defd 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.h +++ b/frameworks/native/hdi_prepared_model_v2_0.h @@ -42,6 +42,11 @@ public: std::vector>& outputsDims, std::vector& isOutputBufferEnough) override; + OH_NN_ReturnCode Run(const std::vector& inputs, + const std::vector& outputs, + std::vector>& outputsDims, + std::vector& isOutputBufferEnough) override; + OH_NN_ReturnCode GetInputDimRanges(std::vector>& minInputDims, std::vector>& maxInputDims) override; diff --git a/frameworks/native/hdi_returncode_utils.h b/frameworks/native/hdi_returncode_utils.h index 7d82e96..01f4252 100644 --- a/frameworks/native/hdi_returncode_utils.h +++ b/frameworks/native/hdi_returncode_utils.h @@ -73,9 +73,10 @@ inline std::string ConverterRetToString(OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode r template T CheckReturnCode(int32_t ret, T funcRet, const std::string& errorInfo) { - if (ret < V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { + int32_t success = static_cast(V2_0::NNRT_ReturnCode::NNRT_SUCCESS); + if (ret < success) { LOGE("%{public}s. An error occurred in HDI, errorcode is %{public}d.", errorInfo.c_str(), ret); - } else if (ret > V2_0::NNRT_ReturnCode::NNRT_SUCCESS) { + } else if (ret > success) { OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); LOGE("%{public}s. Errorcode is %{public}s.", errorInfo.c_str(), ConverterRetToString(nnrtRet).c_str()); } diff --git a/frameworks/native/inner_model.cpp b/frameworks/native/inner_model.cpp index a09643e..2b275ba 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -23,11 +23,12 @@ #include "common/utils.h" #include "common/scoped_trace.h" -#include "device_manager.h" +#include "backend_manager.h" #include "validation.h" #include "ops_builder.h" #include "ops_registry.h" #include "transform.h" +#include "nnbackend.h" namespace MSLITE = mindspore::lite; @@ -198,6 +199,75 @@ OH_NN_ReturnCode InnerModel::AddTensor(const OH_NN_Tensor& nnTensor) return OH_NN_SUCCESS; } +OH_NN_ReturnCode InnerModel::AddTensorDesc(const NN_TensorDesc* nnTensorDesc) +{ + if (nnTensorDesc == nullptr) { + LOGE("AddTensorDesc failed, passed nullptr to nnTensorDesc."); + return OH_NN_INVALID_PARAMETER; + } + + std::shared_ptr tensor = CreateSharedPtr(); + if (tensor == nullptr) { + LOGE("AddTensorDesc failed, error happened when creating NNTensor."); + return OH_NN_MEMORY_ERROR; + } + + OH_NN_ReturnCode returnCode = tensor->BuildFromTensorDesc(nnTensorDesc); + if (returnCode != OH_NN_SUCCESS) { + LOGE("AddTensorDesc failed, error happened when build NNTensor from OH_NNCore_TensorDesc."); + return returnCode; + } + + // The NNTensor is named as "Tensor: "". + tensor->SetName("Tensor: " + std::to_string(m_allTensors.size())); + m_allTensors.emplace_back(tensor); + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode InnerModel::SetTensorType(uint32_t index, OH_NN_TensorType tensorType) +{ + if (IsBuild()) { + LOGE("SetTensorType failed, SetTensorType is forbidden after model has been built."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (index >= m_allTensors.size()) { + LOGE("SetTensorType failed, passed index %u out of the number of added tensors.", index); + return OH_NN_INVALID_PARAMETER; + } + + std::shared_ptr tensor = m_allTensors[index]; + OH_NN_ReturnCode returnCode = tensor->SetTensorType(tensorType); + if (returnCode != OH_NN_SUCCESS) { + LOGE("SetTensorType failed, error happened when setting tensor type."); + } + + return returnCode; +} + +OH_NN_ReturnCode InnerModel::SetTensorQuantParam(uint32_t index, const NN_QuantParam* quantParam) +{ + if (IsBuild()) { + LOGE("SetTensorQuantParam failed, SetTensorValue is forbidden after model has been built."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (index >= m_allTensors.size()) { + LOGE("SetTensorQuantParam failed, passed index %u out of the number of added tensors.", index); + return OH_NN_INVALID_PARAMETER; + } + + std::shared_ptr tensor = m_allTensors[index]; + // quantParam is validated in outer function, no need to check it here. + OH_NN_ReturnCode returnCode = tensor->SetQuantParam(quantParam); + if (returnCode != OH_NN_SUCCESS) { + LOGE("SetTensorQuantParam failed, error happened when set quant param."); + } + + return returnCode; +} + // DOTO: 圈复杂度待优化 OH_NN_ReturnCode InnerModel::SetTensorValue(uint32_t index, const void* buffer, size_t length) { @@ -320,7 +390,7 @@ OH_NN_ReturnCode InnerModel::ValidateTensorArray(const OH_NN_UInt32Array& indice size_t allTensorsSize = m_allTensors.size(); for (uint32_t i = 0; i < indices.size; i++) { if (indices.data[i] >= allTensorsSize) { - LOGE("ValidateTensors failed, index %u is out of the number of added tensors.", indices.data[i]); + LOGE("ValidateTensors failed, index %{public}u is out of the number of added tensors.", indices.data[i]); return OH_NN_INVALID_PARAMETER; } } @@ -610,18 +680,19 @@ OH_NN_ReturnCode InnerModel::GetSupportedOperations(size_t deviceID, const bool* return OH_NN_OPERATION_FORBIDDEN; } - DeviceManager& deviceManager = DeviceManager::GetInstance(); + BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr device = deviceManager.GetDevice(deviceID); - if (device == nullptr) { - LOGE("GetSupportedOperations failed, retrieve device failed."); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("GetSupportedOperations failed, retrieve backend failed."); return OH_NN_FAILED; } std::vector supportedOperations; - OH_NN_ReturnCode ret = device->GetSupportedOperation(m_liteGraph, supportedOperations); + std::shared_ptr nnBackend = std::reinterpret_pointer_cast(backend); + OH_NN_ReturnCode ret = nnBackend->GetSupportedOperation(m_liteGraph, supportedOperations); if (ret != OH_NN_SUCCESS) { - LOGE("GetSupportedOperations failed, error happened when get supported operations from devices."); + LOGE("GetSupportedOperations failed, error happened when get supported operations from backends."); return ret; } @@ -649,6 +720,34 @@ std::vector> InnerModel::GetOutputTensors() const return m_outputTensors; } +std::vector, OH_NN_TensorType>> InnerModel::GetInputTensorDescs() const +{ + std::vector, OH_NN_TensorType>> inputTensorDescs; + std::pair, OH_NN_TensorType> tensorDescPair; + for (auto inputTensor : m_inputTensors) { + tensorDescPair.first = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + inputTensor->ConvertToTensorDesc(*(tensorDescPair.first.get())); + tensorDescPair.second = inputTensor->GetType(); + inputTensorDescs.emplace_back(tensorDescPair); + } + + return inputTensorDescs; +} + +std::vector, OH_NN_TensorType>> InnerModel::GetOutputTensorDescs() const +{ + std::vector, OH_NN_TensorType>> outputTensorDescs; + std::pair, OH_NN_TensorType> tensorDescPair; + for (auto outputTensor : m_outputTensors) { + tensorDescPair.first = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + outputTensor->ConvertToTensorDesc(*(tensorDescPair.first.get())); + tensorDescPair.second = outputTensor->GetType(); + outputTensorDescs.emplace_back(tensorDescPair); + } + + return outputTensorDescs; +} + void* InnerModel::GetMetaGraph() const { return m_metaGraph; diff --git a/frameworks/native/inner_model.h b/frameworks/native/inner_model.h index 7deec70..a538ed0 100644 --- a/frameworks/native/inner_model.h +++ b/frameworks/native/inner_model.h @@ -21,8 +21,9 @@ #include "mindir.h" #include "ops_builder.h" +#include "tensor_desc.h" #include "interfaces/innerkits/c/neural_network_runtime_inner.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -35,6 +36,9 @@ public: OH_NN_ReturnCode BuildFromMetaGraph(const void* metaGraph, const Buffer& quantBuffer, const std::string& modelName); OH_NN_ReturnCode AddTensor(const OH_NN_Tensor& nnTensor); + OH_NN_ReturnCode AddTensorDesc(const NN_TensorDesc* nnTensorDesc); + OH_NN_ReturnCode SetTensorQuantParam(uint32_t index, const NN_QuantParam* quantParam); + OH_NN_ReturnCode SetTensorType(uint32_t index, OH_NN_TensorType tensorType); OH_NN_ReturnCode SetTensorValue(uint32_t index, const void* buffer, size_t length); OH_NN_ReturnCode AddOperation(OH_NN_OperationType opType, const OH_NN_UInt32Array& paramIndices, @@ -48,6 +52,8 @@ public: OH_NN_ReturnCode Build(); std::vector> GetInputTensors() const; std::vector> GetOutputTensors() const; + std::vector, OH_NN_TensorType>> GetInputTensorDescs() const; + std::vector, OH_NN_TensorType>> GetOutputTensorDescs() const; std::shared_ptr GetLiteGraphs() const; void* GetMetaGraph() const; Buffer GetQuantBuffer() const; diff --git a/frameworks/native/memory_manager.h b/frameworks/native/memory_manager.h index 5518deb..ae56bec 100644 --- a/frameworks/native/memory_manager.h +++ b/frameworks/native/memory_manager.h @@ -19,7 +19,7 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp new file mode 100644 index 0000000..426ba5d --- /dev/null +++ b/frameworks/native/neural_network_core.cpp @@ -0,0 +1,690 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interfaces/kits/c/neural_network_runtime/neural_network_core.h" + +#include +#include + +#include "common/log.h" +#include "executor.h" +#include "tensor.h" +#include "compilation.h" +#include "backend_manager.h" + +using namespace OHOS::NeuralNetworkRuntime; +#define NNRT_API __attribute__((visibility("default"))) + +NNRT_API NN_TensorDesc *OH_NNTensorDesc_Create() +{ + TensorDesc *tensorDescImpl = new (std::nothrow) TensorDesc(); + if (tensorDescImpl == nullptr) { + LOGE("OH_NNTensorDesc_Create failed, failed to create tensor desc."); + return nullptr; + } + + NN_TensorDesc *tensorDesc = reinterpret_cast(tensorDescImpl); + return tensorDesc; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_Destroy failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_Destroy failed, *tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + TensorDesc *tensorDescImpl = reinterpret_cast(*tensorDesc); + delete tensorDescImpl; + *tensorDesc = nullptr; + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char *name) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_SetName failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (name == nullptr) { + LOGE("OH_NNTensorDesc_SetName failed, name is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->SetName(name); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const char **name) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetName failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (name == nullptr) { + LOGE("OH_NNTensorDesc_GetName failed, name is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*name != nullptr) { + LOGE("OH_NNTensorDesc_GetName failed, *name is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetName(name); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_DataType dataType) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_SetDataType failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->SetDataType(dataType); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH_NN_DataType *dataType) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetDataType failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (dataType == nullptr) { + LOGE("OH_NNTensorDesc_GetDataType failed, dataType is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetDataType(dataType); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeLength) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_SetShape failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shape == nullptr) { + LOGE("OH_NNTensorDesc_SetShape failed, shape is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeLength == 0) { + LOGE("OH_NNTensorDesc_SetShape failed, shapeLength is 0."); + return OH_NN_INVALID_PARAMETER; + } + TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->SetShape(shape, shapeLength); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetShape failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shape == nullptr) { + LOGE("OH_NNTensorDesc_GetShape failed, shape is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*shape != nullptr) { + LOGE("OH_NNTensorDesc_GetShape failed, *shape is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeLength == nullptr) { + LOGE("OH_NNTensorDesc_GetShape failed, shapeLength is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetShape(shape, shapeLength); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_SetFormat failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->SetFormat(format); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_NN_Format *format) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetFormat failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (format == nullptr) { + LOGE("OH_NNTensorDesc_GetFormat failed, format is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetFormat(format); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetElementCount failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (elementCount == nullptr) { + LOGE("OH_NNTensorDesc_GetElementCount failed, elementCount is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetElementNum(elementCount); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, size_t *byteSize) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetByteSize failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (byteSize == nullptr) { + LOGE("OH_NNTensorDesc_GetByteSize failed, byteSize is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetByteSize(byteSize); +} + +NNRT_API NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensor_Create failed, tensorDesc is nullptr."); + return nullptr; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("OH_NNTensor_Create failed, passed invalid backend name %{public}zu.", deviceID); + return nullptr; + } + + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + Tensor* tensorImpl = backend->CreateTensor(descImpl); + if (tensorImpl == nullptr) { + LOGE("OH_NNTensor_Create failed, failed to create tensor."); + return nullptr; + } + + OH_NN_ReturnCode ret = tensorImpl->CreateData(); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNTensor_Create failed, failed to create tensor."); + backend->DestroyTensor(tensorImpl); + return nullptr; + } + + NN_Tensor* tensor = reinterpret_cast(tensorImpl); + return tensor; +} + +NNRT_API NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc, size_t size) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensor_CreateWithSize failed, tensorDesc is nullptr."); + return nullptr; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("OH_NNTensor_CreateWithSize failed, passed invalid backend name %{public}zu.", deviceID); + return nullptr; + } + + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + Tensor* tensorImpl = backend->CreateTensor(descImpl); + if (tensorImpl == nullptr) { + LOGE("OH_NNTensor_CreateWithSize failed, failed to create tensor."); + return nullptr; + } + + OH_NN_ReturnCode ret = tensorImpl->CreateData(size); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNTensor_CreateWithSize failed, failed to create tensor."); + backend->DestroyTensor(tensorImpl); + return nullptr; + } + + NN_Tensor* tensor = reinterpret_cast(tensorImpl); + return tensor; +} + +NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( + size_t deviceID, NN_TensorDesc *tensorDesc, int fd, size_t size, size_t offset) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensor_CreateWithFd failed, tensorDesc is nullptr."); + return nullptr; + } + if (fd < 0) { + LOGE("OH_NNTensor_CreateWithFd failed, fd is less than zero."); + return nullptr; + } + if (size == 0) { + LOGE("OH_NNTensor_CreateWithFd failed, size is zero."); + return nullptr; + } + if (size < offset) { + LOGE("OH_NNTensor_CreateWithFd failed, size is smaller than offset."); + return nullptr; + } + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + size_t byteSize = 0; + auto ret = descImpl->GetByteSize(&byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to get byte size from tensorDesc."); + return nullptr; + } + if ((size - offset) < byteSize) { + LOGE("OH_NNTensor_CreateWithFd failed, size of fd is insufficient."); + return nullptr; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("OH_NNTensor_CreateWithFd failed, passed invalid backend name %{public}zu.", deviceID); + return nullptr; + } + + Tensor* tensorImpl = backend->CreateTensor(descImpl); + if (tensorImpl == nullptr) { + LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); + return nullptr; + } + + ret = tensorImpl->CreateData(fd, size, offset); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); + backend->DestroyTensor(tensorImpl); + return nullptr; + } + + NN_Tensor* tensor = reinterpret_cast(tensorImpl); + return tensor; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_Destroy failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*tensor == nullptr) { + LOGE("OH_NNTensor_Destroy failed, *tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Tensor* tensorImpl = reinterpret_cast(*tensor); + size_t backendID = tensorImpl->GetBackendID(); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendID); + if (backend == nullptr) { + LOGE("OH_NNTensor_Destroy failed, passed invalid backend name %{public}zu.", backendID); + return OH_NN_NULL_PTR; + } + + auto ret = backend->DestroyTensor(tensorImpl); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNTensor_Destroy failed, failed to destroy tensor."); + return ret; + } + *tensor = nullptr; + return OH_NN_SUCCESS; +} + +NNRT_API NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_GetTensorDesc failed, tensor is nullptr."); + return nullptr; + } + + const Tensor *tensorImpl = reinterpret_cast(tensor); + auto tensorDescImpl = tensorImpl->GetTensorDesc(); + if (tensorDescImpl == nullptr) { + LOGE("OH_NNTensor_GetTensorDesc failed, tensor desc is nullptr."); + return nullptr; + } + + NN_TensorDesc *tensorDesc = reinterpret_cast(tensorDescImpl); + return tensorDesc; +} + +NNRT_API void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_GetDataBuffer failed, tensor is nullptr."); + return nullptr; + } + + const Tensor *tensorImpl = reinterpret_cast(tensor); + auto data = tensorImpl->GetData(); + if (data == nullptr) { + LOGE("OH_NNTensor_GetDataBuffer failed, data is nullptr."); + return nullptr; + } + + return data; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_GetSize failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (size == nullptr) { + LOGE("OH_NNTensor_GetSize failed, size is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Tensor *tensorImpl = reinterpret_cast(tensor); + *size = tensorImpl->GetSize(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_GetFd failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (fd == nullptr) { + LOGE("OH_NNTensor_GetFd failed, fd is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Tensor *tensorImpl = reinterpret_cast(tensor); + *fd = tensorImpl->GetFd(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t *offset) +{ + if (tensor == nullptr) { + LOGE("OH_NNTensor_GetOffset failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (offset == nullptr) { + LOGE("OH_NNTensor_GetOffset failed, offset is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Tensor *tensorImpl = reinterpret_cast(tensor); + *offset = tensorImpl->GetOffset(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation) +{ + if (compilation == nullptr) { + LOGE("OH_NNExecutor_Construct failed, compilation is nullptr."); + return nullptr; + } + + Compilation *compilationImpl = reinterpret_cast(compilation); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(compilationImpl->backendID); + if (backend == nullptr) { + LOGE("OH_NNExecutor_Construct failed, failed to get backend of %{public}zu.", compilationImpl->backendID); + return nullptr; + } + + Executor* executorImpl = backend->CreateExecutor(compilationImpl); + if (executorImpl == nullptr) { + LOGE("OH_NNExecutor_Construct failed, failed to create executor."); + return nullptr; + } + + OH_NNExecutor *executor = reinterpret_cast(executorImpl); + return executor; +} + +NNRT_API void OH_NNExecutor_Destroy(OH_NNExecutor **executor) +{ + if (executor == nullptr) { + LOGW("OH_NNExecutor_Destroy failed, executor is nullptr."); + return; + } + if (*executor == nullptr) { + LOGW("OH_NNExecutor_Destroy failed, *executor is nullptr."); + return; + } + + Executor *executorImpl = reinterpret_cast(*executor); + size_t backendID = executorImpl->GetBackendID(); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendID); + if (backend == nullptr) { + LOGE("OH_NNExecutor_Destroy failed, failed to get backend of %{public}zu.", backendID); + return; + } + + auto returnCode = backend->DestroyExecutor(executorImpl); + if (returnCode != OH_NN_SUCCESS) { + LOGE("OH_NNExecutor_Destroy failed, failed to destroy executor."); + return; + } + *executor = nullptr; +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape( + OH_NNExecutor *executor, uint32_t outputIndex, int32_t **shape, uint32_t *shapeLength) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetOutputShape failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shape == nullptr) { + LOGE("OH_NNExecutor_GetOutputShape failed, shape is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*shape != nullptr) { + LOGE("OH_NNExecutor_GetOutputShape failed, *shape is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeLength == nullptr) { + LOGE("OH_NNExecutor_GetOutputShape failed, shapeLength is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->GetOutputShape(outputIndex, shape, shapeLength); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputCount(const OH_NNExecutor *executor, size_t *inputCount) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetInputCount failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputCount == nullptr) { + LOGE("OH_NNExecutor_GetInputCount failed, inputCount is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Executor *executorImpl = reinterpret_cast(executor); + *inputCount = executorImpl->GetInputNum(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputCount(const OH_NNExecutor *executor, size_t *outputCount) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetOutputCount failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputCount == nullptr) { + LOGE("OH_NNExecutor_GetOutputCount failed, outputCount is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Executor *executorImpl = reinterpret_cast(executor); + *outputCount = executorImpl->GetOutputNum(); + return OH_NN_SUCCESS; +} + +NNRT_API NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor, size_t index) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_CreateInputTensorDesc failed, executor is nullptr."); + return nullptr; + } + + const Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->CreateInputTensorDesc(index); +} + +NNRT_API NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_CreateOutputTensorDesc failed, executor is nullptr."); + return nullptr; + } + + const Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->CreateOutputTensorDesc(index); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, + size_t index, size_t **minInputDims, size_t **maxInputDims, size_t *shapeLength) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetInputDimRange failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (minInputDims == nullptr) { + LOGE("OH_NNExecutor_GetInputDimRange failed, minInputDims is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (maxInputDims == nullptr) { + LOGE("OH_NNExecutor_GetInputDimRange failed, maxInputDims is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeLength == nullptr) { + LOGE("OH_NNExecutor_GetInputDimRange failed, shapeLength is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->GetInputDimRange(index, minInputDims, maxInputDims, shapeLength); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetOnRunDone failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (onRunDone == nullptr) { + LOGE("OH_NNExecutor_SetOnRunDone failed, onRunDone is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetOnRunDone(onRunDone); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor, NN_OnServiceDied onServiceDied) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetOnServiceDied failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (onServiceDied == nullptr) { + LOGE("OH_NNExecutor_SetOnServiceDied failed, onServiceDied is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetOnServiceDied(onServiceDied); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, + NN_Tensor *inputTensor[], size_t inputCount, NN_Tensor *outputTensor[], size_t outputCount) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_RunSync failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputTensor == nullptr) { + LOGE("OH_NNExecutor_RunSync failed, inputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputCount == 0) { + LOGE("OH_NNExecutor_RunSync failed, inputCount is 0."); + return OH_NN_INVALID_PARAMETER; + } + if (outputTensor == nullptr) { + LOGE("OH_NNExecutor_RunSync failed, outputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputCount == 0) { + LOGE("OH_NNExecutor_RunSync failed, outputCount is 0."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->RunSync(inputTensor, inputCount, outputTensor, outputCount); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Tensor* inputTensor[], + size_t inputCount, NN_Tensor* outputTensor[], size_t outputCount, int32_t timeout, void* userData) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_RunAsync failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputTensor == nullptr) { + LOGE("OH_NNExecutor_RunAsync failed, inputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputCount == 0) { + LOGE("OH_NNExecutor_RunAsync failed, inputCount is 0."); + return OH_NN_INVALID_PARAMETER; + } + if (outputTensor == nullptr) { + LOGE("OH_NNExecutor_RunAsync failed, outputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputCount == 0) { + LOGE("OH_NNExecutor_RunAsync failed, outputCount is 0."); + return OH_NN_INVALID_PARAMETER; + } + if (userData == 0) { + LOGE("OH_NNExecutor_RunAsync failed, userData is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->RunAsync(inputTensor, inputCount, outputTensor, outputCount, timeout, userData); +} \ No newline at end of file diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp index eb0ccb7..b34fce5 100644 --- a/frameworks/native/neural_network_runtime.cpp +++ b/frameworks/native/neural_network_runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,13 +14,14 @@ */ #include "interfaces/innerkits/c/neural_network_runtime_inner.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "compilation.h" -#include "device_manager.h" #include "executor.h" #include "inner_model.h" #include "common/log.h" +#include "quant_param.h" +#include "validation.h" #include @@ -32,32 +33,186 @@ using namespace OHOS::NeuralNetworkRuntime; #define NNRT_API __attribute__((visibility("default"))) -NNRT_API OH_NNModel *OH_NNModel_Construct(void) +NNRT_API NN_QuantParam *OH_NNQuantParam_Create() { - InnerModel *innerModel = new(std::nothrow) InnerModel(); - if (innerModel == nullptr) { - LOGE("OH_NNModel_Construct failed, please check whether it has enough memory."); + auto* quantParamImpl = new (std::nothrow) QuantParams(); + if (quantParamImpl == nullptr) { + LOGE("OH_NNQuantParam_Create failed, please check whether it has enough memory."); return nullptr; } - OH_NNModel *nnModel = reinterpret_cast(innerModel); - return nnModel; + return (NN_QuantParam*)(quantParamImpl); } -NNRT_API OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *tensor) +NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam* quantParams, const double* scales, size_t quantNum) +{ + if (quantParams == nullptr) { + LOGE("OH_NNQuantParam_SetScales failed, passed nullptr to quantParams."); + return OH_NN_INVALID_PARAMETER; + } + + if (scales == nullptr) { + LOGE("OH_NNQuantParam_SetScales failed, passed nullptr to scales."); + return OH_NN_INVALID_PARAMETER; + } + + if (quantNum == 0) { + LOGE("OH_NNQuantParam_SetScales failed, passed 0 to quantNum."); + return OH_NN_INVALID_PARAMETER; + } + + auto* quantParamImpl = reinterpret_cast(quantParams); + std::vector scaleVector(scales, scales + quantNum); + quantParamImpl->SetScales(scaleVector); + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam* quantParams, const int32_t* zeroPoints, size_t quantNum) +{ + if (quantParams == nullptr) { + LOGE("OH_NNQuantParam_SetZeroPoints failed, passed nullptr to quantParams."); + return OH_NN_INVALID_PARAMETER; + } + + if (zeroPoints == nullptr) { + LOGE("OH_NNQuantParam_SetZeroPoints failed, passed nullptr to zeroPoints."); + return OH_NN_INVALID_PARAMETER; + } + + if (quantNum == 0) { + LOGE("OH_NNQuantParam_SetZeroPoints failed, passed 0 to quantNum."); + return OH_NN_INVALID_PARAMETER; + } + + auto* quantParamImpl = reinterpret_cast(quantParams); + std::vector zeroPointVector(zeroPoints, zeroPoints + quantNum); + quantParamImpl->SetZeroPoints(zeroPointVector); + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam* quantParams, const uint32_t* numBits, size_t quantNum) +{ + if (quantParams == nullptr) { + LOGE("OH_NNQuantParam_SetNumBits failed, passed nullptr to quantParams."); + return OH_NN_INVALID_PARAMETER; + } + + if (numBits == nullptr) { + LOGE("OH_NNQuantParam_SetNumBits failed, passed nullptr to numBits."); + return OH_NN_INVALID_PARAMETER; + } + + if (quantNum == 0) { + LOGE("OH_NNQuantParam_SetNumBits failed, passed 0 to quantNum."); + return OH_NN_INVALID_PARAMETER; + } + + auto* quantParamImpl = reinterpret_cast(quantParams); + std::vector numBitVector(numBits, numBits + quantNum); + quantParamImpl->SetNumBits(numBitVector); + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam** quantParams) +{ + if (quantParams == nullptr) { + LOGE("OH_NNQuantParam_Destroy failed, passed nullptr to quantParams."); + return OH_NN_INVALID_PARAMETER; + } + + if (*quantParams == nullptr) { + LOGW("OH_NNQuantParam_Destroy failed, passed nullptr to *quantParams."); + return OH_NN_INVALID_PARAMETER; + } + + auto* quantParamImpl = reinterpret_cast(*quantParams); + delete quantParamImpl; + *quantParams = nullptr; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel* model, const NN_TensorDesc* tensorDesc) { if (model == nullptr) { - LOGE("OH_NNModel_AddTensor failed, passed nullptr to model."); + LOGE("OH_NNModel_AddTensorToModel failed, passed nullptr to model."); return OH_NN_INVALID_PARAMETER; } - if (tensor == nullptr) { - LOGE("OH_NNModel_AddTensor failed, passed nullptr to tensor."); + if (tensorDesc == nullptr) { + LOGE("OH_NNModel_AddTensorToModel failed, passed nullptr to tensorDesc."); return OH_NN_INVALID_PARAMETER; } - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->AddTensor(*tensor); + auto* innerModel = reinterpret_cast(model); + if (innerModel == nullptr) { + LOGE("OH_NNModel_AddTensorToModel failed, error happened when converting model."); + return OH_NN_FAILED; + } + + OH_NN_ReturnCode returnCode = innerModel->AddTensorDesc(tensorDesc); + if (returnCode != OH_NN_SUCCESS) { + LOGE("OH_NNModel_AddTensorToModel failed, error happened when adding tensor to model."); + } + + return returnCode; +} + +OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel* model, uint32_t index, NN_QuantParam* quantParam) +{ + if (model == nullptr) { + LOGE("OH_NNModel_SetTensorQuantParams failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (quantParam == nullptr) { + LOGE("OH_NNModel_SetTensorQuantParams failed, passed nullptr to quantParam."); + return OH_NN_INVALID_PARAMETER; + } + + auto* innerModel = reinterpret_cast(model); + OH_NN_ReturnCode returnCode = innerModel->SetTensorQuantParam((uint32_t)(index), quantParam); + if (returnCode != OH_NN_SUCCESS) { + LOGE("OH_NNModel_SetTensorQuantParams failed, error happened when setting tensor quantParam."); + } + + return returnCode; +} + +OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel* model, uint32_t index, OH_NN_TensorType tensorType) +{ + if (model == nullptr) { + LOGE("OH_NNModel_SetTensorType failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (!Validation::ValidateTensorType(tensorType)) { + LOGE("OH_NNModel_SetTensorType failed, invalid tensor type."); + return OH_NN_INVALID_PARAMETER; + } + + auto* innerModel = reinterpret_cast(model); + OH_NN_ReturnCode returnCode = innerModel->SetTensorType((uint32_t)(index), tensorType); + if (returnCode != OH_NN_SUCCESS) { + LOGE("OH_NNModel_SetTensorType failed, error happened when setting tensor type."); + } + + return returnCode; +} + +NNRT_API OH_NNModel *OH_NNModel_Construct(void) +{ + InnerModel *innerModel = new(std::nothrow) InnerModel(); + if (innerModel == nullptr) { + LOGE("OH_NNModel_Construct failed, please check whether it has enough memory."); + return nullptr; + } + + OH_NNModel *nnModel = reinterpret_cast(innerModel); + return nnModel; } NNRT_API OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, @@ -264,475 +419,4 @@ NNRT_API OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, InnerModel *innerModel = reinterpret_cast(model); return innerModel->GetSupportedOperations(deviceID, isAvailable, *opCount); -} - -NNRT_API OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) -{ - if (model == nullptr) { - LOGE("OH_NNCompilation_Construct failed, passed nullptr to model."); - return nullptr; - } - const InnerModel *innerModel = reinterpret_cast(model); - - if (!innerModel->IsBuild()) { - LOGE("OH_NNCompilation_Construct failed, should call OH_NNModel_Finish before creating compilation."); - return nullptr; - } - - Compilation *compilation = new(std::nothrow) Compilation(innerModel); - if (compilation == nullptr) { - LOGE("OH_NNCompilation_Construct failed, please check whether it has enough memory."); - return nullptr; - } - - OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); - return nnCompilation; -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_SetDevice failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->SetDevice(deviceID); -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, - const char *cachePath, - uint32_t version) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_SetCache failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - if (cachePath == nullptr) { - LOGE("OH_NNCompilation_SetCache failed, passed nullptr to cachePath."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->SetCacheDir(cachePath, version); -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, - OH_NN_PerformanceMode performanceMode) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_SetPerformanceMode failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->SetPerformance(performanceMode); -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, - OH_NN_Priority priority) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_SetPriority failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->SetPriority(priority); -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_EnableFloat16 failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->SetEnableFp16(enableFloat16); -} - -NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) -{ - if (compilation == nullptr) { - LOGE("OH_NNCompilation_Build failed, passed nullptr to compilation."); - return OH_NN_INVALID_PARAMETER; - } - - Compilation* innerCompilation = reinterpret_cast(compilation); - return innerCompilation->Build(); -} - -NNRT_API void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) -{ - if (compilation == nullptr) { - LOGW("OH_NNCompilation_Destroy has no effect, passed nullptr to compilation."); - return; - } - - if (*compilation == nullptr) { - LOGW("OH_NNCompilation_Destroy has no effect, passed nullptr to *compilation."); - return; - } - - Compilation *innerCompilation = reinterpret_cast(*compilation); - delete innerCompilation; - *compilation = nullptr; -} - -NNRT_API OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation) -{ - if (compilation == nullptr) { - LOGE("OH_NNExecutor_Construct failed, passed nullptr to compilation."); - return nullptr; - } - Compilation *innerCompilation = reinterpret_cast(compilation); - - if (!innerCompilation->IsBuild()) { - LOGE("OH_NNExecutor_Construct failed, should call OH_NNCompilation_Build before creating executor."); - return nullptr; - } - - Executor* executor = new(std::nothrow) Executor(innerCompilation); - if (executor == nullptr) { - LOGE("OH_NNExecutor_Construct failed, please check whether it has enough memory."); - return nullptr; - } - - OH_NNExecutor* nnExecutor = reinterpret_cast(executor); - return nnExecutor; -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetInput(OH_NNExecutor *executor, - uint32_t inputIndex, - const OH_NN_Tensor *tensor, - const void *dataBuffer, - size_t length) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_SetInput failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - if (tensor == nullptr) { - LOGE("OH_NNExecutor_SetInput failed, passed nullptr to tensor."); - return OH_NN_INVALID_PARAMETER; - } - - if (dataBuffer == nullptr) { - LOGE("OH_NNExecutor_SetInput failed, passed nullptr to dataBuffer."); - return OH_NN_INVALID_PARAMETER; - } - - if (length == 0) { - LOGE("OH_NNExecutor_SetInput failed, dataBuffer length is 0."); - return OH_NN_INVALID_PARAMETER; - } - - Executor* innerExecutor = reinterpret_cast(executor); - return innerExecutor->SetInput(inputIndex, *tensor, dataBuffer, length); -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, - uint32_t outputIndex, - void *dataBuffer, - size_t length) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_SetOutput failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - if (dataBuffer == nullptr) { - LOGE("OH_NNExecutor_SetOutput failed, passed nullptr to dataBuffer."); - return OH_NN_INVALID_PARAMETER; - } - - if (length == 0) { - LOGE("OH_NNExecutor_SetOutput failed, dataBuffer length is 0."); - return OH_NN_INVALID_PARAMETER; - } - - Executor* innerExecutor = reinterpret_cast(executor); - return innerExecutor->SetOutput(outputIndex, dataBuffer, length); -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, - uint32_t outputIndex, - int32_t **shape, - uint32_t *shapeLength) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_GetOutputShape failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - if (shape == nullptr) { - LOGE("OH_NNExecutor_GetOutputShape failed, passed nullptr to shape."); - return OH_NN_INVALID_PARAMETER; - } - - if (*shape != nullptr) { - LOGE("OH_NNExecutor_GetOutputShape failed, *shape is not nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (shapeLength == nullptr) { - LOGE("OH_NNExecutor_GetOutputShape failed, passed nullptr to shapeLength."); - return OH_NN_INVALID_PARAMETER; - } - - Executor* innerExecutor = reinterpret_cast(executor); - return innerExecutor->GetOutputShape(outputIndex, shape, *shapeLength); -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_Run(OH_NNExecutor *executor) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_Run failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - Executor *innerExecutor = reinterpret_cast(executor); - return innerExecutor->Run(); -} - -NNRT_API OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, size_t length) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_AllocateInputMemory failed, passed nullptr to executor."); - return nullptr; - } - - if (length == 0) { - LOGW("OH_NNExecutor_AllocateInputMemory has no effect, passed length equals 0."); - return nullptr; - } - - OH_NN_Memory *nnMemory = nullptr; - Executor *innerExecutor = reinterpret_cast(executor); - OH_NN_ReturnCode ret = innerExecutor->CreateInputMemory(inputIndex, length, &nnMemory); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNExecutor_AllocateInputMemory failed, error happened when creating input memory in executor."); - return nullptr; - } - - return nnMemory; -} - -NNRT_API OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, size_t length) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_AllocateOutputMemory failed, passed nullptr to executor."); - return nullptr; - } - - if (length == 0) { - LOGW("OH_NNExecutor_AllocateOutputMemory has no effect, passed length equals 0."); - return nullptr; - } - - OH_NN_Memory *nnMemory = nullptr; - Executor *innerExecutor = reinterpret_cast(executor); - OH_NN_ReturnCode ret = innerExecutor->CreateOutputMemory(outputIndex, length, &nnMemory); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNExecutor_AllocateOutputMemory failed, error happened when creating output memory in executor."); - return nullptr; - } - - return nnMemory; -} - -NNRT_API void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, OH_NN_Memory **memory) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_DestroyInputMemory failed, passed nullptr to executor."); - return; - } - - if (memory == nullptr) { - LOGW("OH_NNExecutor_DestroyInputMemory has no effect, passed nullptr to memory."); - return; - } - - if (*memory == nullptr) { - LOGW("OH_NNExecutor_DestroyInputMemory has no effect, passed nullptr to *memory."); - return; - } - - Executor *innerExecutor = reinterpret_cast(executor); - OH_NN_ReturnCode ret = innerExecutor->DestroyInputMemory(inputIndex, memory); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNExecutor_DestroyInputMemory failed, error happened when destroying input memory."); - return; - } - - *memory = nullptr; -} - -NNRT_API void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, OH_NN_Memory **memory) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_DestroyOutputMemory failed, passed nullptr to executor."); - return; - } - - if (memory == nullptr) { - LOGW("OH_NNExecutor_DestroyOutputMemory has no effect, passed nullptr to memory."); - return; - } - - if (*memory == nullptr) { - LOGW("OH_NNExecutor_DestroyOutputMemory has no effect, passed nullptr to *memory."); - return; - } - - Executor *innerExecutor = reinterpret_cast(executor); - OH_NN_ReturnCode ret = innerExecutor->DestroyOutputMemory(outputIndex, memory); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNExecutor_DestroyOutputMemory failed, error happened when destroying output memory."); - return; - } - - *memory = nullptr; -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, - uint32_t inputIndex, - const OH_NN_Tensor *tensor, - const OH_NN_Memory *memory) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - if (tensor == nullptr) { - LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to tensor."); - return OH_NN_INVALID_PARAMETER; - } - - if (memory == nullptr) { - LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to memory."); - return OH_NN_INVALID_PARAMETER; - } - - Executor *innerExecutor = reinterpret_cast(executor); - return innerExecutor->SetInputFromMemory(inputIndex, *tensor, *memory); -} - -NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOutputWithMemory(OH_NNExecutor *executor, - uint32_t outputIndex, - const OH_NN_Memory *memory) -{ - if (executor == nullptr) { - LOGE("OH_NNExecutor_SetOutputWithMemory failed, passed nullptr to executor."); - return OH_NN_INVALID_PARAMETER; - } - - if (memory == nullptr) { - LOGE("OH_NNExecutor_SetOutputWithMemory failed, passed nullptr to memory."); - return OH_NN_INVALID_PARAMETER; - } - - Executor *innerExecutor = reinterpret_cast(executor); - return innerExecutor->SetOutputFromMemory(outputIndex, *memory); -} - -NNRT_API void OH_NNExecutor_Destroy(OH_NNExecutor **executor) -{ - if (executor == nullptr) { - LOGW("OH_NNExecutor_Destroy has no effect, since executor is nullptr."); - return; - } - - if ((*executor) == nullptr) { - LOGW("OH_NNExecutor_Destroy has no effect, since *executor is nullptr"); - return; - } - - Executor *innerExecutor = reinterpret_cast(*executor); - delete innerExecutor; - *executor = nullptr; -} - -NNRT_API OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount) -{ - if (allDevicesID == nullptr) { - LOGE("OH_NNDevice_GetAllDevicesID failed, passed nullptr to allDevicesID."); - return OH_NN_INVALID_PARAMETER; - } - - if ((*allDevicesID) != nullptr) { - LOGE("OH_NNDevice_GetAllDevicesID failed, *allDevicesID should be nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (deviceCount == nullptr) { - LOGE("OH_NNDevice_GetAllDevicesID failed, passed nullptr to deviceCount."); - return OH_NN_INVALID_PARAMETER; - } - - DeviceManager& deviceManager = DeviceManager::GetInstance(); - const std::vector& allDevices = deviceManager.GetAllDeviceId(); - - if (allDevices.empty()) { - LOGW("OH_NNDevice_GetAllDevicesID got no device."); - *allDevicesID = nullptr; - *deviceCount = 0; - return OH_NN_SUCCESS; - } - - *allDevicesID = allDevices.data(); - // allDevices.size() will not exceed UINT32_MAX, it is safe to cast to uint32_t. - *deviceCount = static_cast(allDevices.size()); - - return OH_NN_SUCCESS; -} - -NNRT_API OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name) -{ - if (name == nullptr) { - LOGE("OH_NNDevice_GetName failed, passed nullptr to name."); - return OH_NN_INVALID_PARAMETER; - } - - if ((*name) != nullptr) { - LOGE("OH_NNDevice_GetName failed, *name should be nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - DeviceManager& deviceManager = DeviceManager::GetInstance(); - const std::string& deviceName = deviceManager.GetDeviceName(deviceID); - if (deviceName.empty()) { - LOGE("OH_NNDevice_GetName failed, error happened when getting name of deviceID %zu.", deviceID); - *name = nullptr; - return OH_NN_FAILED; - } - - *name = deviceName.data(); - return OH_NN_SUCCESS; -} - -NNRT_API OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType* deviceType) -{ - DeviceManager& deviceManager = DeviceManager::GetInstance(); - std::shared_ptr device = deviceManager.GetDevice(deviceID); - if (device == nullptr) { - LOGE("OH_NNDevice_GetName failed, passed invalid deviceID."); - return OH_NN_INVALID_PARAMETER; - } - - if (deviceType == nullptr) { - LOGE("OH_NNDevice_GetType failed, passed nullptr to deviceType."); - return OH_NN_INVALID_PARAMETER; - } - - OH_NN_ReturnCode ret = device->GetDeviceType(*deviceType); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNDevice_GetType failed, device id: %zu.", deviceID); - return ret; - } - return OH_NN_SUCCESS; -} +} \ No newline at end of file diff --git a/frameworks/native/neural_network_runtime_compat.cpp b/frameworks/native/neural_network_runtime_compat.cpp new file mode 100644 index 0000000..c6e3cd2 --- /dev/null +++ b/frameworks/native/neural_network_runtime_compat.cpp @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interfaces/innerkits/c/neural_network_runtime_inner.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" + +#include "compilation.h" +#include "nnexecutor.h" +#include "inner_model.h" +#include "common/log.h" + + +using namespace OHOS::NeuralNetworkRuntime; + +#define NNRT_API __attribute__((visibility("default"))) + +NNRT_API OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *tensor) +{ + if (model == nullptr) { + LOGE("OH_NNModel_AddTensor failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (tensor == nullptr) { + LOGE("OH_NNModel_AddTensor failed, passed nullptr to tensor."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->AddTensor(*tensor); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetInput(OH_NNExecutor *executor, + uint32_t inputIndex, const OH_NN_Tensor *tensor, const void *dataBuffer, size_t length) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetInput failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (tensor == nullptr) { + LOGE("OH_NNExecutor_SetInput failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (dataBuffer == nullptr) { + LOGE("OH_NNExecutor_SetInput failed, dataBuffer is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (length == 0) { + LOGE("OH_NNExecutor_SetInput failed, dataBuffer length is 0."); + return OH_NN_INVALID_PARAMETER; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetInput(inputIndex, *tensor, dataBuffer, length); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, + uint32_t outputIndex, void *dataBuffer, size_t length) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetOutput failed, passed nullptr to executor."); + return OH_NN_INVALID_PARAMETER; + } + if (dataBuffer == nullptr) { + LOGE("OH_NNExecutor_SetOutput failed, passed nullptr to dataBuffer."); + return OH_NN_INVALID_PARAMETER; + } + if (length == 0) { + LOGE("OH_NNExecutor_SetOutput failed, dataBuffer length is 0."); + return OH_NN_INVALID_PARAMETER; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetOutput(outputIndex, dataBuffer, length); + +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_Run(OH_NNExecutor *executor) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_Run failed, passed nullptr to executor."); + return OH_NN_INVALID_PARAMETER; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + return executorImpl->Run(); +} + +NNRT_API OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, size_t length) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_AllocateInputMemory failed, passed nullptr to executor."); + return nullptr; + } + if (length == 0) { + LOGW("OH_NNExecutor_AllocateInputMemory has no effect, passed length equals 0."); + return nullptr; + } + + OH_NN_Memory *nnMemory = nullptr; + NNExecutor *executorImpl = reinterpret_cast(executor); + OH_NN_ReturnCode ret = executorImpl->CreateInputMemory(inputIndex, length, &nnMemory); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNExecutor_AllocateInputMemory failed, error happened when creating input memory in executor."); + return nullptr; + } + + return nnMemory; +} + +NNRT_API OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, size_t length) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_AllocateOutputMemory failed, passed nullptr to executor."); + return nullptr; + } + if (length == 0) { + LOGW("OH_NNExecutor_AllocateOutputMemory has no effect, passed length equals 0."); + return nullptr; + } + + OH_NN_Memory *nnMemory = nullptr; + NNExecutor *executorImpl = reinterpret_cast(executor); + OH_NN_ReturnCode ret = executorImpl->CreateOutputMemory(outputIndex, length, &nnMemory); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNExecutor_AllocateOutputMemory failed, error happened when creating output memory in executor."); + return nullptr; + } + + return nnMemory; +} + +NNRT_API void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, OH_NN_Memory **memory) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_DestroyInputMemory failed, passed nullptr to executor."); + return; + } + if (memory == nullptr) { + LOGW("OH_NNExecutor_DestroyInputMemory has no effect, passed nullptr to memory."); + return; + } + if (*memory == nullptr) { + LOGW("OH_NNExecutor_DestroyInputMemory has no effect, passed nullptr to *memory."); + return; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + OH_NN_ReturnCode ret = executorImpl->DestroyInputMemory(inputIndex, memory); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNExecutor_DestroyInputMemory failed, error happened when destroying input memory."); + return; + } + + *memory = nullptr; +} + +NNRT_API void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, OH_NN_Memory **memory) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_DestroyOutputMemory failed, passed nullptr to executor."); + return; + } + if (memory == nullptr) { + LOGW("OH_NNExecutor_DestroyOutputMemory has no effect, passed nullptr to memory."); + return; + } + if (*memory == nullptr) { + LOGW("OH_NNExecutor_DestroyOutputMemory has no effect, passed nullptr to *memory."); + return; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + OH_NN_ReturnCode ret = executorImpl->DestroyOutputMemory(outputIndex, memory); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNExecutor_DestroyOutputMemory failed, error happened when destroying output memory."); + return; + } + + *memory = nullptr; +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, + uint32_t inputIndex, const OH_NN_Tensor *tensor, const OH_NN_Memory *memory) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to executor."); + return OH_NN_INVALID_PARAMETER; + } + if (tensor == nullptr) { + LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to tensor."); + return OH_NN_INVALID_PARAMETER; + } + if (memory == nullptr) { + LOGE("OH_NNExecutor_SetInputWithMemory failed, passed nullptr to memory."); + return OH_NN_INVALID_PARAMETER; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetInputFromMemory(inputIndex, *tensor, *memory); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOutputWithMemory(OH_NNExecutor *executor, + uint32_t outputIndex, const OH_NN_Memory *memory) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_SetOutputWithMemory failed, passed nullptr to executor."); + return OH_NN_INVALID_PARAMETER; + } + if (memory == nullptr) { + LOGE("OH_NNExecutor_SetOutputWithMemory failed, passed nullptr to memory."); + return OH_NN_INVALID_PARAMETER; + } + + NNExecutor *executorImpl = reinterpret_cast(executor); + return executorImpl->SetOutputFromMemory(outputIndex, *memory); +} \ No newline at end of file diff --git a/frameworks/native/nn_tensor.cpp b/frameworks/native/nn_tensor.cpp index 71755a1..0b2f019 100644 --- a/frameworks/native/nn_tensor.cpp +++ b/frameworks/native/nn_tensor.cpp @@ -23,6 +23,7 @@ #include "common/log.h" #include "mindir.h" #include "mindir_types.h" +#include "quant_param.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -74,7 +75,7 @@ NNTensor& NNTensor::operator=(NNTensor&& tensor) noexcept OH_NN_ReturnCode NNTensor::Build(OH_NN_DataType dataType, const std::vector& dimensions, - const std::vector& quantParam, + const std::vector& quantParams, OH_NN_TensorType type) { m_type = type; @@ -85,17 +86,19 @@ OH_NN_ReturnCode NNTensor::Build(OH_NN_DataType dataType, } m_dataType = dataType; - OH_NN_ReturnCode ret = ParseDimensions(dimensions); - if (ret != OH_NN_SUCCESS) { - LOGE("Build failed, passed invalid dimensions."); - return ret; + OH_NN_ReturnCode returnCode = ValidateDimensions(dimensions); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Build failed, error happened when validating dimensions."); + return returnCode; } + m_dimensions = dimensions; - ret = ParseQuantParams(quantParam); - if (ret != OH_NN_SUCCESS) { - LOGE("Build failed, please check quantParam."); - return ret; + returnCode = ValidateQuantParams(quantParams); + if (returnCode != OH_NN_SUCCESS) { + LOGE("Build failed, error happened when validating quantParams."); + return returnCode; } + m_quantParams = quantParams; return OH_NN_SUCCESS; } @@ -115,16 +118,16 @@ OH_NN_ReturnCode NNTensor::BuildFromOHNNTensor(const OH_NN_Tensor& nnTensor) return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret = ParseDimensions(nnTensor.dimensions, nnTensor.dimensionCount); - if (ret != OH_NN_SUCCESS) { + OH_NN_ReturnCode returnCode = ParseDimensions(nnTensor.dimensions, nnTensor.dimensionCount); + if (returnCode != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, passed invalid nnTensor dimensions."); - return ret; + return returnCode; } - ret = ParseQuantParams(nnTensor.quantParam); - if (ret != OH_NN_SUCCESS) { + returnCode = ParseQuantParams(nnTensor.quantParam); + if (returnCode != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, please check quantParam in nnTensor."); - return ret; + return returnCode; } return OH_NN_SUCCESS; @@ -145,16 +148,86 @@ OH_NN_ReturnCode NNTensor::BuildFromOHNNTensorInfo(const OH_NN_TensorInfo& nnTen m_format = nnTensorInfo.format; m_name = nnTensorInfo.name; - OH_NN_ReturnCode ret = ParseDimensions(nnTensorInfo.dimensions, nnTensorInfo.dimensionCount); - if (ret != OH_NN_SUCCESS) { + OH_NN_ReturnCode returnCode = ParseDimensions(nnTensorInfo.dimensions, nnTensorInfo.dimensionCount); + if (returnCode != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensorInfo failed, passed invalid nnTensorInfo dimensions."); - return ret; + return returnCode; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNTensor::BuildFromTensorDesc(const NN_TensorDesc* tensorDesc) +{ + if (tensorDesc == nullptr) { + LOGE("BuildFromTensorDesc failed, passed nullptr to tensorDesc."); + return OH_NN_INVALID_PARAMETER; + } + + const auto* tensorDescImpl = reinterpret_cast(tensorDesc); + + // Get datatype from TensorDesc + OH_NN_DataType dataType; + OH_NN_ReturnCode returnCode = tensorDescImpl->GetDataType(&dataType); + if (returnCode != OH_NN_SUCCESS) { + LOGE("BuildFromTensorDesc failed, error happened when get dataType."); + return returnCode; + } + if (!OHOS::NeuralNetworkRuntime::Validation::ValidateTensorDataType(dataType)) { + LOGE("BuildFromTensorDesc failed, passed invalid dataType."); + return OH_NN_INVALID_PARAMETER; + } + + // Get Dimensions from TensorDesc and transform to std::vector + int32_t* shape {nullptr}; + size_t shapeNum {0}; + returnCode = tensorDescImpl->GetShape(&shape, &shapeNum); + if (returnCode != OH_NN_SUCCESS) { + LOGE("BuildFromTensorDesc failed, error happened when get shape."); + return returnCode; + } + std::vector dimensions(shape, shape + shapeNum); + + // OH_NNCore_TensorDesc does not include quant parameters and tensor type, should be set using indenpendent interface. + returnCode = Build(dataType, dimensions, {}, OH_NN_TENSOR); + if (returnCode != OH_NN_SUCCESS) { + LOGE("BuildFromTensorDesc failed, error happened when building NNTensor."); } + return returnCode; +} + +OH_NN_ReturnCode NNTensor::SetQuantParam(const NN_QuantParam* quantParam) +{ + if (quantParam == nullptr) { + LOGE("SetQuantParam failed, quantParam is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const auto* quantParamImpl = reinterpret_cast(quantParam); + m_quantParams.clear(); + OH_NN_ReturnCode returnCode = quantParamImpl->CopyToCompat(m_quantParams); + if (returnCode != OH_NN_SUCCESS) { + LOGE("SetQuantParam failed, error happened when converting quantization parameters."); + return returnCode; + } + + returnCode = ValidateQuantParams(m_quantParams); + if (returnCode != OH_NN_SUCCESS) { + m_quantParams.clear(); + LOGE("SetQuantParam failed, error happened when parsing quantization parameters."); + } + + return returnCode; +} + +OH_NN_ReturnCode NNTensor::SetTensorType(OH_NN_TensorType tensorType) +{ + m_type = tensorType; return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNTensor::ParseDimensions(const std::vector& dimensions) +OH_NN_ReturnCode NNTensor::ValidateDimensions(const std::vector& dimensions) { // Temporary variable to check overflow. uint64_t absoluteDim {0}; @@ -187,24 +260,24 @@ OH_NN_ReturnCode NNTensor::ParseDimensions(const std::vector& dimension m_dataLength = static_cast(dataLength); } - m_dimensions = std::move(dimensions); return OH_NN_SUCCESS; } OH_NN_ReturnCode NNTensor::ParseDimensions(const int32_t* dimensions, uint32_t dimensionCount) { - OH_NN_ReturnCode ret = Validation::ValidateArray(dimensions, dimensionCount); - if (ret != OH_NN_SUCCESS) { + OH_NN_ReturnCode returnCode = Validation::ValidateArray(dimensions, dimensionCount); + if (returnCode != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, please check dimension and dimensionCount in NNTensor."); - return ret; + return returnCode; } std::vector dimensionsVec = ConstructVectorFromArray(dimensions, dimensionCount); - ret = ParseDimensions(dimensionsVec); - if (ret != OH_NN_SUCCESS) { + returnCode = ValidateDimensions(dimensionsVec); + if (returnCode != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, passed invalid dimension info."); - return ret; + return returnCode; } + m_dimensions = std::move(dimensionsVec); return OH_NN_SUCCESS; } @@ -231,26 +304,26 @@ OH_NN_ReturnCode NNTensor::ParseQuantParams(const OH_NN_QuantParam* quantParam) tmpQuantParam.emplace_back((QuantParam){numBits, scale, zeroPoint}); } - OH_NN_ReturnCode ret = ParseQuantParams(tmpQuantParam); - if (ret != OH_NN_SUCCESS) { - LOGE("ParseQuantParams failed, please numBits in NNTensor."); - return ret; + OH_NN_ReturnCode returnCode = ValidateQuantParams(tmpQuantParam); + if (returnCode != OH_NN_SUCCESS) { + LOGE("ParseQuantParams failed, error happened when validating quantization parameters."); + return returnCode; } + m_quantParams = std::move(tmpQuantParam); return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNTensor::ParseQuantParams(const std::vector& quantParams) +OH_NN_ReturnCode NNTensor::ValidateQuantParams(const std::vector& quantParams) { for (const QuantParam& param : quantParams) { // Only support 8-bit quantization in NNR version 1.0 if ((param.numBits != SUPPORT_NUM_BIT) || (param.numBits == INVALID_NUM_BIT)) { - LOGE("ParseQuantParams failed, get invalid numBits %d.", param.numBits); + LOGE("ValidateQuantParams failed, get invalid numBits %d.", param.numBits); return OH_NN_INVALID_PARAMETER; } } - m_quantParams = quantParams; return OH_NN_SUCCESS; } @@ -287,10 +360,10 @@ OH_NN_ReturnCode NNTensor::SetDimensions(const std::vector& dimensions) return OH_NN_INVALID_PARAMETER; } - auto ret = ParseDimensions(dimensions); - if (ret != OH_NN_SUCCESS) { - LOGE("SetDimemsions failed, passed invalid dimension info."); - return ret; + auto returnCode = ValidateDimensions(dimensions); + if (returnCode != OH_NN_SUCCESS) { + LOGE("SetDimemsions failed, error happened when validating dimensions."); + return returnCode; } m_dimensions = dimensions; @@ -381,6 +454,14 @@ void NNTensor::ConvertToIOTensor(IOTensor& tensor) const tensor.length = m_bufferLength; } +void NNTensor::ConvertToTensorDesc(TensorDesc& desc) const +{ + desc.SetDataType(m_dataType); + desc.SetFormat(m_format); + desc.SetName(m_name.c_str()); + desc.SetShape(m_dimensions.data(), m_dimensions.size()); +} + bool NNTensor::IsDynamicShape() const { return m_isDynamicShape; diff --git a/frameworks/native/nn_tensor.h b/frameworks/native/nn_tensor.h index fc7db02..f2d091d 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -20,8 +20,9 @@ #include #include "cpp_type.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "interfaces/innerkits/c/neural_network_runtime_inner.h" +#include "tensor_desc.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -41,9 +42,11 @@ public: OH_NN_ReturnCode BuildFromOHNNTensor(const OH_NN_Tensor& nnTensor); OH_NN_ReturnCode BuildFromOHNNTensorInfo(const OH_NN_TensorInfo& nnTensorInfo); + OH_NN_ReturnCode BuildFromTensorDesc(const NN_TensorDesc* tensorDesc); + OH_NN_ReturnCode Build(OH_NN_DataType dataType, const std::vector& dimensions, - const std::vector& quantParam, + const std::vector& quantParams, OH_NN_TensorType type); void IdentifyOpParameter(); @@ -51,6 +54,8 @@ public: void SetBuffer(const void* buffer, size_t length); void SetFormat(const OH_NN_Format& format); OH_NN_ReturnCode SetDimensions(const std::vector& dimensions); + OH_NN_ReturnCode SetQuantParam(const NN_QuantParam* quantParam); + OH_NN_ReturnCode SetTensorType(OH_NN_TensorType tensorType); std::string GetName() const; OH_NN_TensorType GetType() const; @@ -66,6 +71,7 @@ public: std::vector GetQuantParam() const; LiteGraphTensorPtr ConvertToLiteGraphTensor() const; void ConvertToIOTensor(IOTensor& tensor) const; + void ConvertToTensorDesc(TensorDesc& desc) const; bool IsDynamicShape() const; bool IsQuantTensor() const; @@ -74,12 +80,10 @@ public: bool CompareAttribute(const NNTensor& tensor) const; private: - // Used in BuildFromOHNNTensor() OH_NN_ReturnCode ParseQuantParams(const OH_NN_QuantParam* quantParams); OH_NN_ReturnCode ParseDimensions(const int32_t* dimensions, uint32_t dimensionCount); - // Used in Build() - OH_NN_ReturnCode ParseQuantParams(const std::vector& quantParams); - OH_NN_ReturnCode ParseDimensions(const std::vector& dimensions); + OH_NN_ReturnCode ValidateQuantParams(const std::vector& quantParams); + OH_NN_ReturnCode ValidateDimensions(const std::vector& dimensions); private: OH_NN_TensorType m_type {OH_NN_TENSOR}; diff --git a/frameworks/native/executor.cpp b/frameworks/native/nnexecutor.cpp similarity index 45% rename from frameworks/native/executor.cpp rename to frameworks/native/nnexecutor.cpp index fda1fff..6bd9671 100644 --- a/frameworks/native/executor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,30 +13,355 @@ * limitations under the License. */ -#include "executor.h" -#include "securec.h" +#include "nnexecutor.h" +#include "nntensor.h" +#include "common/log.h" +#include "cpp_type.h" +#include "securec.h" #include "common/utils.h" #include "common/scoped_trace.h" #include "transform.h" - namespace OHOS { namespace NeuralNetworkRuntime { -Executor::Executor(const Compilation* compilation) - : m_modelInputs(compilation->GetInputTensors()), - m_modelOutputs(compilation->GetOutputTensors()), - m_executionPlan(compilation->GetExecutionPlan()) {} +NNExecutor::NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, + const std::vector, OH_NN_TensorType>>& inputTensorDescs, + const std::vector, OH_NN_TensorType>>& outputTensorDescs) +{ + m_backendID = backendID; + m_device = device; + m_preparedModel = preparedModel; + m_inputTensorDescs = inputTensorDescs; + m_outputTensorDescs = outputTensorDescs; +} + +OH_NN_ReturnCode NNExecutor::GetInputDimRange( + size_t inputIndex, size_t** minInputDims, size_t** maxInputDims, size_t* shapeNum) const +{ + if (minInputDims == nullptr) { + LOGE("NNExecutor::GetInputDimRange failed, minInputDims is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (maxInputDims == nullptr) { + LOGE("NNExecutor::GetInputDimRange failed, maxInputDims is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeNum == nullptr) { + LOGE("NNExecutor::GetInputDimRange failed, shapeNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + std::vector> minInputDimsVec; + std::vector> maxInputDimsVec; + OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(minInputDimsVec, maxInputDimsVec); + if (oldRet != OH_NN_SUCCESS) { + LOGW("NNExecutor::GetInputDimRange failed, current version don't support get input dim ranges."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (minInputDimsVec.size() != maxInputDimsVec.size()) { + LOGE("NNExecutor::GetInputDimRange failed, size of minInputDimsVec is not equal to maxInputDimsVec."); + return OH_NN_INVALID_PARAMETER; + } + if (inputIndex >= minInputDimsVec.size()) { + LOGE("NNExecutor::GetInputDimRange failed, inputIndex[%{public}zu] is out of range.", inputIndex); + return OH_NN_INVALID_PARAMETER; + } -OH_NN_ReturnCode Executor::BuildInputTensor(uint32_t index, const OH_NN_Tensor& nnTensor, - std::shared_ptr inputTensor) const + std::vector minInputDimVec = minInputDimsVec[inputIndex]; + std::vector maxInputDimVec = maxInputDimsVec[inputIndex]; + if (minInputDimVec.size() != maxInputDimVec.size()) { + LOGE("NNExecutor::GetInputDimRange failed, size of the min input dims is not equal to the max input" + " dims of the %{public}zuth input.", inputIndex); + return OH_NN_INVALID_PARAMETER; + } + *shapeNum = minInputDimVec.size(); + *minInputDims = reinterpret_cast(minInputDimVec.data()); + *maxInputDims = reinterpret_cast(maxInputDimVec.data()); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) const +{ + if (outputIndex >= m_outputTensorDescs.size()) { + LOGE("NNExecutor::GetOutputShape failed, outputIndex must be smaller than m_outputTensorDescs.size."); + return OH_NN_INVALID_PARAMETER; + } + if (m_outputTensorDescs[outputIndex].first == nullptr) { + LOGE("NNExecutor::GetOutputShape failed, tensor desc of output %{public}u is nullptr.", outputIndex); + return OH_NN_INVALID_PARAMETER; + } + + auto tensorDesc = m_outputTensorDescs[outputIndex].first; + size_t shapeNumTmp = 0; + auto ret = tensorDesc->GetShape(shape, &shapeNumTmp); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::GetOutputShape failed, failed to get shape from tensor desc."); + return ret; + } + *shapeNum = static_cast(shapeNumTmp); + + return OH_NN_SUCCESS; +} + +size_t NNExecutor::GetInputNum() const +{ + return m_inputTensorDescs.size(); +} + +size_t NNExecutor::GetOutputNum() const +{ + return m_outputTensorDescs.size(); +} + +NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) const +{ + if (index >= m_inputTensorDescs.size()) { + LOGE("NNExecutor::CreateInputTensorDesc failed, index must be smaller than m_inputTensorDescs.size."); + return nullptr; + } + if (m_inputTensorDescs[index].first == nullptr) { + LOGE("NNExecutor::CreateInputTensorDesc failed, tensor desc of input %{public}zu is nullptr.", index); + return nullptr; + } + + TensorDesc* tensorDescImpl = new (std::nothrow) TensorDesc(); + if (tensorDescImpl == nullptr) { + LOGE("NNExecutor::CreateInputTensorDesc failed, failed to create tensor desc."); + return nullptr; + } + + // Copy the member attributes to new tensor description + *tensorDescImpl = *(m_inputTensorDescs[index].first.get()); + + return reinterpret_cast(tensorDescImpl); +} + +NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) const +{ + if (index >= m_outputTensorDescs.size()) { + LOGE("NNExecutor::CreateOutputTensorDesc failed, index must be smaller than m_outputTensorDescs.size."); + return nullptr; + } + if (m_outputTensorDescs[index].first == nullptr) { + LOGE("NNExecutor::CreateOutputTensorDesc failed, tensor desc of output %{public}zu is nullptr.", index); + return nullptr; + } + + TensorDesc* tensorDescImpl = new (std::nothrow) TensorDesc(); + if (tensorDescImpl == nullptr) { + LOGE("NNExecutor::CreateOutputTensorDesc failed, failed to create tensor desc."); + return nullptr; + } + + // Copy the member attributes to new tensor description + *tensorDescImpl = *(m_outputTensorDescs[index].first.get()); + + return reinterpret_cast(tensorDescImpl); +} + +OH_NN_ReturnCode NNExecutor::SetOnRunDone(NN_OnRunDone onRunDone) +{ + LOGE("NNExecutor::SetOnRunDone failed, SetOnRunDone is not supported."); + return OH_NN_OPERATION_FORBIDDEN; +} + +OH_NN_ReturnCode NNExecutor::SetOnServiceDied(NN_OnServiceDied onServiceDied) +{ + LOGE("NNExecutor::SetOnServiceDied failed, SetOnServiceDied is not supported."); + return OH_NN_OPERATION_FORBIDDEN; +} + +OH_NN_ReturnCode NNExecutor::RunSync(NN_Tensor* inputTensors[], size_t inputSize, + NN_Tensor* outputTensors[], size_t outputSize) +{ + if (m_inputTensorDescs.size() != inputSize) { + LOGE("NNExecutor::RunSync failed, inputSize:%{public}zu is not equal to model input size:%{public}zu", + inputSize, m_inputTensorDescs.size()); + return OH_NN_INVALID_PARAMETER; + } + if (m_outputTensorDescs.size() != outputSize) { + LOGE("NNExecutor::RunSync failed, outputSize:%{public}zu is not equal to model output size:%{public}zu", + outputSize, m_outputTensorDescs.size()); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret {OH_NN_FAILED}; + ret = CheckInputDimRanges(inputTensors, inputSize); + if (ret != OH_NN_OPERATION_FORBIDDEN && ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::RunSync failed, failed to check input dim ranges."); + return ret; + } + + OHOS::NeuralNetworkRuntime::IOTensor tensor; + std::vector inputTensorsVec; + for (size_t i = 0; i < inputSize; ++i) { + if (inputTensors[i] == nullptr) { + LOGE("NNExecutor::RunSync failed, input[%{public}zu] is nullptr.", i); + return OH_NN_INVALID_PARAMETER; + } + inputTensorsVec.emplace_back(inputTensors[i]); + } + + std::vector outputTensorsVec; + for (size_t i = 0; i < outputSize; ++i) { + if (outputTensors[i] == nullptr) { + LOGE("NNExecutor::RunSync failed, output[%{public}zu] is nullptr.", i); + return OH_NN_INVALID_PARAMETER; + } + outputTensorsVec.emplace_back(outputTensors[i]); + } + + std::vector> outputsDims; + std::vector isSufficientDataBuffer; + + ret = m_preparedModel->Run(inputTensorsVec, outputTensorsVec, outputsDims, isSufficientDataBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::RunSync failed, failed to run in prepared model."); + return ret; + } + + // Set the output NNTensor2_0's dimensions from output IOTensor if it is dynamic. + // NNTensor2_0::SetDimensions will check if the tensor buffer is enough for the new dimensions. + if (outputsDims.size() != outputSize) { + LOGE("NNExecutor::RunSync failed, size of outputsDims is not equal to outputTensors."); + return OH_NN_INVALID_PARAMETER; + } + for (size_t i = 0; i < outputSize; ++i) { + NNTensor2_0* nnTensor = reinterpret_cast(outputTensors[i]); + TensorDesc* nnTensorDesc = nnTensor->GetTensorDesc(); + if (nnTensorDesc == nullptr) { + LOGE("NNExecutor::RunSync failed, failed to get desc from tensor."); + return OH_NN_NULL_PTR; + } + ret = nnTensorDesc->SetShape(outputsDims[i].data(), outputsDims[i].size()); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::RunSync failed, error happened when setting output tensor's dimensions," + " output id: %zu.", i); + return ret; + } + ret = m_outputTensorDescs[i].first->SetShape(outputsDims[i].data(), outputsDims[i].size()); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::RunSync failed, error happened when setting inner output tensor's dimensions," + " output id: %zu.", i); + return ret; + } + } + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNExecutor::RunAsync(NN_Tensor* inputTensors[], size_t inputSize, + NN_Tensor* outputTensors[], size_t outputSize, int32_t timeout, void* userData) +{ + LOGE("NNExecutor::RunAsync failed, RunAsync is not supported."); + return OH_NN_OPERATION_FORBIDDEN; +} + +size_t NNExecutor::GetBackendID() +{ + return m_backendID; +} + +OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize) +{ + std::vector> minInputDims; + std::vector> maxInputDims; + OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(minInputDims, maxInputDims); + if (oldRet != OH_NN_SUCCESS) { + LOGW("NNExecutor::CheckInputDimRanges failed, current version don't support get input dim ranges."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (inputSize != minInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of minInputDims:%{public}zu is not equal to " + "inputSize:%{public}zu.", minInputDims.size(), inputSize); + return OH_NN_INVALID_PARAMETER; + } + + if (inputSize != maxInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of maxInputDims:%{public}zu is not equal to " + "inputSize:%{public}zu.", maxInputDims.size(), inputSize); + return OH_NN_INVALID_PARAMETER; + } + + const NNTensor2_0* nnTensor = nullptr; + OH_NN_ReturnCode ret {OH_NN_FAILED}; + for (size_t i = 0; i < inputSize; ++i) { + const std::vector& minSingleInputDims = minInputDims[i]; + const std::vector& maxSingleInputDims = maxInputDims[i]; + nnTensor = reinterpret_cast(inputTensors[i]); + if (nnTensor == nullptr) { + LOGE("NNExecutor::CheckInputDimRanges failed, input %{public}zu is nullptr.", i); + return OH_NN_NULL_PTR; + } + ret = nnTensor->CheckDimRanges(minSingleInputDims, maxSingleInputDims); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::CheckInputDimRanges failed, failed to check input dim ranges of input %{public}zu", i); + return ret; + } + } + + return OH_NN_SUCCESS; +} + +bool NNExecutor::CompareAttribute( + const std::pair, OH_NN_TensorType>& tensorDesc, const NNTensor& tensor) const +{ + OH_NN_DataType dataType; + auto ret = tensorDesc.first->GetDataType(&dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("CompareAttribute failed, failed to get data type from tensor desc."); + return false; + } + if (dataType != tensor.GetDataType()) { + LOGI("Tensors have different data type: %d and %d.", dataType, tensor.GetDataType()); + return false; + } + + int32_t* shape {nullptr}; + size_t shapeNum {0}; + ret = tensorDesc.first->GetShape(&shape, &shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("CompareAttribute failed, failed to get shape from tensor desc."); + return false; + } + const std::vector dimensions = tensor.GetDimensions(); + if (shapeNum != dimensions.size()) { + LOGI("Tensors have differents dimension counts: %zu and %zu.", shapeNum, dimensions.size()); + return false; + } + + size_t dimensionsSize = dimensions.size(); + for (size_t i = 0; i < dimensionsSize; i++) { + if ((shape[i] != -1) && (shape[i] != dimensions[i])) { + LOGI("Tensors have different dimension: dimension index: %zu, dimension value: %d and %d.", + i, shape[i], dimensions[i]); + return false; + } + } + + if (tensorDesc.second != tensor.GetType()) { + LOGI("Tensors have different type: %{public}d and %{public}d.", tensorDesc.second, tensor.GetType()); + return false; + } + + return true; +} + +OH_NN_ReturnCode NNExecutor::BuildInputTensor(uint32_t index, const OH_NN_Tensor& nnTensor, + std::shared_ptr inputTensor) const { // Note: inputs have only shapes info. - if (index >= m_modelInputs.size()) { + if (index >= m_inputTensorDescs.size()) { LOGE("BuildInputTensor failed, input index is out of range."); return OH_NN_INVALID_PARAMETER; } + if (m_inputTensorDescs[index].first == nullptr) { + LOGE("BuildInputTensor failed, tensor desc of input %{public}u is nullptr.", index); + return OH_NN_INVALID_PARAMETER; + } // Build a tensor from nnTensor. auto ret = inputTensor->BuildFromOHNNTensor(nnTensor); @@ -50,22 +375,32 @@ OH_NN_ReturnCode Executor::BuildInputTensor(uint32_t index, const OH_NN_Tensor& return OH_NN_INVALID_PARAMETER; } - inputTensor->SetFormat(m_modelInputs[index]->GetFormat()); - if (!m_modelInputs[index]->CompareAttribute(*inputTensor)) { + OH_NN_Format format; + ret = m_inputTensorDescs[index].first->GetFormat(&format); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildInputTensor failed, failed to get tensor format from desc."); + return ret; + } + inputTensor->SetFormat(format); + + if (!CompareAttribute(m_inputTensorDescs[index], *inputTensor)) { LOGE("BuildInputTensor failed, input has different attributes from the one in the constructed model."); return OH_NN_INVALID_PARAMETER; } - inputTensor->SetName(m_modelInputs[index]->GetName()); + const char* name {nullptr}; + ret = m_inputTensorDescs[index].first->GetName(&name); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildInputTensor failed, failed to get tensor name from desc."); + return ret; + } + inputTensor->SetName(name); return OH_NN_SUCCESS; } -OH_NN_ReturnCode Executor::SetInputTensorWithCurrentBuffer(uint32_t index, - std::shared_ptr inputTensor, - const void* buffer, - size_t dataLength, - size_t curBufferLength) +OH_NN_ReturnCode NNExecutor::SetInputTensorWithCurrentBuffer(uint32_t index, + std::shared_ptr inputTensor, const void* buffer, size_t dataLength, size_t curBufferLength) { void* curBuffer = m_inputTensors[index].tensor->GetBuffer(); errno_t status = memcpy_s(curBuffer, dataLength, buffer, dataLength); @@ -89,18 +424,14 @@ OH_NN_ReturnCode Executor::SetInputTensorWithCurrentBuffer(uint32_t index, } -void Executor::SetInputTensorWithNewBuffer(uint32_t index, - std::shared_ptr inputTensor, - const void* inputBuffer, - size_t length, - bool isInnerMem) +void NNExecutor::SetInputTensorWithNewBuffer(uint32_t index, + std::shared_ptr inputTensor, const void* inputBuffer, size_t length, bool isInnerMem) { // Release the memory inside the tensor first, if it is allocated by Executor during SetInput(). if (m_inputTensors.find(index) != m_inputTensors.end()) { if (m_inputTensors[index].isInnerMem) { void* curBuffer = m_inputTensors[index].tensor->GetBuffer(); - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - inputDevice->ReleaseBuffer(curBuffer); + m_device->ReleaseBuffer(curBuffer); } // Set current tensor's buffer to nullptr in case the NNTensor release the driver memory in destruction. m_inputTensors[index].tensor->SetBuffer(nullptr, 0); @@ -115,11 +446,11 @@ void Executor::SetInputTensorWithNewBuffer(uint32_t index, } -OH_NN_ReturnCode Executor::CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const +OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const { std::vector> minInputDims; std::vector> maxInputDims; - auto ret = m_executionPlan->GetInputDimRanges(minInputDims, maxInputDims); + auto ret = m_preparedModel->GetInputDimRanges(minInputDims, maxInputDims); if (ret != OH_NN_SUCCESS) { LOGE("Get the dimension ranges of input %u failed. ErrorCode=%d", index, ret); return ret; @@ -163,7 +494,7 @@ OH_NN_ReturnCode Executor::CheckInputDimRanges(uint32_t index, const OH_NN_Tenso } -OH_NN_ReturnCode Executor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor, const void* buffer, size_t length) +OH_NN_ReturnCode NNExecutor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor, const void* buffer, size_t length) { auto nnRet = CheckInputDimRanges(index, nnTensor); if (nnRet == OH_NN_OPERATION_FORBIDDEN) { @@ -217,8 +548,7 @@ OH_NN_ReturnCode Executor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor * - SetInput() has not been called for the input before. * - The buffer held in m_inputTensors is allocated and set by CreateInputMemory() and SetInputFromMemory(). */ - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - void* inputBuffer = inputDevice->AllocateTensorBuffer(length, inputTensor); + void* inputBuffer = m_device->AllocateTensorBuffer(length, inputTensor); if (inputBuffer == nullptr) { LOGE("SetInput failed, error happened when allocating input device buffer."); return OH_NN_MEMORY_ERROR; @@ -227,7 +557,7 @@ OH_NN_ReturnCode Executor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor errno_t status = memcpy_s(inputBuffer, dataLength, buffer, dataLength); if (status != EOK) { LOGE("SetInput failed, copy data from user buffer failed. Error code: %d.", status); - inputDevice->ReleaseBuffer(inputBuffer); + m_device->ReleaseBuffer(inputBuffer); return OH_NN_MEMORY_ERROR; } @@ -237,7 +567,7 @@ OH_NN_ReturnCode Executor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor } -OH_NN_ReturnCode Executor::SetInputFromMemory(uint32_t index, const OH_NN_Tensor& nnTensor, const OH_NN_Memory& memory) +OH_NN_ReturnCode NNExecutor::SetInputFromMemory(uint32_t index, const OH_NN_Tensor& nnTensor, const OH_NN_Memory& memory) { auto nnRet = CheckInputDimRanges(index, nnTensor); if (nnRet == OH_NN_OPERATION_FORBIDDEN) { @@ -273,15 +603,69 @@ OH_NN_ReturnCode Executor::SetInputFromMemory(uint32_t index, const OH_NN_Tensor return OH_NN_SUCCESS; } +std::shared_ptr NNExecutor::BuildNNTensorFromDesc( + const std::pair, OH_NN_TensorType>& tensorDesc) +{ + std::shared_ptr tensor = CreateSharedPtr(); + if (tensor == nullptr) { + LOGE("BuildNNTensorFromDesc failed, error happened when creating NNTensor."); + return nullptr; + } + + // Build a tensor from nnTensor. + NN_TensorDesc* tensorDescCast = reinterpret_cast(tensorDesc.first.get()); + auto ret = tensor->BuildFromTensorDesc(tensorDescCast); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, please check input nnTensor."); + return nullptr; + } + + OH_NN_Format format; + tensorDesc.first->GetFormat(&format); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, failed to get tensor format from desc."); + return nullptr; + } + tensor->SetFormat(format); + + ret = tensor->SetTensorType(tensorDesc.second); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, failed to set tensor type."); + return nullptr; + } + + if (!CompareAttribute(tensorDesc, *tensor)) { + LOGE("BuildNNTensorFromDesc failed, input has different attributes from the one in the constructed model."); + return nullptr; + } + + const char* name {nullptr}; + ret = tensorDesc.first->GetName(&name); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, failed to get tensor name from desc."); + return nullptr; + } + tensor->SetName(name); + return tensor; +} -OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length) +OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t length) { - if (index >= m_modelOutputs.size()) { + if (index >= m_outputTensorDescs.size()) { LOGE("SetOutput failed, output index is out of range."); return OH_NN_INVALID_PARAMETER; } + if (m_outputTensorDescs[index].first == nullptr) { + LOGE("NNExecutor::SetOutput failed, tensor desc of output %{public}u is nullptr.", index); + return OH_NN_INVALID_PARAMETER; + } - size_t dataLength = m_modelOutputs[index]->GetDataLength(); + size_t dataLength {0}; + auto ret = m_outputTensorDescs[index].first->GetByteSize(&dataLength); + if (ret != OH_NN_SUCCESS) { + LOGE("SetOutputFromMemory failed, failed to get byte size from tensor desc."); + return ret; + } if (length == 0 || length < dataLength) { LOGE("SetOutput failed, the given buffer length is too small to store the output tensor data."); return OH_NN_INVALID_PARAMETER; @@ -290,7 +674,6 @@ OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length // If output tensor does not exist, or inner device buffer size is not enough, // or device buffer is set by SetOutputFromMemory() before, // allocate a new device buffer and set it to output tensor, and update the user buffer. - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); if (m_outputTensors.find(index) != m_outputTensors.end()) { if (m_outputTensors[index].isInnerMem) { size_t curBufferLength = m_outputTensors[index].tensor->GetBufferLength(); @@ -304,17 +687,21 @@ OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length // If current device buffer size is not enough, // release current device buffer and then allocate a new one below. void* curBuffer = m_outputTensors[index].tensor->GetBuffer(); - outputDevice->ReleaseBuffer(curBuffer); + m_device->ReleaseBuffer(curBuffer); } } } else { // If output tensor does not exist, create a new null output tensor. ExeTensor exeTensor; m_outputTensors[index] = exeTensor; - m_outputTensors[index].tensor = m_modelOutputs[index]; + m_outputTensors[index].tensor = BuildNNTensorFromDesc(m_outputTensorDescs[index]); + if (m_outputTensors[index].tensor == nullptr) { + LOGE("SetOutput failed, failed to build nntensor from desc."); + return OH_NN_NULL_PTR; + } } - void* deviceOutputBuffer = outputDevice->AllocateTensorBuffer(length, m_outputTensors[index].tensor); + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[index].first); if (deviceOutputBuffer == nullptr) { LOGE("SetOutput failed, allocating output device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -329,14 +716,23 @@ OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length } -OH_NN_ReturnCode Executor::SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory) +OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory) { - if (index >= m_modelOutputs.size()) { + if (index >= m_outputTensorDescs.size()) { LOGE("SetOutputFromMemory failed, output index is out of range."); return OH_NN_INVALID_PARAMETER; } + if (m_outputTensorDescs[index].first == nullptr) { + LOGE("NNExecutor::SetOutputFromMemory failed, tensor desc of output %{public}u is nullptr.", index); + return OH_NN_INVALID_PARAMETER; + } - size_t dataLength = m_modelOutputs[index]->GetDataLength(); + size_t dataLength {0}; + auto ret = m_outputTensorDescs[index].first->GetByteSize(&dataLength); + if (ret != OH_NN_SUCCESS) { + LOGE("SetOutputFromMemory failed, failed to get byte size from tensor desc."); + return ret; + } if (memory.length == 0 || memory.length < dataLength) { LOGE("SetOutputFromMemory failed, the memory is too small to store the output tensor data."); return OH_NN_INVALID_PARAMETER; @@ -346,14 +742,17 @@ OH_NN_ReturnCode Executor::SetOutputFromMemory(uint32_t index, const OH_NN_Memor if (m_outputTensors[index].isInnerMem) { // If it is inner buffer, releate it void* curBuffer = m_outputTensors[index].tensor->GetBuffer(); - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - outputDevice->ReleaseBuffer(curBuffer); + m_device->ReleaseBuffer(curBuffer); } } else { // If output tensor does not exist, create a new null output tensor. ExeTensor exeTensor; m_outputTensors[index] = exeTensor; - m_outputTensors[index].tensor = m_modelOutputs[index]; + m_outputTensors[index].tensor = BuildNNTensorFromDesc(m_outputTensorDescs[index]); + if (m_outputTensors[index].tensor == nullptr) { + LOGE("SetOutputFromMemory failed, failed to build nntensor from desc."); + return OH_NN_NULL_PTR; + } } // Set the output tensor with memory @@ -365,42 +764,19 @@ OH_NN_ReturnCode Executor::SetOutputFromMemory(uint32_t index, const OH_NN_Memor return OH_NN_SUCCESS; } - -OH_NN_ReturnCode Executor::GetOutputShape(uint32_t index, int32_t** dimensions, uint32_t& dimensionCount) +OH_NN_ReturnCode NNExecutor::CreateInputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) { - if (!m_isRun) { - LOGE("GetOutputShape failed, cannot get output dimensions before Run."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (index >= m_modelOutputs.size()) { - LOGE("GetOutputShape failed, output index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - if (m_outputTensors.find(index) == m_outputTensors.end()) { - LOGE("GetOutputShape failed, output has not been set. Output index: %u.", index); + if (index >= m_inputTensorDescs.size()) { + LOGE("CreateInputMemory failed, input index is out of range."); return OH_NN_INVALID_PARAMETER; } - - m_outputDimensions[index] = m_outputTensors[index].tensor->GetDimensions(); - *dimensions = m_outputDimensions[index].data(); - dimensionCount = m_outputDimensions[index].size(); - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::CreateInputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) -{ - if (index >= m_modelInputs.size()) { - LOGE("CreateInputMemory failed, input index is out of range."); + if (m_inputTensorDescs[index].first == nullptr) { + LOGE("CreateInputMemory failed, tensor desc of input %{public}u is nullptr.", index); return OH_NN_INVALID_PARAMETER; } // Allocate device buffer - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - void* deviceInputBuffer = inputDevice->AllocateTensorBuffer(length, m_modelInputs[index]); + void* deviceInputBuffer = m_device->AllocateTensorBuffer(length, m_inputTensorDescs[index].first); if (deviceInputBuffer == nullptr) { LOGE("CreateInputMemory failed, allocating intput device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -409,7 +785,7 @@ OH_NN_ReturnCode Executor::CreateInputMemory(uint32_t index, size_t length, OH_N *memory = new(std::nothrow) OH_NN_Memory{deviceInputBuffer, length}; if (*memory == nullptr) { LOGE("CreateInputMemory failed, constructing OH_NN_Memory failed."); - inputDevice->ReleaseBuffer(deviceInputBuffer); + m_device->ReleaseBuffer(deviceInputBuffer); return OH_NN_MEMORY_ERROR; } @@ -420,9 +796,9 @@ OH_NN_ReturnCode Executor::CreateInputMemory(uint32_t index, size_t length, OH_N } -OH_NN_ReturnCode Executor::DestroyInputMemory(uint32_t index, OH_NN_Memory** memory) +OH_NN_ReturnCode NNExecutor::DestroyInputMemory(uint32_t index, OH_NN_Memory** memory) { - if (index >= m_modelInputs.size()) { + if (index >= m_inputTensorDescs.size()) { LOGE("DestroyInputMemory failed, input index is out of range."); return OH_NN_INVALID_PARAMETER; } @@ -439,8 +815,7 @@ OH_NN_ReturnCode Executor::DestroyInputMemory(uint32_t index, OH_NN_Memory** mem return OH_NN_INVALID_PARAMETER; } - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - auto ret = inputDevice->ReleaseBuffer((*memory)->data); + auto ret = m_device->ReleaseBuffer((*memory)->data); if (ret != OH_NN_SUCCESS) { LOGE("Release input buffer failed."); return ret; @@ -454,16 +829,19 @@ OH_NN_ReturnCode Executor::DestroyInputMemory(uint32_t index, OH_NN_Memory** mem } -OH_NN_ReturnCode Executor::CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) +OH_NN_ReturnCode NNExecutor::CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) { - if (index >= m_modelOutputs.size()) { + if (index >= m_outputTensorDescs.size()) { LOGE("CreateOutputMemory failed, output index is out of range."); return OH_NN_INVALID_PARAMETER; } + if (m_outputTensorDescs[index].first == nullptr) { + LOGE("NNExecutor::CreateOutputMemory failed, tensor desc of output %{public}u is nullptr.", index); + return OH_NN_INVALID_PARAMETER; + } // Allocate device buffer - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - void* deviceOutputBuffer = outputDevice->AllocateTensorBuffer(length, m_modelOutputs[index]); + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[index].first); if (deviceOutputBuffer == nullptr) { LOGE("CreateOutputMemory failed, allocating output device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -472,7 +850,7 @@ OH_NN_ReturnCode Executor::CreateOutputMemory(uint32_t index, size_t length, OH_ *memory = new(std::nothrow) OH_NN_Memory{deviceOutputBuffer, length}; if (*memory == nullptr) { LOGE("CreateOutputMemory failed, constructing OH_NN_Memory failed."); - outputDevice->ReleaseBuffer(deviceOutputBuffer); + m_device->ReleaseBuffer(deviceOutputBuffer); return OH_NN_MEMORY_ERROR; } @@ -483,9 +861,9 @@ OH_NN_ReturnCode Executor::CreateOutputMemory(uint32_t index, size_t length, OH_ } -OH_NN_ReturnCode Executor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory) +OH_NN_ReturnCode NNExecutor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory) { - if (index >= m_modelOutputs.size()) { + if (index >= m_outputTensorDescs.size()) { LOGE("DestroyOutputMemory failed, output index is out of range."); return OH_NN_INVALID_PARAMETER; } @@ -502,8 +880,7 @@ OH_NN_ReturnCode Executor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** me return OH_NN_INVALID_PARAMETER; } - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - auto ret = outputDevice->ReleaseBuffer((*memory)->data); + auto ret = m_device->ReleaseBuffer((*memory)->data); if (ret != OH_NN_SUCCESS) { LOGE("Release output buffer failed."); return ret; @@ -516,15 +893,64 @@ OH_NN_ReturnCode Executor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** me return OH_NN_SUCCESS; } +OH_NN_ReturnCode NNExecutor::Run(const std::vector>& inputTensors, + std::vector>& outputTensors) +{ + OH_NN_ReturnCode ret {OH_NN_FAILED}; + IOTensor tensor; + std::vector inputIOTensors; + size_t inputSize = inputTensors.size(); + size_t outputSize = outputTensors.size(); + for (size_t i = 0; i < inputSize; ++i) { + inputTensors[i]->ConvertToIOTensor(tensor); + inputIOTensors.emplace_back(std::move(tensor)); + } -OH_NN_ReturnCode Executor::Run() + std::vector outputIOTensors; + for (size_t i = 0; i < outputSize; ++i) { + outputTensors[i]->ConvertToIOTensor(tensor); + outputIOTensors.emplace_back(std::move(tensor)); + } + + std::vector> outputsDims; + std::vector isSufficientDataBuffer; + ret = m_preparedModel->Run(inputIOTensors, outputIOTensors, outputsDims, isSufficientDataBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("PrepardModel Run() failed."); + return ret; + } + + // Set the output NNTensor's dimensions from output IOTensor if it is dynamic. + // NNTensor::SetDimensions will check if the tensor buffer is enough for the new dimensions. + if (outputsDims.size() != outputSize) { + LOGE("ExecutionPlan run failed, size of outputsDims is not equal to outputTensors."); + return OH_NN_INVALID_PARAMETER; + } + for (size_t i = 0; i < outputSize; ++i) { + ret = outputTensors[i]->SetDimensions(outputsDims[i]); + if (ret != OH_NN_SUCCESS) { + LOGE("Run failed, error happened when setting output tensor's dimensions, output id: %zu.", i); + return ret; + } + ret = m_outputTensorDescs[i].first->SetShape(outputsDims[i].data(), outputsDims[i].size()); + if (ret != OH_NN_SUCCESS) { + LOGE("Run failed, error happened when setting inner output tensor's dimensions," + " output id: %zu.", i); + return ret; + } + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNExecutor::Run() { NNRT_TRACE_NAME("Execution"); - if (m_modelInputs.size() != m_inputTensors.size()) { + if (m_inputTensorDescs.size() != m_inputTensors.size()) { LOGE("Run failed, some input tensors have not been set."); return OH_NN_INVALID_PARAMETER; } - if (m_modelOutputs.size() != m_outputTensors.size()) { + if (m_outputTensorDescs.size() != m_outputTensors.size()) { LOGE("Run failed, some output tensors have not been set."); return OH_NN_INVALID_PARAMETER; } @@ -542,7 +968,7 @@ OH_NN_ReturnCode Executor::Run() } // Predict - auto ret = m_executionPlan->Run(inputTensors, outputTensors); + auto ret = Run(inputTensors, outputTensors); if (ret != OH_NN_SUCCESS) { LOGE("Run failed, error happened when executing the inference."); return ret; @@ -577,13 +1003,11 @@ OH_NN_ReturnCode Executor::Run() return OH_NN_SUCCESS; } -Executor::~Executor() +NNExecutor::~NNExecutor() { - std::shared_ptr inputDevice; for (auto& it : m_inputTensors) { - inputDevice = m_executionPlan->GetInputDevice(); if ((it.second).isInnerMem) { - inputDevice->ReleaseBuffer((it.second).tensor->GetBuffer()); + m_device->ReleaseBuffer((it.second).tensor->GetBuffer()); } (it.second).tensor->SetBuffer(nullptr, 0); (it.second).tensor.reset(); @@ -591,11 +1015,9 @@ Executor::~Executor() } m_inputTensors.clear(); - std::shared_ptr outputDevice; for (auto& it : m_outputTensors) { - outputDevice = m_executionPlan->GetOutputDevice(); if ((it.second).isInnerMem) { - outputDevice->ReleaseBuffer((it.second).tensor->GetBuffer()); + m_device->ReleaseBuffer((it.second).tensor->GetBuffer()); } (it.second).tensor->SetBuffer(nullptr, 0); (it.second).tensor.reset(); @@ -612,10 +1034,6 @@ Executor::~Executor() it.second.clear(); } m_outputCreatedMem.clear(); - - m_outputDimensions.clear(); - m_modelInputs.clear(); - m_modelOutputs.clear(); } -} // namespace NeuralNetworkRuntime -} // namespace OHOS +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h new file mode 100644 index 0000000..bf011c7 --- /dev/null +++ b/frameworks/native/nnexecutor.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_NNEXECUTOR_H +#define NEURAL_NETWORK_RUNTIME_NNEXECUTOR_H + +#include "executor.h" +#include "device.h" +#include "prepared_model.h" +#include "nn_tensor.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class NNExecutor : public Executor { +public: + NNExecutor(size_t backendID, + std::shared_ptr device, + std::shared_ptr preparedModel, + const std::vector, OH_NN_TensorType>>& inputTensorDescs, + const std::vector, OH_NN_TensorType>>& outputTensorDescs); + virtual ~NNExecutor(); + + virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, + size_t** minInputDims, + size_t** maxInputDims, + size_t* shapeNum) const override; + virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) const override; + + virtual size_t GetInputNum() const override; + virtual size_t GetOutputNum() const override; + virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) const override; + virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) const override; + + virtual OH_NN_ReturnCode SetOnRunDone(NN_OnRunDone onRunDone) override; + virtual OH_NN_ReturnCode SetOnServiceDied(NN_OnServiceDied onServiceDied) override; + virtual OH_NN_ReturnCode RunSync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize) override; + virtual OH_NN_ReturnCode RunAsync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize, + int32_t timeout, + void* userData) override; + virtual size_t GetBackendID() override; + + // The following APIs are compatible with older versions + OH_NN_ReturnCode SetInput(uint32_t index, const OH_NN_Tensor& nnTensor, const void* buffer, size_t length); + OH_NN_ReturnCode SetInputFromMemory(uint32_t index, const OH_NN_Tensor& nnTensor, const OH_NN_Memory& memory); + OH_NN_ReturnCode SetOutput(uint32_t index, void* buffer, size_t length); + OH_NN_ReturnCode SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory); + + OH_NN_ReturnCode CreateInputMemory(uint32_t index, size_t length, OH_NN_Memory** memory); + OH_NN_ReturnCode CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory); + OH_NN_ReturnCode DestroyInputMemory(uint32_t index, OH_NN_Memory** memory); + OH_NN_ReturnCode DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory); + + OH_NN_ReturnCode Run(); + +private: + OH_NN_ReturnCode CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize); + + // The following APIs are compatible with older versions + OH_NN_ReturnCode Run(const std::vector>& inputTensors, + std::vector>& outputTensors); + bool CompareAttribute( + const std::pair, OH_NN_TensorType>& tensorDesc, const NNTensor& tensor) const; + std::shared_ptr BuildNNTensorFromDesc( + const std::pair, OH_NN_TensorType>& tensorDesc); + OH_NN_ReturnCode BuildInputTensor(uint32_t index, const OH_NN_Tensor& nnTensor, + std::shared_ptr inputTensor) const; + OH_NN_ReturnCode SetInputTensorWithCurrentBuffer(uint32_t index, std::shared_ptr inputTensor, + const void* buffer, size_t dataLength, size_t curBufferLength); + void SetInputTensorWithNewBuffer(uint32_t index, std::shared_ptr inputTensor, + const void* inputBuffer, size_t length, bool isInnerMem); + OH_NN_ReturnCode CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const; + +private: + size_t m_backendID {0}; + std::shared_ptr m_device {nullptr}; + std::shared_ptr m_preparedModel {nullptr}; + std::vector, OH_NN_TensorType>> m_inputTensorDescs; + std::vector, OH_NN_TensorType>> m_outputTensorDescs; + + // The following parameters are provided for compatibility with older versions + struct ExeTensor { + std::shared_ptr tensor; + void* userBuffer; + size_t userBufferLength; + bool isInnerMem; + }; + bool m_isRun {false}; + std::unordered_map m_inputTensors; + std::unordered_map m_outputTensors; + std::unordered_map> m_inputCreatedMem; + std::unordered_map> m_outputCreatedMem; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_NNEXECUTOR_H diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp new file mode 100644 index 0000000..dfbf242 --- /dev/null +++ b/frameworks/native/nntensor.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "backend_manager.h" +#include "nnbackend.h" +#include "nntensor.h" +#include "common/log.h" +#include +#include +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +NNTensor2_0::~NNTensor2_0() +{ + if (!m_isUserData) { + ReleaseMemory(); + } + + delete m_tensorDesc; + m_tensorDesc = nullptr; + + m_data = nullptr; + m_fd = 0; + m_offset = 0; + m_size = 0; + m_isUserData = false; +} + +OH_NN_ReturnCode NNTensor2_0::SetTensorDesc(const TensorDesc* tensorDesc) +{ + m_tensorDesc = new (std::nothrow) TensorDesc(); + if (m_tensorDesc == nullptr) { + LOGE("[NNTensor2_0] SetTensorDesc failed, failed to create desc for tensor."); + return OH_NN_NULL_PTR; + } + + // Copy the member attributes to new tensor description + *m_tensorDesc = *tensorDesc; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNTensor2_0::CreateData() +{ + if (m_data != nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_data has been created before."); + return OH_NN_FAILED; + } + if (m_tensorDesc == nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_tensorDesc is nullptr."); + return OH_NN_NULL_PTR; + } + + size_t byteSize = 0; + auto ret = m_tensorDesc->GetByteSize(&byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to get byte size from tensorDesc."); + return ret; + } + if (byteSize > ALLOCATE_BUFFER_LIMIT) { + LOGE("NNTensor2_0::CreateData failed, Invalid buffer size, " + "it must greater than 0 and less than 1Gb. length=%{public}zu", byteSize); + return OH_NN_INVALID_PARAMETER; + } + + ret = AllocateMemory(byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to allocate memory."); + return ret; + } + m_isUserData = false; + return OH_NN_SUCCESS; +} +OH_NN_ReturnCode NNTensor2_0::CreateData(size_t size) +{ + if (m_data != nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_data has been created before."); + return OH_NN_FAILED; + } + if (m_tensorDesc == nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_tensorDesc is nullptr."); + return OH_NN_NULL_PTR; + } + if (size > ALLOCATE_BUFFER_LIMIT) { + LOGE("NNTensor2_0::CreateData failed, Invalid buffer size, " + "it must greater than 0 and less than 1Gb. length=%{public}zu", size); + return OH_NN_INVALID_PARAMETER; + } + size_t byteSize = 0; + auto ret = m_tensorDesc->GetByteSize(&byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to get byte size from tensorDesc."); + return ret; + } + if (size < byteSize) { + LOGE("NNTensor2_0::CreateData failed, size:%{public}zu must be larger than " + "or equal to byte size:%{public}zu.", size, byteSize); + return OH_NN_INVALID_PARAMETER; + } + + ret = AllocateMemory(size); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to allocate memory."); + return ret; + } + m_isUserData = false; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNTensor2_0::CreateData(int fd, size_t size, size_t offset) +{ + if (m_data != nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_data has been created before."); + return OH_NN_FAILED; + } + if (m_tensorDesc == nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_tensorDesc is nullptr."); + return OH_NN_NULL_PTR; + } + + size_t byteSize = 0; + auto ret = m_tensorDesc->GetByteSize(&byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CreateData failed, failed to get byte size from tensorDesc."); + return ret; + } + if (fd < 0) { + LOGE("NNTensor2_0::CreateData failed, fd is less than 0."); + return OH_NN_INVALID_PARAMETER; + } + if (size == 0) { + LOGE("NNTensor2_0::CreateData failed, size is zero."); + return OH_NN_INVALID_PARAMETER; + } + if (size < offset) { + LOGE("NNTensor2_0::CreateData failed, size is smaller than offset."); + return OH_NN_INVALID_PARAMETER; + } + if ((size - offset) < byteSize) { + LOGE("NNTensor2_0::CreateData failed, size of fd is insufficient."); + return OH_NN_INVALID_PARAMETER; + } + + m_data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); + if (m_data == MAP_FAILED) { + LOGE("NNTensor2_0::AllocateMemory failed, Map fd to address failed: %{public}s.", strerror(errno)); + m_data = nullptr; + return OH_NN_MEMORY_ERROR; + } + + m_fd = fd; + m_size = size; + m_offset = offset; + m_isUserData = true; + return OH_NN_SUCCESS; +} + +TensorDesc* NNTensor2_0::GetTensorDesc() const +{ + return m_tensorDesc; +} + +void* NNTensor2_0::GetData() const +{ + return m_data; +} + +int NNTensor2_0::GetFd() const +{ + return m_fd; +} + +size_t NNTensor2_0::GetSize() const +{ + return m_size; +} + +size_t NNTensor2_0::GetOffset() const +{ + return m_offset; +} + +OH_NN_ReturnCode NNTensor2_0::AllocateMemory(size_t length) +{ + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(m_backendID); + if (backend == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, failed to get backend of %{public}zu.", m_backendID); + return OH_NN_NULL_PTR; + } + + auto* nnBackend = reinterpret_cast(backend.get()); + if (nnBackend == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, failed to convert backend to nnbackend."); + return OH_NN_NULL_PTR; + } + auto device = nnBackend->GetDevice(); + if (device == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, device of nnbackend is nullptr."); + return OH_NN_NULL_PTR; + } + int fd = 0; + auto oldRet = device->AllocateBuffer(length, fd); + if (oldRet != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::AllocateMemory failed, failed to allocate buffer."); + return OH_NN_MEMORY_ERROR; + } + if (fd < 0) { + LOGE("NNTensor2_0::AllocateMemory failed, fd must greater than 0."); + return OH_NN_INVALID_PARAMETER; + } + + m_data = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (m_data == MAP_FAILED) { + LOGE("NNTensor2_0::AllocateMemory failed, Map fd to address failed: %{public}s.", strerror(errno)); + m_data = nullptr; + return OH_NN_MEMORY_ERROR; + } + m_fd = fd; + m_offset = 0; + m_size = length; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNTensor2_0::ReleaseMemory() +{ + if (m_size == 0 || m_data == nullptr) { + return OH_NN_SUCCESS; + } + if (m_fd < 0) { + LOGE("NNTensor2_0::ReleaseMemory failed, m_fd must greater than 0."); + return OH_NN_INVALID_PARAMETER; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(m_backendID); + if (backend == nullptr) { + LOGE("NNTensor2_0::ReleaseMemory failed, failed to get backend of %{public}zu.", m_backendID); + return OH_NN_NULL_PTR; + } + + auto* nnrtBackend = reinterpret_cast(backend.get()); + if (nnrtBackend == nullptr) { + LOGE("NNTensor2_0::ReleaseMemory failed, failed to convert backend to nnbackend."); + return OH_NN_NULL_PTR; + } + auto device = nnrtBackend->GetDevice(); + if (device == nullptr) { + LOGE(""); + return OH_NN_NULL_PTR; + } + auto oldRet = device->ReleaseBuffer(m_fd, m_size); + if (oldRet != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::ReleaseMemory failed, failed to release buffer."); + return OH_NN_MEMORY_ERROR; + } + + auto unmapResult = munmap(m_data, m_size); + if (unmapResult != 0) { + LOGE("NNTensor2_0::ReleaseMemory failed. Please try again."); + return OH_NN_MEMORY_ERROR; + } + m_data = nullptr; + m_size = 0; + + if (close(m_fd) != 0) { + LOGE("NNTensor2_0::ReleaseMemory failed. fd=%{public}d", m_fd); + return OH_NN_MEMORY_ERROR; + } + m_fd = 0; + + return OH_NN_SUCCESS; +} + +size_t NNTensor2_0::GetBackendID() const +{ + return m_backendID; +} + +bool NNTensor2_0::CheckTensorData() const +{ + if (m_tensorDesc == nullptr) { + LOGE("NNTensor2_0::CheckTensorData failed, m_tensorDesc is nullptr."); + return false; + } + + size_t byteSize = 0; + auto ret = m_tensorDesc->GetByteSize(&byteSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CheckTensorData failed, failed to get byte size from tensorDesc."); + return false; + } + if ((m_size - m_offset) < byteSize) { + LOGE("NNTensor2_0::CheckTensorData failed, m_size is less than byte size."); + return false; + } + + if (m_data == nullptr) { + LOGE("NNTensor2_0::CheckTensorData failed, m_data is nullptr."); + return false; + } + + if (m_fd < 0) { + LOGE("NNTensor2_0::CheckTensorData failed, m_fd is less than zero."); + return false; + } + + return true; +} + +OH_NN_ReturnCode NNTensor2_0::CheckDimRanges( + const std::vector& minDimRanges, const std::vector& maxDimRanges) const +{ + if (m_tensorDesc == nullptr) { + LOGE("NNTensor2_0::CheckInputDimRanges failed, m_tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + int32_t* shape = nullptr; + size_t shapeSize = 0; + auto ret = m_tensorDesc->GetShape(&shape, &shapeSize); + if (ret != OH_NN_SUCCESS) { + LOGE("NNTensor2_0::CheckInputDimRanges failed, failed to get shape from desc."); + return ret; + } + for (size_t j = 0; j < shapeSize; ++j) { + // Dimensions cannot be negative + if (shape[j] < 0) { + LOGE("Dimension %{public}zu is %{public}d.", j, shape[j]); + return OH_NN_INVALID_PARAMETER; + } + uint32_t dim = static_cast(shape[j]); + if (dim < minDimRanges[j] || dim > maxDimRanges[j]) { + LOGE("Dimension %{public}zu is %{public}u, which is out of range " + "[%{public}u, %{public}u]", j, dim, minDimRanges[j], maxDimRanges[j]); + return OH_NN_INVALID_PARAMETER; + } + } + + return OH_NN_SUCCESS; +} +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/nntensor.h b/frameworks/native/nntensor.h new file mode 100644 index 0000000..24ba9fc --- /dev/null +++ b/frameworks/native/nntensor.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_NNTENSOR_H +#define NEURAL_NETWORK_RUNTIME_NNTENSOR_H + +#include "tensor.h" +#include + +namespace OHOS { +namespace NeuralNetworkRuntime { +class NNTensor2_0 : public Tensor { +public: + NNTensor2_0(size_t backendID) : m_backendID(backendID) {} + virtual ~NNTensor2_0(); + + OH_NN_ReturnCode SetTensorDesc(const TensorDesc* tensorDesc) override; + OH_NN_ReturnCode CreateData() override; + OH_NN_ReturnCode CreateData(size_t size) override; + OH_NN_ReturnCode CreateData(int fd, size_t size, size_t offset) override; + + TensorDesc* GetTensorDesc() const override; + void* GetData() const override; + int GetFd() const override; + size_t GetSize() const override; + size_t GetOffset() const override; + size_t GetBackendID() const override; + + bool CheckTensorData() const; + + OH_NN_ReturnCode CheckDimRanges(const std::vector& minDimRanges, + const std::vector& maxDimRanges) const; + +private: + OH_NN_ReturnCode AllocateMemory(size_t length); + OH_NN_ReturnCode ReleaseMemory(); + +private: + size_t m_backendID {0}; + TensorDesc* m_tensorDesc {nullptr}; + void* m_data {nullptr}; + int m_fd {0}; + size_t m_size {0}; + size_t m_offset {0}; + bool m_isUserData {false}; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_NNTENSOR_H \ No newline at end of file diff --git a/frameworks/native/ops/conv2d_builder.cpp b/frameworks/native/ops/conv2d_builder.cpp index df23946..1ba4d51 100644 --- a/frameworks/native/ops/conv2d_builder.cpp +++ b/frameworks/native/ops/conv2d_builder.cpp @@ -17,6 +17,7 @@ #include "frameworks/native/transform.h" #include "frameworks/native/validation.h" +#include "ops_validation.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops/conv2d_transpose_builder.cpp b/frameworks/native/ops/conv2d_transpose_builder.cpp index 9111b55..5318618 100644 --- a/frameworks/native/ops/conv2d_transpose_builder.cpp +++ b/frameworks/native/ops/conv2d_transpose_builder.cpp @@ -17,6 +17,7 @@ #include "frameworks/native/transform.h" #include "frameworks/native/validation.h" +#include "ops_validation.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops/depthwise_conv2d_native_builder.cpp b/frameworks/native/ops/depthwise_conv2d_native_builder.cpp index d1fbeb8..f7d5f91 100644 --- a/frameworks/native/ops/depthwise_conv2d_native_builder.cpp +++ b/frameworks/native/ops/depthwise_conv2d_native_builder.cpp @@ -17,6 +17,7 @@ #include "frameworks/native/transform.h" #include "frameworks/native/validation.h" +#include "ops_validation.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops/ops_validation.cpp b/frameworks/native/ops/ops_validation.cpp new file mode 100644 index 0000000..988ffd8 --- /dev/null +++ b/frameworks/native/ops/ops_validation.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #include "mindir_types.h" // todo + +#include "ops_validation.h" +#include "mindir_types.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +namespace Validation { +bool ValidatePadMode(int8_t padMode) +{ + if ((padMode >= mindspore::lite::PAD_MODE_PAD) && (padMode <= mindspore::lite::PAD_MODE_VALID)) { + return true; + } + return false; +} +} // namespace Validation +} // namespace NeuralNetworkRuntime +} // namespace OHOS diff --git a/frameworks/native/ops/ops_validation.h b/frameworks/native/ops/ops_validation.h new file mode 100644 index 0000000..91c5d79 --- /dev/null +++ b/frameworks/native/ops/ops_validation.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_OPS_VALIDATION_H +#define NEURAL_NETWORK_RUNTIME_OPS_VALIDATION_H + +#include + +namespace OHOS { +namespace NeuralNetworkRuntime { +namespace Validation { +bool ValidatePadMode(int8_t padMode); +} // namespace Validation +} // NeuralNetworkRuntime +} // namespace OHOS + +#endif // NEURAL_NETWORK_RUNTIME_OPS_VALIDATION_H diff --git a/frameworks/native/ops/pooling_builder.cpp b/frameworks/native/ops/pooling_builder.cpp index 7338ed4..df25ea8 100644 --- a/frameworks/native/ops/pooling_builder.cpp +++ b/frameworks/native/ops/pooling_builder.cpp @@ -17,6 +17,7 @@ #include "frameworks/native/transform.h" #include "frameworks/native/validation.h" +#include "ops_validation.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops/strided_slice_builder.cpp b/frameworks/native/ops/strided_slice_builder.cpp index 4f25d85..5a5873b 100644 --- a/frameworks/native/ops/strided_slice_builder.cpp +++ b/frameworks/native/ops/strided_slice_builder.cpp @@ -17,7 +17,7 @@ #include "mindir.h" -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops_builder.cpp b/frameworks/native/ops_builder.cpp index f0fce4c..806e946 100644 --- a/frameworks/native/ops_builder.cpp +++ b/frameworks/native/ops_builder.cpp @@ -62,11 +62,11 @@ OH_NN_ReturnCode OpsBuilder::CheckIOIndex(const std::vector& inputsInd size_t inputsIndexSize = inputsIndex.size(); size_t outputIndexSize = outputsIndex.size(); if (inputsIndexSize != inputNum) { - LOGE("The number of index of inputs is %zu don't equal to %zu.", inputsIndexSize, inputNum); + LOGE("The number of index of inputs is %{public}zu don't equal to %{public}zu.", inputsIndexSize, inputNum); return OH_NN_INVALID_PARAMETER; } if (outputIndexSize != outputNum) { - LOGE("The number of index of outputs is %zu don't equal to %zu.", outputIndexSize, outputNum); + LOGE("The number of index of outputs is %{public}zu don't equal to %zu.", outputIndexSize, outputNum); return OH_NN_INVALID_PARAMETER; } diff --git a/frameworks/native/ops_builder.h b/frameworks/native/ops_builder.h index ca2f70c..ecc82f0 100644 --- a/frameworks/native/ops_builder.h +++ b/frameworks/native/ops_builder.h @@ -21,7 +21,7 @@ #include "nn_tensor.h" #include "common/log.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/ops_registry.h b/frameworks/native/ops_registry.h index 29171cb..4908483 100644 --- a/frameworks/native/ops_registry.h +++ b/frameworks/native/ops_registry.h @@ -21,7 +21,7 @@ #include #include "ops_builder.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/prepared_model.h b/frameworks/native/prepared_model.h index 7e64f08..5c6304a 100644 --- a/frameworks/native/prepared_model.h +++ b/frameworks/native/prepared_model.h @@ -18,7 +18,7 @@ #include -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "cpp_type.h" namespace OHOS { @@ -35,6 +35,11 @@ public: std::vector>& outputsDims, std::vector& isOutputBufferEnough) = 0; + virtual OH_NN_ReturnCode Run(const std::vector& inputs, + const std::vector& outputs, + std::vector>& outputsDims, + std::vector& isOutputBufferEnough) = 0; + virtual OH_NN_ReturnCode GetInputDimRanges(std::vector>& minInputDims, std::vector>& maxInputDims) { diff --git a/frameworks/native/quant_param.cpp b/frameworks/native/quant_param.cpp new file mode 100644 index 0000000..f5a48e5 --- /dev/null +++ b/frameworks/native/quant_param.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "quant_param.h" + +#include "common/log.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +void QuantParams::SetScales(std::vector scales) +{ + m_scales = scales; +} + +void QuantParams::SetZeroPoints(std::vector zeroPoints) +{ + m_zeroPoints = zeroPoints; +} + +void QuantParams::SetNumBits(std::vector numBits) +{ + m_numBits = numBits; +} + +std::vector QuantParams::GetScales() const +{ + return m_scales; +} + +std::vector QuantParams::GetZeroPoints() const +{ + return m_zeroPoints; +} + +std::vector QuantParams::GetNumBits() const +{ + return m_numBits; +} + +OH_NN_ReturnCode QuantParams::CopyToCompat(std::vector& compatQuantParams) const +{ + if ((m_scales.size() != m_zeroPoints.size()) || (m_zeroPoints.size() != m_numBits.size())) { + LOGE("CopyToCompat failed, the size of scales(%zu), zeroPoints(%zu) and numBits(%zu) are not equal.", m_scales.size(), m_zeroPoints.size(), m_numBits.size()); + return OH_NN_INVALID_PARAMETER; + } + + size_t quantCount = m_scales.size(); + for (size_t i = 0; i < quantCount; i++) { + compatQuantParams.push_back({ + .numBits = m_numBits[i], + .scale = m_scales[i], + .zeroPoint = m_zeroPoints[i], + }); + } + + return OH_NN_SUCCESS; +} +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/execution_plan.h b/frameworks/native/quant_param.h similarity index 42% rename from frameworks/native/execution_plan.h rename to frameworks/native/quant_param.h index 54f4648..59bc5e9 100644 --- a/frameworks/native/execution_plan.h +++ b/frameworks/native/quant_param.h @@ -13,36 +13,36 @@ * limitations under the License. */ -#ifndef NEURAL_NETWORK_RUNTIME_EXECUTION_PLAN_H -#define NEURAL_NETWORK_RUNTIME_EXECUTION_PLAN_H +#ifndef NEURAL_NETWORK_RUNTIME_QUANT_PARAMS_H +#define NEURAL_NETWORK_RUNTIME_QUANT_PARAMS_H -#include "frameworks/native/nn_tensor.h" -#include "interfaces/kits/c/neural_network_runtime_type.h" -#include "prepared_model.h" -#include "device.h" +#include +#include "cpp_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -class ExecutionPlan { +class QuantParams { public: - ExecutionPlan(std::shared_ptr preparedModel, std::shared_ptr device) - : m_preparedModel(preparedModel), - m_device(device) {}; - - OH_NN_ReturnCode GetInputDimRanges(std::vector>& minInputDims, - std::vector>& maxInputDims); + QuantParams() = default; + ~QuantParams() = default; - OH_NN_ReturnCode Run(const std::vector>& inputTensors, - std::vector>& outputTensors); + void SetScales(std::vector scales); + void SetZeroPoints(std::vector zeroPoints); + void SetNumBits(std::vector numBits); - std::shared_ptr GetInputDevice() const; - std::shared_ptr GetOutputDevice() const; + std::vector GetScales() const; + std::vector GetZeroPoints() const; + std::vector GetNumBits() const; + + OH_NN_ReturnCode CopyToCompat(std::vector& compatQuantParams) const; private: - std::shared_ptr m_preparedModel {nullptr}; - std::shared_ptr m_device {nullptr}; + std::vector m_scales; + std::vector m_zeroPoints; + std::vector m_numBits; }; } // namespace NeuralNetworkRuntime } // namespace OHOS -#endif \ No newline at end of file +#endif // NEURAL_NETWORK_RUNTIME_QUANT_PARAMS_H \ No newline at end of file diff --git a/frameworks/native/tensor.h b/frameworks/native/tensor.h new file mode 100644 index 0000000..0ab606f --- /dev/null +++ b/frameworks/native/tensor.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_TENSOR_H +#define NEURAL_NETWORK_RUNTIME_TENSOR_H + +#include "tensor_desc.h" +#include + +namespace OHOS { +namespace NeuralNetworkRuntime { +class Tensor { +public: + Tensor() = default; + Tensor(size_t backendID); + virtual ~Tensor() = default; + + virtual OH_NN_ReturnCode SetTensorDesc(const TensorDesc* tensorDesc) = 0; + virtual OH_NN_ReturnCode CreateData() = 0; + virtual OH_NN_ReturnCode CreateData(size_t size) = 0; + virtual OH_NN_ReturnCode CreateData(int fd, size_t size, size_t offset) = 0; + + virtual TensorDesc* GetTensorDesc() const = 0; + virtual void* GetData() const = 0; + virtual int GetFd() const = 0; + virtual size_t GetSize() const = 0; + virtual size_t GetOffset() const = 0; + virtual size_t GetBackendID() const = 0; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_TENSOR_H \ No newline at end of file diff --git a/frameworks/native/tensor_desc.cpp b/frameworks/native/tensor_desc.cpp new file mode 100644 index 0000000..34c3ce4 --- /dev/null +++ b/frameworks/native/tensor_desc.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tensor_desc.h" +#include "validation.h" +#include "common/log.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +const uint32_t BIT8_TO_BYTE = 1; +const uint32_t BIT16_TO_BYTE = 2; +const uint32_t BIT32_TO_BYTE = 4; +const uint32_t BIT64_TO_BYTE = 8; + +uint32_t GetTypeSize(OH_NN_DataType type) +{ + switch (type) { + case OH_NN_BOOL: + return sizeof(bool); + case OH_NN_INT8: + case OH_NN_UINT8: + return BIT8_TO_BYTE; + case OH_NN_INT16: + case OH_NN_UINT16: + case OH_NN_FLOAT16: + return BIT16_TO_BYTE; + case OH_NN_INT32: + case OH_NN_UINT32: + case OH_NN_FLOAT32: + return BIT32_TO_BYTE; + case OH_NN_INT64: + case OH_NN_UINT64: + case OH_NN_FLOAT64: + return BIT64_TO_BYTE; + default: + return 0; + } +} + +OH_NN_ReturnCode TensorDesc::GetDataType(OH_NN_DataType* dataType) const +{ + if (dataType == nullptr) { + LOGE("GetDataType failed, dataType is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + *dataType = m_dataType; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::SetDataType(OH_NN_DataType dataType) +{ + if (!Validation::ValidateTensorDataType(dataType)) { + LOGE("TensorDesc::SetDataType failed, dataType %{public}d is invalid.", static_cast(dataType)); + return OH_NN_INVALID_PARAMETER; + } + m_dataType = dataType; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::GetFormat(OH_NN_Format* format) const +{ + if (format == nullptr) { + LOGE("GetFormat failed, format is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + *format = m_format; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::SetFormat(OH_NN_Format format) +{ + if (!Validation::ValidateTensorFormat(format)) { + LOGE("TensorDesc::SetFormat failed, format %{public}d is invalid.", static_cast(format)); + return OH_NN_INVALID_PARAMETER; + } + m_format = format; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::GetShape(int32_t** shape, size_t* shapeNum) const +{ + if (shape == nullptr) { + LOGE("GetShape failed, shape is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*shape != nullptr) { + LOGE("GetShape failed, *shape is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeNum == nullptr) { + LOGE("GetShape failed, shapeNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + *shape = const_cast(m_shape.data()); + *shapeNum = m_shape.size(); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::SetShape(const int32_t* shape, size_t shapeNum) +{ + if (shape == nullptr) { + LOGE("SetShape failed, shape is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (shapeNum == 0) { + LOGE("SetShape failed, shapeNum is 0."); + return OH_NN_INVALID_PARAMETER; + } + m_shape.clear(); + for (size_t i = 0; i < shapeNum; ++i) { + m_shape.emplace_back(shape[i]); + } + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::GetElementNum(size_t* elementNum) const +{ + if (elementNum == nullptr) { + LOGE("GetElementNum failed, elementNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (m_shape.empty()) { + LOGE("GetElementNum failed, shape is empty."); + return OH_NN_INVALID_PARAMETER; + } + *elementNum = 1; + size_t shapeNum = m_shape.size(); + for (size_t i = 0; i < shapeNum; ++i) { + if (m_shape[i] <= 0) { + LOGW("GetElementNum return 0 with dynamic shape, shape[%{public}zu] is %{public}d.", i, m_shape[i]); + *elementNum = 0; + return OH_NN_DYNAMIC_SHAPE; + } + (*elementNum) *= m_shape[i]; + } + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::GetByteSize(size_t* byteSize) const +{ + if (byteSize == nullptr) { + LOGE("GetByteSize failed, byteSize is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + *byteSize = 0; + size_t elementNum = 0; + auto ret = GetElementNum(&elementNum); + if (ret == OH_NN_DYNAMIC_SHAPE) { + return OH_NN_SUCCESS; + } else if (ret != OH_NN_SUCCESS) { + LOGE("GetByteSize failed, get element num failed."); + return ret; + } + + uint32_t typeSize = GetTypeSize(m_dataType); + if (typeSize == 0) { + LOGE("GetByteSize failed, data type is invalid."); + return OH_NN_INVALID_PARAMETER; + } + + *byteSize = elementNum * typeSize; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode TensorDesc::SetName(const char* name) +{ + if (name == nullptr) { + LOGE("SetName failed, name is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + m_name = name; + return OH_NN_SUCCESS; +} + +// *name will be invalid after TensorDesc is destroyed +OH_NN_ReturnCode TensorDesc::GetName(const char** name) const +{ + if (name == nullptr) { + LOGE("GetName failed, name is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (*name != nullptr) { + LOGE("GetName failed, *name is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + *name = m_name.c_str(); + return OH_NN_SUCCESS; +} +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/tensor_desc.h b/frameworks/native/tensor_desc.h new file mode 100644 index 0000000..b16e379 --- /dev/null +++ b/frameworks/native/tensor_desc.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H +#define NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H + +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" +#include +#include + +namespace OHOS { +namespace NeuralNetworkRuntime { +class TensorDesc{ +public: + TensorDesc() = default; + ~TensorDesc() = default; + + OH_NN_ReturnCode GetDataType(OH_NN_DataType* dataType) const; + OH_NN_ReturnCode SetDataType(OH_NN_DataType dataType); + + OH_NN_ReturnCode GetFormat(OH_NN_Format* format) const; + OH_NN_ReturnCode SetFormat(OH_NN_Format format); + + OH_NN_ReturnCode GetShape(int32_t** shape, size_t* shapeNum) const; + OH_NN_ReturnCode SetShape(const int32_t* shape, size_t shapeNum); + + OH_NN_ReturnCode GetElementNum(size_t* elementNum) const; + OH_NN_ReturnCode GetByteSize(size_t* byteSize) const; + + OH_NN_ReturnCode SetName(const char* name); + OH_NN_ReturnCode GetName(const char** name) const; + + +private: + OH_NN_DataType m_dataType {OH_NN_UNKNOWN}; + OH_NN_Format m_format {OH_NN_FORMAT_NONE}; + std::vector m_shape; + std::string m_name; + +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H \ No newline at end of file diff --git a/frameworks/native/transform.cpp b/frameworks/native/transform.cpp index 12e51b0..8cc6b20 100644 --- a/frameworks/native/transform.cpp +++ b/frameworks/native/transform.cpp @@ -15,7 +15,6 @@ #include "transform.h" -#include "memory_manager.h" #include "common/log.h" namespace OHOS { diff --git a/frameworks/native/transform.h b/frameworks/native/transform.h index fc05ab5..369223c 100644 --- a/frameworks/native/transform.h +++ b/frameworks/native/transform.h @@ -16,7 +16,7 @@ #ifndef NEURAL_NETWORK_RUNTIME_TRANSFORM_H #define NEURAL_NETWORK_RUNTIME_TRANSFORM_H -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "cpp_type.h" #include "mindir.h" #include "mindir_types.h" diff --git a/frameworks/native/validation.cpp b/frameworks/native/validation.cpp index d451601..69204c6 100644 --- a/frameworks/native/validation.cpp +++ b/frameworks/native/validation.cpp @@ -13,8 +13,6 @@ * limitations under the License. */ -#include "mindir_types.h" - #include "validation.h" namespace OHOS { @@ -30,7 +28,7 @@ bool ValidateTensorDataType(OH_NN_DataType dataType) bool ValidateTensorFormat(OH_NN_Format format) { - if ((format >= OH_NN_FORMAT_NONE) && (format <= OH_NN_FORMAT_NHWC)) { + if ((format >= OH_NN_FORMAT_NONE) && (format <= OH_NN_FORMAT_ND)) { return true; } return false; @@ -60,14 +58,6 @@ bool ValidateFuseType(OH_NN_FuseType fuseType) return false; } -bool ValidatePadMode(int8_t padMode) -{ - if ((padMode >= mindspore::lite::PAD_MODE_PAD) && (padMode <= mindspore::lite::PAD_MODE_VALID)) { - return true; - } - return false; -} - bool ValidateTensorType(OH_NN_TensorType nnTensorType) { if ((nnTensorType >= OH_NN_TENSOR) && (nnTensorType <= OH_NN_UNSQUEEZE_AXIS)) { diff --git a/frameworks/native/validation.h b/frameworks/native/validation.h index 7c6d540..ddcd289 100644 --- a/frameworks/native/validation.h +++ b/frameworks/native/validation.h @@ -17,7 +17,7 @@ #define NEURAL_NETWORK_RUNTIME_VALIDATION_H #include "common/log.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -39,7 +39,6 @@ bool ValidateTensorFormat(OH_NN_Format format); bool ValidatePerformanceMode(OH_NN_PerformanceMode performanceMode); bool ValidatePriority(OH_NN_Priority priority); bool ValidateFuseType(OH_NN_FuseType fuseType); -bool ValidatePadMode(int8_t padMode); } // namespace Validation } // NeuralNetworkRuntime } // namespace OHOS diff --git a/interfaces/innerkits/c/neural_network_runtime_inner.h b/interfaces/innerkits/c/neural_network_runtime_inner.h index 314e986..92acc5b 100644 --- a/interfaces/innerkits/c/neural_network_runtime_inner.h +++ b/interfaces/innerkits/c/neural_network_runtime_inner.h @@ -16,7 +16,7 @@ #ifndef NEURAL_NETWORK_RUNTIME_INNER_H #define NEURAL_NETWORK_RUNTIME_INNER_H -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #ifdef __cplusplus extern "C" { diff --git a/interfaces/kits/c/BUILD.gn b/interfaces/kits/c/BUILD.gn deleted file mode 100644 index 856097a..0000000 --- a/interfaces/kits/c/BUILD.gn +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build/ohos.gni") - -ohos_ndk_library("libneural_network_runtime_ndk") { - output_name = "neural_network_runtime" - output_extension = "so" - ndk_description_file = "libneural_network_runtime.ndk.json" - min_compact_version = "9" - system_capability = "SystemCapability.AI.NeuralNetworkRuntime" - system_capability_headers = [ - "neural_network_runtime.h", - "neural_network_runtime_type.h", - ] -} - -ohos_ndk_headers("libneural_network_runtime_header") { - dest_dir = "$ndk_headers_out_dir/neural_network_runtime" - sources = [ - "neural_network_runtime.h", - "neural_network_runtime_type.h", - ] -} diff --git a/interfaces/kits/c/libneural_network_runtime.ndk.json b/interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json similarity index 100% rename from interfaces/kits/c/libneural_network_runtime.ndk.json rename to interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_core.h b/interfaces/kits/c/neural_network_runtime/neural_network_core.h new file mode 100644 index 0000000..7ba73a2 --- /dev/null +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -0,0 +1,1030 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup NeuralNeworkRuntime + * @{ + * + * @brief Provides APIs of Neural Network Runtime for accelerating the model inference. + * + * @since 11 + * @version 1.0 + */ + +/** + * @file neural_network_core.h + * + * @brief Defines the Neural Network Core APIs. The AI inference framework uses the Native APIs provided by Neural Network Core + * to compile models and perform inference and computing on acceleration hardware. + * Note: Currently, the APIs of Neural Network Core do not support multi-thread calling. \n + * + * @library libneural_network_core.so + * @Syscap SystemCapability.Ai.NeuralNetworkRuntime + * @since 11 + * @version 1.0 + */ + +#ifndef NEURAL_NETWORK_CORE_H +#define NEURAL_NETWORK_CORE_H + +#include "neural_network_runtime_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a compilation instance of the {@link OH_NNCompilation} type. + * + * After the OH_NNModel module completes model construction, APIs provided by the OH_NNCompilation module pass the model + * to underlying device for compilation. This method creates a {@link OH_NNCompilation} instance + * based on the passed {@link OH_NNModel} instance. The {@link OH_NNCompilation_SetDevice} method is called + * to set the device to compile on, and {@link OH_NNCompilation_Build} is then called to complete compilation. \n + * + * In addition to computing device selection, the OH_NNCompilation module supports features such as model caching, performance preference, + * priority setting, and float16 computing, which can be implemented by the following methods: + * - {@link OH_NNCompilation_SetCache} + * - {@link OH_NNCompilation_SetPerformanceMode} + * - {@link OH_NNCompilation_SetPriority} + * - {@link OH_NNCompilation_EnableFloat16} \n + * + * After {@link OH_NNCompilation_Build} is called, the {@link OH_NNModel} instance can be released. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @return Returns the pointer to a {@link OH_NNCompilation} instance. + * @since 9 + * @version 1.0 + */ +OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model); + +/** + * @brief Creates a compilation instance based on an offline model file. + * + * This method conflicts with the way of passing an online built model or an offline model file buffer, + * and you have to choose only one of the three construction methods. \n + * + * Offline model is a type of model that is offline compiled by the model converter provided by a device vendor. + * So that the offline model can only be used on the specified device, but the compilation time of offline model is usually + * much less than {@link OH_NNModel}. \n + * + * You should perform the offline compilation during your development and deploy the offline model in your app package. \n + * + * + * @param modelPath Offline model file path. + * @return Pointer to an {@link OH_NNCompilation} instance. + * @since 11 + * @version 1.0 + */ +OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *modelPath); + +/** + * @brief Creates a compilation instance based on an offline model file buffer. + * + * This method conflicts with the way of passing an online built model or an offline model file path, + * and you have to choose only one of the three construction methods. \n + * + * After {@link OH_NNCompilation_Build} is called, the modelBuffer<\b> can be released. \n + * + * @param modelBuffer Offline model file buffer. + * @param modelSize Offfline model buffer size. + * @return Pointer to an {@link OH_NNCompilation} instance. + * @since 11 + * @version 1.0 + */ +OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *modelBuffer, size_t modelSize); + +/** + * @brief Creates a empty compilation instance for restoration from cache later. + * + * The restoration time from the cache is less than compilation with {@link OH_NNModel}. \n + * + * You should call {@link OH_NNCompilation_SetCache} or {@link OH_NNCompilation_ImportCacheFromBuffer} first, + * and then call {@link OH_NNCompilation_Build} to complete the restoration. \n + * + * @since 11 + * @version 1.0 + */ +OH_NNCompilation *OH_NNCompilation_ConstructForCache(); + +/** + * @brief Exports the cache to a given buffer. + * + * The cache is the result of compilation building {@link OH_NNCompilation_Build}, + * so that this method must be called after {@link OH_NNCompilation_Build}. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param buffer Pointer to the given buffer. + * @param length Buffer length. + * @param modelSize Byte size of the model cache. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t length, + size_t *modelSize); + +/** + * @brief Imports the cache from a given buffer. + * + * {@link OH_NNCompilation_Build} should be called to complete the restoration after {@link OH_NNCompilation_ImportCacheFromBuffer} is called. \n + * + * After {@link OH_NNCompilation_Build} is called, the buffer<\b> can be released. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param buffer Pointer to the given buffer. + * @param modelSize Byte size of the model cache. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t modelSize); + +/** + * @brief Adds an extension config for a custom hardware attribute. + * + * Some devices have their own specific attributes which have not been opened in NNRt. This method provides an additional way for you + * to set these custom hardware attributes of the device. You should query their names and values from the device + * vendor's documents, and add them into compilation instance one by one. These attributes will be passed directly to device + * driver, and this method will return error code if the driver cannot parse them. \n + * + * After {@link OH_NNCompilation_Build} is called, the configName<\b> and configValue<\b> can be released. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param configName Config name. + * @param configValue A byte buffer saving the config value. + * @param configValueSize Byte size of the config value. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, + const char *configName, + const void *configValue, + const size_t configValueSize); + +/** + * @brief Specifies the device for model compilation and computing. + * + * In the compilation phase, you need to specify the device for model compilation and computing. Call {@link OH_NNDevice_GetAllDevicesID} + * to obtain available device IDs. Call {@link OH_NNDevice_GetType} and {@link OH_NNDevice_GetName} to obtain device information + * and pass target device IDs to this method for setting. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param deviceID Device ID. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID); + +/** + * @brief Set the cache directory and version of the compiled model. + * + * On the device that supports caching, a model can be saved as a cache file after being compiled on the device driver. + * The model can be directly read from the cache file in the next compilation, saving recompilation time. + * This method performs different operations based on the passed cache directory and version: \n + * + * - No file exists in the cache directory: + * Caches the compiled model to the directory and sets the cache version to version. \n + * + * - A complete cache file exists in the cache directory, and its version is version: + * Reads the cache file in the path and passes the data to the underlying device for conversion into executable model instances. \n + * + * - A complete cache file exists in the cache directory, and its version is earlier than version: + * When model compilation is complete on the underlying device, overwrites the cache file and changes the version number to version. \n + * + * - A complete cache file exists in the cache directory, and its version is later than version: + * Returns the {@link OH_NN_INVALID_PARAMETER} error code without reading the cache file. \n + * + * - The cache file in the cache directory is incomplete or you do not have the permission to access the cache file. + * Returns the {@link OH_NN_INVALID_FILE} error code. \n + * + * - The cache directory does not exist or you do not have the access permission. + * Returns the {@link OH_NN_INVALID_PATH} error code. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param cachePath Directory for storing model cache files. This method creates directories for different devices in the cachePath directory. + * You are advised to use a separate cache directory for each model. + * @param version Cache version. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const char *cachePath, uint32_t version); + +/** + * @brief Sets the performance mode for model computing. + * + * Allows you to set the performance mode for model computing to meet the requirements of low power consumption + * and ultimate performance. If this method is not called to set the performance mode in the compilation phase, the compilation instance assigns + * the {@link OH_NN_PERFORMANCE_NONE} mode for the model by default. In this case, the device performs computing in the default performance mode. \n + * + * If this method is called on the device that does not support the setting of the performance mode, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param performanceMode Performance mode. For details about the available performance modes, see {@link OH_NN_PerformanceMode}. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, + OH_NN_PerformanceMode performanceMode); + +/** + * @brief Sets the model computing priority. + * + * Allows you to set computing priorities for models. + * The priorities apply only to models created by the process with the same UID. + * The settings will not affect models created by processes with different UIDs on different devices. \n + * + * If this method is called on the device that does not support the priority setting, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param priority Priority. For details about the optional priorities, see {@link OH_NN_Priority}. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_NN_Priority priority); + +/** + * @brief Enables float16 for computing. + * + * Float32 or int8 are used by default. If this method is called on a device that supports float16, + * float16 will be used for computing the float32 model to reduce memory usage and execution time. \n + * + * If this method is called on the device that does not support float16, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @param enableFloat16 Indicates whether to enable float16. If this parameter is set to true, float16 inference is performed. + * If this parameter is set to false, float32 inference is performed. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, an error code is returned. + * For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16); + +/** + * @brief Compiles a model. + * + * After the compilation configuration is complete, call this method to return the compilation result. The compilation instance pushes the model and + * compilation options to the device for compilation. After this method is called, additional compilation operations cannot be performed. \n + * + * If the {@link OH_NNCompilation_SetDevice}, {@link OH_NNCompilation_SetCache}, {@link OH_NNCompilation_SetPerformanceMode}, + * {@link OH_NNCompilation_SetPriority}, and {@link OH_NNCompilation_EnableFloat16} methods are called, {@link OH_NN_OPERATION_FORBIDDEN} is returned. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation); + +/** + * @brief Releases the Compilation object. + * + * This method needs to be called to release the compilation instance created by calling {@link OH_NNCompilation_Construct}. + * Otherwise, the memory leak will occur. \n + * + * If compilation or *compilation is a null pointer, this method only prints warning logs and does not execute the release. \n + * + * @param compilation Double pointer to the {@link OH_NNCompilation} instance. After a compilation instance is destroyed, + * this method sets *compilation to a null pointer. + * @since 9 + * @version 1.0 + */ +void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); + + +/** + * @brief Creates an {@link NN_TensorDesc} instance. + * + * The {@link NN_TensorDesc} describes various tensor attributes, such as name/data type/shape/format, etc. \n + * + * The following methods can be called to create a {@link NN_Tensor} instance based on the passed {@link NN_TensorDesc} instance: + * - {@link OH_NNTensor_Create} + * - {@link OH_NNTensor_CreateWithSize} + * - {@link OH_NNTensor_CreateWithFd} \n + * Note that these methods will copy the {@link NN_TensorDesc} instance into {@link NN_Tensor}. Therefore you can create multiple + * {@link NN_Tensor} instances with the same {@link NN_TensorDesc} instance. And you should destroy the {@link NN_TensorDesc} instance + * by {@link OH_NNTensorDesc_Destroy} when it is no longer used. \n + * + * @return Pointer to a {@link NN_TensorDesc} instance + * @since 11 + * @version 1.0 + */ +NN_TensorDesc *OH_NNTensorDesc_Create(); + +/** + * @brief Releases an {@link NN_TensorDesc} instance. + * + * When the {@link NN_TensorDesc} instance is no longer used, this method needs to be called to release it. Otherwise, + * the memory leak will occur. \n + * + * If tensorDesc or *tensorDesc is a null pointer, this method will return error code and does not execute the release. \n + * + * @param tensorDesc Double pointer to the {@link NN_TensorDesc} instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); + +/** + * @brief Sets the name of a {@link NN_TensorDesc}. + * + * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor name. + * The value of (*name) is a C-style string ended with '\0'. \n + * + * if tensorDesc or name is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param name The name of the tensor that needs to be set. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char *name); + +/** + * @brief Gets the name of a {@link NN_TensorDesc}. + * + * Call this method to obtain the name of the specified {@link NN_TensorDesc} instance. + * The value of (*name) is a C-style string ended with '\0'. \n + * + * if tensorDesc or name is a null pointer, this method will return error code. + * As an output parameter, *name must be a null pointer, otherwise the method will return an error code. + * Fou example, you should define char* tensorName = NULL, and pass &tensorName as the argument of name. \n + * + * You do not need to release the memory of name. It will be released when tensorDesc is destroied. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param name The retured name of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const char **name); + +/** + * @brief Sets the data type of a {@link NN_TensorDesc}. + * + * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor data type. \n + * + * if tensorDesc is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param dataType The data type of the tensor that needs to be set. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_DataType dataType); + +/** + * @brief Gets the data type of a {@link NN_TensorDesc}. + * + * Call this method to obtain the data type of the specified {@link NN_TensorDesc} instance. \n + * + * if tensorDesc or dataType is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param dataType The returned data type of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH_NN_DataType *dataType); + +/** + * @brief Sets the shape of a {@link NN_TensorDesc}. + * + * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor shape. \n + * + * if tensorDesc or shape is a null pointer, or shapeNum is 0, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param shape The shape list of the tensor that needs to be set. + * @param shapeLength The length of the shape list that needs to be set. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeLength); + +/** + * @brief Gets the shape of a {@link NN_TensorDesc}. + * + * Call this method to obtain the shape of the specified {@link NN_TensorDesc} instance. \n + * + * if tensorDesc, shape or shapeNum is a null pointer, this method will return error code. + * As an output parameter, *shape must be a null pointer, otherwise the method will return an error code. + * Fou example, you should define int32_t* tensorShape = NULL, and pass &tensorShape as the argument of shape. \n + * + * You do not need to release the memory of shape. It will be released when tensorDesc is destroied. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param shape Return the shape list of the tensor. + * @param shapeLength The returned length of the shape list. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength); + +/** + * @brief Sets the format of a {@link NN_TensorDesc}. + * + * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor format. \n + * + * if tensorDesc is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param format The format of the tensor that needs to be set. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format); + +/** + * @brief Gets the format of a {@link NN_TensorDesc}. + * + * Call this method to obtain the format of the specified {@link NN_TensorDesc} instance. \n + * + * if tensorDesc or format is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param format The returned format of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_NN_Format *format); + +/** + * @brief Gets the element count of a {@link NN_TensorDesc}. + * + * Call this method to obtain the element count of the specified {@link NN_TensorDesc} instance. + * If you need to obtain byte size of the tensor data, call {@link OH_NNTensorDesc_GetByteSize}. \n + * + * If the tensor shape is dynamic, this method will return error code, and elementCount will be 0. \n + * + * if tensorDesc or elementCount is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param elementCount The returned element count of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount); + +/** + * @brief Gets the byte size of a {@link NN_TensorDesc}. + * + * Call this method to obtain the byte size of the specified {@link NN_TensorDesc} instance. \n + * + * If the tensor shape is dynamic, this method will return error code, and byteSize will be 0. \n + * + * If you need to obtain element count of the tensor data, call {@link OH_NNTensorDesc_GetElementCount}. \n + * + * if tensorDesc or byteSize is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param byteSize The returned byte size of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, size_t *byteSize); + +/** + * @brief Creates a {@link NN_Tensor} instance from {@link NN_TensorDesc}. + * + * This method use {@link OH_NNTensorDesc_GetByteSize} to calculate the byte size of tensor data and allocate device memory for it. + * The device dirver will get the tensor data directly by the "zero-copy" way. \n + * + * Note that this method will copy the tensorDesc into {@link NN_Tensor}. Therefore you should destroy tensorDesc + * by {@link OH_NNTensorDesc_Destroy} when it is no longer used. \n + * + * If the tensor shape is dynamic, this method will return error code. \n + * + * deviceID indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. \n + * + * tensorDesc must be provided, and this method will return an error code if it is a null pointer. \n + * + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n + * + * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @return Pointer to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); + +/** + * @brief Creates a {@link NN_Tensor} instance with specified size. + * + * This method use size as the byte size of tensor data and allocate device memory for it. + * The device dirver will get the tensor data directly by the "zero-copy" way. \n + * + * Note that this method will copy the tensorDesc into {@link NN_Tensor}. Therefore you should destroy tensorDesc + * by {@link OH_NNTensorDesc_Destroy} when it is no longer used. \n + * + * deviceName indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. \n + * + * tensorDesc must be provided, if it is a null pointer, the method returns an error code. + * size must be no less than the byte size of tensorDesc. Otherwise, this method will return an error code. If the tensor + * shape is dynamic, the size will not be checked. \n + * + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n + * + * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param size Size of tensor data that need to be allocated. + * @return Pointer to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc, size_t size); + +/** + * @brief Creates a {@link NN_Tensor} instance with specified fd. + * + * This method reuses the shared memory corresponding to the argument fd passed. It may comes from another {@link NN_Tensor} instance. + * When you call the {@link OH_NNTensor_DestroyTensor} method to release the tensor created by this method, the tensor data memory will not be released. \n + * + * Note that this method will copy the tensorDesc into {@link NN_Tensor}. Therefore you should destroy tensorDesc + * by {@link OH_NNTensorDesc_Destroy} when it is no longer used. \n + * + * Note that the tensorDesc will be released along with the {@link NN_Tensor} instance. Therefore every {@link NN_Tensor} + * instance you created must use a new tensorDesc that has not been used by another {@link NN_Tensor} instance. + * Otherwise, a tensorDesc will be released twice, which will bring a memory corruption of doulbe free. \n + * + * deviceName indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. + * tensorDesc must be provided, if it is a null pointer, the method returns an error code. \n + * + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n + * + * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param fd Fd of the shared memory to be resued. + * @param size Size of the shared memory to be resued. + * @param offset Offset of the shared memory to be resued. + * @return Pinter to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, + NN_TensorDesc *tensorDesc, + int fd, + size_t size, + size_t offset); + +/** + * @brief Releases a {@link NN_Tensor} instance. + * + * When the {@link NN_Tensor} instance is no longer used, this method needs to be called to release the instance. + * Otherwise, the memory leak will occur. \n + * + * If tensor or *tensor is a null pointer, this method will return error code and does not execute the release. \n + * + * @param tensorDesc Double pointer to the {@link NN_Tensor} instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor); + +/** + * @brief Gets the {@link NN_TensorDesc} instance of a {@link NN_Tensor}. + * + * Call this method to obtain the inner {@link NN_TensorDesc} instance pointer of the specified {@link NN_Tensor} instance. + * You can get various types of the tensor attributes such as name/format/data type/shape from the returned {@link NN_TensorDesc} instance. \n + * + * You should not destory the returned {@link NN_TensorDesc} instance because it points to the inner instance of {@link NN_Tensor}. + * Otherwise, a menory corruption of double free will occur when {@link OH_NNTensor_Destroy} is called. + * + * if tensor is a null pointer, this method will return null pointer. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @return Pointer to the {@link NN_TensorDesc} instance. If the operation fails, a null pointer is returned. + * @since 11 + * @version 1.0 + */ +NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor); + +/** + * @brief Gets the data buffer of a {@link NN_Tensor}. + * + * You can read/write data from/to the tensor data buffer. The buffer is mapped from a shared memory on device, so the device dirver + * will get the tensor data directly by this "zero-copy" way. \n + * + * Note that you are only allowed to access the tensor data buffer with length of (size - offset), otherwise a heap corruption may occur. \n + * + * if tensor is a null pointer, this method will return null pointer. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @return Pointer to data buffer of the tensor. If the operation fails, a null pointer is returned. + * @since 11 + * @version 1.0 + */ +void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); + +/** + * @brief Gets the data size of a {@link NN_Tensor}. + * + * The tensor data size is as same as the argument size of {@link OH_NNTensor_CreateWithSize} and {@link OH_NNTensor_CreateWithFd}. + * But for a tensor created by {@link OH_NNTensor_Create}, it equals to the tensor byte size. \n + * + * Note that you are only allowed to access the tensor data buffer with length of (size - offset), otherwise a heap corruption may occur. \n + * + * if tensor or size is a null pointer, this method will return error code. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @param size The returned size of tensor data. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); + +/** + * @brief Gets the data fd of a {@link NN_Tensor}. + * + * The fd corresponds to a shared memory on device driver, and can be resued by another {@link NN_Tensor} through + * {@link OH_NNTensor_CreateWithFd}. \n + * + * if tensor or fd is a null pointer, this method will return error code. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @param fd The returned fd of tensor data. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); + +/** + * @brief Get the data offset of a tensor. + * + * The offset corresponds to the fd of the tensor data, and can be resued by another {@link NN_Tensor} through + * {@link OH_NNTensor_CreateWithFd}. \n + * + * if tensor or offset is a null pointer, this method will return error code. \n + * + * Note that you are only allowed to access the tensor data buffer with length of (size - offset), otherwise a heap corruption may occur. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @param offset The returned offset of tensor data. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t *offset); + +/** + * @brief Creates an executor instance of the {@link OH_NNExecutor} type. + * + * This method constructs a model inference executor associated with the device based on the passed compiler. \n + * + * After the {@link OH_NNExecutor} instance is created, you can release the {@link OH_NNCompilation} + * instance if you do not need to create any other executors. \n + * + * @param compilation Pointer to the {@link OH_NNCompilation} instance. + * @return Pointer to a {@link OH_NNExecutor} instance. + * @since 9 + * @version 1.0 + */ +OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation); + +/** + * @brief Obtains the dimension information about the output tensor. + * + * After {@link OH_NNExecutor_Run} is called to complete a single inference, call this method to obtain the specified output dimension + * information and number of dimensions. It is commonly used in dynamic shape input and output scenarios. \n + * + * As an output parameter, *shape must be a null pointer, otherwise the method will return an error code. + * Fou example, you should define int32_t* tensorShape = NULL, and pass &tensorShape as the argument of shape. \n + * + * You do not need to release the memory of shape. It will be released when executor is destroied. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * When {@link OH_NNExecutor_GetOutputShape} is called to obtain dimension information about the output tensor, + * outputIndices is {0, 1, 2}. + * + * @param shape Pointer to the int32_t array. The value of each element in the array is the length of the output tensor in each dimension. + * @param shapeLength Pointer to the uint32_t type. The number of output dimensions is returned. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, + uint32_t outputIndex, + int32_t **shape, + uint32_t *shapeLength); + +/** + * @brief Destroys an executor instance to release the memory occupied by the executor. + * + * This method needs to be called to release the executor instance created by calling {@link OH_NNExecutor_Construct}. Otherwise, + * the memory leak will occur. \n + * + * If executor or *executor is a null pointer, this method only prints warning logs and does not execute the release. \n + * + * @param executor Double pointer to the {@link OH_NNExecutor} instance. + * @since 9 + * @version 1.0 + */ +void OH_NNExecutor_Destroy(OH_NNExecutor **executor); + +/** + * @brief Gets the input tensor count. + * + * You can get the input tensor count from the executor, and then create an input tensor descriptor with its index by + * {@link OH_NNExecutor_CreateInputTensorDesc}. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param inputCount Input tensor count returned. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_GetInputCount(const OH_NNExecutor *executor, size_t *inputCount); + +/** + * @brief Gets the output tensor count. + * + * You can get the output tensor count from the executor, and then create an output tensor descriptor with its index by + * {@link OH_NNExecutor_CreateOutputTensorDesc}. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param OutputCount Output tensor count returned. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_GetOutputCount(const OH_NNExecutor *executor, size_t *outputCount); + +/** + * @brief Creates an input tensor descriptor with its index. + * + * The input tensor descriptor contains all attributes of the input tensor. + * If the index exceeds the inputCount - 1, this method will return error code. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param index Input tensor index. + * @return Pointer to {@link NN_TensorDesc} instance. + * @since 11 + * @version 1.0 + */ +NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor, size_t index); + +/** + * @brief Creates an output tensor descriptor with its index. + * + * The output tensor descriptor contains all attributes of the output tensor. + * If the index exceeds the outputCount - 1, this method will return error code. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param index Output tensor index. + * @return Pointer to {@link NN_TensorDesc} instance. + * @since 11 + * @version 1.0 + */ +NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index); + +/** + * @brief Gets the dimension ranges of an input tensor. + * + * The supported dimension ranges of an input tensor with dynamic shape may be different among various devices. + * You can call this method to get the dimension ranges of the input tensor supported by the device. + * *minInputDims<\b> contains the minimum demensions of the input tensor, and *maxInputDims<\b> contains the maximum, + * e.g. if an input tensor has dynamic shape [-1, -1, -1, 3], its *minInputDims<\b> may be [1, 10, 10, 3] and + * *maxInputDims<\b> may be [100, 1024, 1024, 3] on the device. \n + * + * If the index exceeds the inputCount - 1, this method will return error code. \n + * + * As an output parameter, *minInputDims or *maxInputDims must be a null pointer, otherwise the method will return an error code. + * For example, you should define int32_t* minInDims = NULL, and pass &minInDims as the argument of minInputDims. \n + * + * You do not need to release the memory of *minInputDims or *maxInputDims. It will be released when executor is destroied. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param index Input tensor index. + * @param minInputDims Returned pointer to an array contains the minimum dimensions of the input tensor. + * @param maxInputDims Returned pointer to an array contains the maximum dimensions of the input tensor. + * @param shapeLength Returned length of the shape of input tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, + size_t index, + size_t **minInputDims, + size_t **maxInputDims, + size_t *shapeLength); + +/** + * @brief Sets the callback function handle for the post-process when the asynchronous execution has been done. + * + * The definition fo the callback function: {@link NN_OnRunDone} \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param onRunDone Callback function handle {@link NN_OnRunDone}. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); + +/** + * @brief Sets the callback function handle for the post-process when the device driver service is dead during asynchronous execution. + * + * The definition fo the callback function: {@link NN_OnServiceDied} \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param onServiceDied Callback function handle {@link NN_OnServiceDied}. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor, NN_OnServiceDied onServiceDied); + +/** + * @brief Synchronous execution of the model inference. + * + * Input and output tensors should be created first by {@link OH_NNTensor_Create}, {@link OH_NNTensor_CreateWithSize} or + * {@link OH_NNTensor_CreateWithFd}. And then the input tensors data which is got by {@link OH_NNTensor_GetDataBuffer} must be filled. + * The executor will then yield out the results by inference execution and fill them into output tensors data for you to read. \n + * + * In the case of dynamic shape, you can get the real output shape directly by {@link OH_NNExecutor_GetOutputShape}, or you + * can create a tensor descriptor from an output tensor by {@link OH_NNTensor_GetTensorDesc}, and then read its real shape + * by {@link OH_NNTensorDesc_GetShape}. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param inputTensor An array of input tensors {@link NN_Tensor}. + * @param inputCount Number of input tensors. + * @param outputTensor An array of output tensors {@link NN_Tensor}. + * @param outputCount Number of output tensors. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, + NN_Tensor *inputTensor[], + size_t inputCount, + NN_Tensor *outputTensor[], + size_t outputCount); + +/** + * @brief Asynchronous execution of the model inference. + * + * Input and output tensors should be created first by {@link OH_NNTensor_Create}, {@link OH_NNTensor_CreateWithSize} or + * {@link OH_NNTensor_CreateWithFd}. And then the input tensors data which is got by {@link OH_NNTensor_GetDataBuffer} must be filled. + * The executor will yield out the results by inference execution and fill them into output tensors data for you to read. \n + * + * In the case of dynamic shape, you can get the real output shape directly by {@link OH_NNExecutor_GetOutputShape}, or you + * can create a tensor descriptor from an output tensor by {@link OH_NNTensor_GetTensorDesc}, and then read its real shape + * by {@link OH_NNTensorDesc_GetShape}. \n + * + * The method is non-blocked and will return immediately. The callback function handles are set by {@link OH_NNExecutor_SetOnRunDone} + * and {@link OH_NNExecutor_SetOnServiceDied}. If the execution time reaches the timeout<\b>, the execution will be terminated + * with no outputs, and the errCode returned in callback function {@link NN_OnRunDone} will be {@link OH_NN_TIMEOUT}. \n + * + * The userData<\b> is asynchronous execution identifier and will be returned as the first parameter of the callback function. + * You can input any value you want as long as it can identify different asynchronous executions. \n + * + * @param executor Pointer to the {@link OH_NNExecutor} instance. + * @param inputTensor An array of input tensors {@link NN_Tensor}. + * @param inputCount Number of input tensors. + * @param outputTensor An array of output tensors {@link NN_Tensor}. + * @param outputCount Number of output tensors. + * @param timeout Time limit (millisecond) of the asynchronous execution, e.g. 1000. + * @param userData Asynchronous execution identifier. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, + NN_Tensor *inputTensor[], + size_t inputCount, + NN_Tensor *outputTensor[], + size_t outputCount, + int32_t timeout, + void* userData); + +/** + * @brief Obtains the IDs of all devices connected. + * + * Each device has an unique and fixed ID. This method returns device IDs on the current device through the uint32_t array. \n + * + * Device IDs are returned through the size_t array. Each element of the array is the ID of a single device. \n + * + * The array memory is managed inside, so you do not need to care about it. + * The data pointer is valid before this method is called next time. \n + * + * @param allDevicesID Pointer to the size_t array. The input *allDevicesID must be a null pointer. Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. + * @param deviceCount Pointer of the uint32_t type, which is used to return the length of (*allDevicesID). + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount); + +/** + * @brief Obtains the name of the specified device. + * + * deviceID specifies the device whose name will be obtained. The device ID needs to be obtained by calling {@link OH_NNDevice_GetAllDevicesID}. \n + * + * The value of (*name) is a C-style string ended with '\0'. *name must be a null pointer. + * Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. + * Fou example, you should define char* deviceName = NULL, and pass &deviceName as the argument of name. \n + * + * @param deviceID Device ID. + * @param name The device name returned. + + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name); + +/** + * @brief Obtains the type information of the specified device. + * + * deviceID specifies the device whose type will be obtained. Currently the following device types are supported: + * - OH_NN_CPU: CPU device. + * - OH_NN_GPU: GPU device. + * - OH_NN_ACCELERATOR: machine learning dedicated accelerator. + * - OH_NN_OTHERS: other hardware types. \n + * + * @param deviceID Device ID. + * @param deviceType The device type {@link OH_NN_DeviceType} returned. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType *deviceType); + +#ifdef __cplusplus +} +#endif // __cplusplus + +/** @} */ +#endif // NEURAL_NETWORK_CORE_H diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h new file mode 100644 index 0000000..041a416 --- /dev/null +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup NeuralNeworkRuntime + * @{ + * + * @brief Provides APIs of Neural Network Runtime for accelerating the model inference. + * + * @Syscap SystemCapability.Ai.NeuralNetworkRuntime + * @since 9 + * @version 2.0 + */ + +/** + * @file neural_network_runtime.h + * + * @brief Defines the Neural Network Runtime APIs. The AI inference framework uses the Native APIs provided by Neural Network Runtime + * to construct models. + * Note: Currently, the APIs of Neural Network Runtime do not support multi-thread calling. \n + * + * @library libneural_network_runtime.so + * @since 9 + * @version 2.0 + */ + +#ifndef NEURAL_NETWORK_RUNTIME_H +#define NEURAL_NETWORK_RUNTIME_H + +#include "neural_network_runtime_type.h" +#include "neural_network_core.h" +#include "neural_network_runtime_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a {@link NN_QuantParam} instance. + * + * After the NN_QuantParam instance is created, call {@link OH_NNQuantParam_SetScales}, {@link OH_NNQuantParam_SetZeroPoints}, + * {@link OH_NNQuantParam_SetNumBits} to set its attributes, and then call {@link OH_NNModel_SetTensorQuantParams} to set it + * to a tensor. After that you should destroy it by calling {@link OH_NNQuantParam_Destroy} to avoid memory leak. \n + * + * @return Pointer to a {@link NN_QuantParam} instance. + * @since 11 + * @version 1.0 + */ +NN_QuantParam *OH_NNQuantParam_Create(); + +/** + * @brief Sets the scales of the quantization parameter instance. + * + * The parameter quantCount<\b> is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * count if the tensor is per-channel quantized. \n + * + * @param quantParams Pointer to the {@link NN_QuantParam} instance. + * @param scales An array of scales for all quantization parameters of the tensor. + * @param quantCount Number of quantization parameters of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam *quantParams, const double *scales, size_t quantCount); + +/** + * @brief Sets the zero points of the quantization parameter instance. + * + * The parameter quantCount<\b> is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * count if the tensor is per-channel quantized. \n + * + * @param quantParams Pointer to the {@link NN_QuantParam} instance. + * @param zeroPoints An array of zero points for all quantization parameters of the tensor. + * @param quantCount Number of quantization parameters of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam *quantParams, const int32_t *zeroPoints, size_t quantCount); + +/** + * @brief Sets the number bits of the quantization parameter instance. + * + * The parameter quantCount<\b> is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * count if the tensor is per-channel quantized. \n + * + * @param quantParams Pointer to the {@link NN_QuantParam} instance. + * @param numBits An array of number bits for all quantization parameters of the tensor. + * @param quantCount Number of quantization parameters of the tensor. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam *quantParams, const uint32_t *numBits, size_t quantCount); + +/** + * @brief Releases a quantization parameter instance. + * + * The {@link NN_QuantParam} instance needs to be released to avoid memory leak after it is set to a {@link NN_TensorDesc}. + * If quantParams or *quantParams is a null pointer, this method only prints warning logs and does not + * execute the release. \n + * + * @param quantParams Double pointer to the {@link NN_QuantParam} instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam **quantParams); + +/** + * @brief Creates a model instance of the {@link OH_NNModel} type and uses other APIs provided by OH_NNModel to construct the model instance. + * + * Before composition, call {@link OH_NNModel_Construct} to create a model instance. Based on the model topology, + * call the {@link OH_NNModel_AddTensor}, {@link OH_NNModel_AddOperation}, and {@link OH_NNModel_SetTensorData} methods + * to fill in the data and operator nodes of the model, and then call {@link OH_NNModel_SpecifyInputsAndOutputs} to specify the inputs and outputs of the model. + * After the model topology is constructed, call {@link OH_NNModel_Finish} to build the model. \n + * + * After a model instance is no longer used, you need to destroy it by calling {@link OH_NNModel_Destroy} to avoid memory leak. \n + * + * @return Pointer to a {@link OH_NNModel} instance. + * @since 9 + * @version 1.0 + */ +OH_NNModel *OH_NNModel_Construct(void); + +/** + * @brief Adds a tensor to the model instance. + * + * The data node and operator parameters in the Neural Network Runtime model are composed of tensors of the model. + * This method is used to add tensors to a model instance based on the tensorDesc parameter with type of {@link NN_TensorDesc}. + * {@link NN_TensorDesc} contains some attributes such as shape, format, data type and provides corresponding APIs to access them. + * The order of adding tensors is specified by the indices recorded in the model. The {@link OH_NNModel_SetTensorData}, {@link OH_NNModel_AddOperation}, + * and {@link OH_NNModel_SpecifyInputsAndOutputs} methods specify tensors based on the indices. \n + * + * Neural Network Runtime supports inputs and outputs of the dynamic shape. When adding a data node with a dynamic shape, + * you need to set the dimensions that support dynamic changes to -1. + * For example, if the shape of a four-dimensional tensor is set to [1, -1, 2, 2], the second dimension supports dynamic changes. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. The tensor descriptor specifies the attributes of the tensor added to the model instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel *model, const NN_TensorDesc *tensorDesc); + +/** + * @brief Sets the tensor value. + * + * For tensors with constant values (such as model weights), you need to use this method to set their data. + * The index of a tensor is determined by the order in which the tensor is added to the model. + * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param index Index of a tensor. + * @param dataBuffer Pointer to real data. + * @param length Length of the data buffer. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, const void *dataBuffer, size_t length); + +/** + * @brief Sets the quantization parameter of a tensor. + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param index Index of a tensor. + * @param quantParam Pointer to the quantization parameter instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel *model, uint32_t index, NN_QuantParam *quantParam); + +/** + * @brief Sets the tensor type. See {@link OH_NN_TensorType} for details. + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param index Index of a tensor. + * @param tensorType Tensor type of {@link OH_NN_TensorType}. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 11 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_NN_TensorType tensorType); + +/** + * @brief Adds an operator to a model instance. + * + * This method is used to add an operator to a model instance. The operator type is specified by op, and + * the operator parameters, inputs, and outputs are specified by paramIndices, inputIndices, and outputIndices respectively. + * This method verifies the attributes of operator parameters and the number of input and output parameters. + * These attributes must be correctly set when {@link OH_NNModel_AddTensor} is called to add tensors. + * For details about the expected parameters, input attributes, and output attributes of each operator, see {@link OH_NN_OperationType}. \n + * + * paramIndices, inputIndices, and outputIndices store the indices of tensors. + * The indices are determined by the order in which tensors are added to the model. + * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n + * + * If unnecessary parameters are added when adding an operator, this method returns {@link OH_NN_INVALID_PARAMETER}. + * If no operator parameter is set, the operator uses the default parameter value. + * For details about the default values, see {@link OH_NN_OperationType}. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param op Specifies the type of an operator to be added. For details, see the enumerated values of {@link OH_NN_OperationType}. + * @param paramIndices Pointer to the OH_NN_UInt32Array instance, which is used to set operator parameters. + * @param inputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator input. + * @param outputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator output. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, + OH_NN_OperationType op, + const OH_NN_UInt32Array *paramIndices, + const OH_NN_UInt32Array *inputIndices, + const OH_NN_UInt32Array *outputIndices); + +/** + * @brief Specifies the inputs and outputs of a model. + * + * A tensor must be specified as the end-to-end inputs and outputs of a model instance. This type of tensor cannot be set + * using {@link OH_NNModel_SetTensorData}. \n + * + * The index of a tensor is determined by the order in which the tensor is added to the model. + * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n + * + * Currently, the model inputs and outputs cannot be set asynchronously. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param inputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator input. + * @param outputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator output. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, + const OH_NN_UInt32Array *inputIndices, + const OH_NN_UInt32Array *outputIndices); + +/** + * @brief Completes model composition. + * + * After the model topology is set up, call this method to indicate that the composition is complete. After this method is called, + * additional composition operations cannot be performed. If {@link OH_NNModel_AddTensor}, {@link OH_NNModel_AddOperation}, + * {@link OH_NNModel_SetTensorData}, and {@link OH_NNModel_SpecifyInputsAndOutputs} are called, + * {@link OH_NN_OPERATION_FORBIDDEN} is returned. \n + * + * Before calling {@link OH_NNModel_GetAvailableOperations} and {@link OH_NNCompilation_Construct}, + * you must call this method to complete composition. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); + +/** + * @brief Releases a model instance. + * + * This method needs to be called to release the model instance created by calling {@link OH_NNModel_Construct}. Otherwise, memory leak will occur. \n + * + * If model or *model is a null pointer, this method only prints warning logs and does not execute the release. \n + * + * @param model Double pointer to the {@link OH_NNModel} instance. After a model instance is destroyed, this method sets *model to a null pointer. + * @since 9 + * @version 1.0 + */ +void OH_NNModel_Destroy(OH_NNModel **model); + +/** + * @brief Queries whether the device supports operators in the model. The support status is indicated by the Boolean value. + * + * Queries whether underlying device supports operators in a model instance. The device is specified by deviceID, + * and the result is represented by the array pointed by isSupported. If the ith operator is supported, + * the value of (*isSupported)[i] is true. Otherwise, the value is false. \n + * + * After this method is successfully executed, (*isSupported) points to the bool array that records the operator support status. + * The operator quantity for the array length is the same as that for the model instance. The memory corresponding to this array is + * managed by Neural Network Runtime and is automatically destroyed after the model instance is destroyed or this method is called again. \n + * + * @param model Pointer to the {@link OH_NNModel} instance. + * @param deviceID Device ID to be queried, which can be obtained by using {@link OH_NNDevice_GetAllDevicesID}. + * @param isSupported Pointer to the bool array. When this method is called, (*isSupported) must be a null pointer. + * Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. + * @param opCount Number of operators in a model instance, corresponding to the length of the (*isSupported) array. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, + size_t deviceID, + const bool **isSupported, + uint32_t *opCount); + +#ifdef __cplusplus +} +#endif // __cplusplus + +/** @} */ +#endif // NEURAL_NETWORK_RUNTIME_H diff --git a/interfaces/kits/c/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h similarity index 35% rename from interfaces/kits/c/neural_network_runtime.h rename to interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h index b7740e1..44f302e 100644 --- a/interfaces/kits/c/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,24 +20,24 @@ * @brief Provides APIs of Neural Network Runtime for accelerating the model inference. * * @Syscap SystemCapability.Ai.NeuralNetworkRuntime - * @since 9 + * @since 11 * @version 1.0 */ /** - * @file neural_network_runtime.h + * @file neural_network_runtime_compat.h * - * @brief Defines the Neural Network Runtime APIs. The AI inference framework uses the Native APIs provided by Neural Network Runtime - * to construct and compile models and perform inference and computing on acceleration hardware. + * @brief The APIs defined in this document are all compatible APIs of the previous version, which will be deprecated after five versions. + * It is recommended to use the new APIs defined by neural_network_core.h and neural_network_runtime.h. * Note: Currently, the APIs of Neural Network Runtime do not support multi-thread calling. \n * * @library libneural_network_runtime.so - * @since 9 + * @since 11 * @version 1.0 */ -#ifndef NEURAL_NETWORK_RUNTIME_H -#define NEURAL_NETWORK_RUNTIME_H +#ifndef NEURAL_NETWORK_RUNTIME_COMPAT_H +#define NEURAL_NETWORK_RUNTIME_COMPAT_H #include "neural_network_runtime_type.h" @@ -45,384 +45,59 @@ extern "C" { #endif -/** - * @brief Creates a model instance of the {@link OH_NNModel} type and uses other APIs provided by OH_NNModel to construct the model instance. - * - * Before composition, call {@link OH_NNModel_Construct} to create a model instance. Based on the model topology, - * call the {@link OH_NNModel_AddTensor}, {@link OH_NNModel_AddOperation}, and {@link OH_NNModel_SetTensorData} methods - * to fill in the data and operator nodes of the model, and then call {@link OH_NNModel_SpecifyInputsAndOutputs} to specify the inputs and outputs of the model. - * After the model topology is constructed, call {@link OH_NNModel_Finish} to build the model. \n - * - * After a model instance is used, you need to destroy it by calling {@link OH_NNModel_Destroy} to avoid memory leak. \n - * - * @return Returns the pointer to a {@link OH_NNModel} instance. - * @since 9 - * @version 1.0 - */ -OH_NNModel *OH_NNModel_Construct(void); - /** * @brief Adds a tensor to a model instance. * * The data node and operator parameters in the Neural Network Runtime model are composed of tensors of the model. - * This method is used to add tensors to a model instance based on the tensor parameter. + * This method is used to add tensors to a model instance based on the tensor parameter. * The sequence of adding tensors is specified by the index value recorded in the model. The {@link OH_NNModel_SetTensorData}, {@link OH_NNModel_AddOperation}, * and {@link OH_NNModel_SpecifyInputsAndOutputs} methods specifies tensors based on the index value. \n * * Neural Network Runtime supports inputs and outputs of the dynamic shape. When adding a data node with a dynamic shape, - * you need to set the dimensions that support dynamic changes in tensor.dimensions to -1. + * you need to set the dimensions that support dynamic changes in tensor.dimensions to -1. * For example, if tensor.dimensions of a four-dimensional tensor is set to [1, -1, 2, 2], the second dimension supports dynamic changes. \n * * @param model Pointer to the {@link OH_NNModel} instance. - * @param tensor Pointer to the {@link OH_NN_Tensor} tensor. The tensor specifies the attributes of the tensor added to the model instance. + * @param tensor Pointer to the {@link OH_NN_Tensor} tensor. The tensor specifies the attributes of the tensor added to the model instance. * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNModel_AddTensorToModel} * @since 9 * @version 1.0 */ OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *tensor); -/** - * @brief Sets the tensor value. - * - * For tensors with constant values (such as model weights), you need to use this method in the composition phase. - * The index value of a tensor is determined by the sequence in which the tensor is added to the model. - * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @param index Index value of a tensor. - * @param dataBuffer Pointer to real data. - * @param length Length of the data buffer. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, const void *dataBuffer, size_t length); - -/** - * @brief Adds an operator to a model instance. - * - * This method is used to add an operator to a model instance. The operator type is specified by op, and - * the operator parameters, inputs, and outputs are specified by paramIndices, inputIndices, and outputIndices respectively. - * This method verifies the attributes of operator parameters and the number of input and output parameters. - * These attributes must be correctly set when {@link OH_NNModel_AddTensor} is called to add tensors. - * For details about the expected parameters, input attributes, and output attributes of each operator, see {@link OH_NN_OperationType}. \n - * - * paramIndices, inputIndices, and outputIndices store index values of tensors. - * Index values are determined by the sequence in which tensors are added to the model. - * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n - * - * If unnecessary parameters are added for adding an operator, this method returns {@link OH_NN_INVALID_PARAMETER}. - * If no operator parameter is set, the operator uses the default parameter value. - * For details about the default values, see {@link OH_NN_OperationType}. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @param op Specifies the type of an operator to be added. For details, see the enumerated values of {@link OH_NN_OperationType}. - * @param paramIndices Pointer to the OH_NN_UInt32Array instance, which is used to set operator parameters. - * @param inputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator input. - * @param outputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator output. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, - OH_NN_OperationType op, - const OH_NN_UInt32Array *paramIndices, - const OH_NN_UInt32Array *inputIndices, - const OH_NN_UInt32Array *outputIndices); - -/** - * @brief Specifies the inputs and outputs of a model. - * - * A tensor must be specified as the end-to-end inputs and outputs of a model instance. This type of tensor cannot be set - * using {@link OH_NNModel_SetTensorData}. The OH_NNExecutor method needs to be called in the execution phase to set the input and output data. \n - * - * The index value of a tensor is determined by the sequence in which the tensor is added to the model. - * For details about how to add a tensor, see {@link OH_NNModel_AddTensor}. \n - * - * Currently, the model inputs and outputs cannot be set asynchronously. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @param inputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator input. - * @param outputIndices Pointer to the OH_NN_UInt32Array instance, which is used to set the operator output. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, - const OH_NN_UInt32Array *inputIndices, - const OH_NN_UInt32Array *outputIndices); - -/** - * @brief Completes model composition. - * - * After the model topology is set up, call this method to indicate that the composition is complete. After this method is called, - * additional composition operations cannot be performed. If {@link OH_NNModel_AddTensor}, {@link OH_NNModel_AddOperation}, - * {@link OH_NNModel_SetTensorData}, and {@link OH_NNModel_SpecifyInputsAndOutputs} are called, - * {@link OH_NN_OPERATION_FORBIDDEN} is returned. \n - * - * Before calling {@link OH_NNModel_GetAvailableOperations} and {@link OH_NNCompilation_Construct}, - * you must call this method to complete composition. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); - -/** - * @brief Releases a model instance. - * - * This method needs to be called to release the model instance created by calling {@link OH_NNModel_Construct}. Otherwise, memory leak will occur. \n - * - * If model or *model is a null pointer, this method only prints warning logs and does not execute the release logic. \n - * - * @param model Level-2 pointer to the {@link OH_NNModel} instance. After a model instance is destroyed, this method sets *model to a null pointer. - * @since 9 - * @version 1.0 - */ -void OH_NNModel_Destroy(OH_NNModel **model); - -/** - * @brief Queries whether the device supports operators in the model. The support status is indicated by the Boolean value. - * - * Queries whether underlying device supports operators in a model instance. The device is specified by deviceID, - * and the result is represented by the array pointed by isSupported. If the ith operator is supported, - * the value of (*isSupported)[i] is true. Otherwise, the value is false. \n - * - * After this method is successfully executed, (*isSupported) points to the bool array that records the operator support status. - * The operator quantity for the array length is the same as that for the model instance. The memory corresponding to this array is - * managed by Neural Network Runtime and is automatically destroyed after the model instance is destroyed or this method is called again. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @param deviceID Device ID to be queried, which can be obtained by using {@link OH_NNDevice_GetAllDevicesID}. - * @param isSupported Pointer to the bool array. When this method is called, (*isSupported) must be a null pointer. - * Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. - * - * @param opCount Number of operators in a model instance, corresponding to the length of the (*isSupported) array. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, - size_t deviceID, - const bool **isSupported, - uint32_t *opCount); - - -/** - * @brief Creates a compilation instance of the {@link OH_NNCompilation} type. - * - * After the OH_NNModel module completes model construction, APIs provided by the OH_NNCompilation module pass the model - * to underlying device for compilation. This method creates a {@link OH_NNCompilation} instance - * based on the passed {@link OH_NNModel} instance. The {@link OH_NNCompilation_SetDevice} method is called - * to set the device to compile on, and {@link OH_NNCompilation_Build} is then called to complete compilation.\n - * - * In addition to computing device selection, the OH_NNCompilation module supports features such as model caching, performance preference, - * priority setting, and float16 computing, which can be implemented by the following methods: - * - {@link OH_NNCompilation_SetCache} - * - {@link OH_NNCompilation_SetPerformanceMode} - * - {@link OH_NNCompilation_SetPriority} - * - {@link OH_NNCompilation_EnableFloat16} \n - * - * After {@link OH_NNCompilation} is created by calling this method, the {@link OH_NNModel} instance can be released. \n - * - * @param model Pointer to the {@link OH_NNModel} instance. - * @return Returns the pointer to a {@link OH_NNCompilation} instance. - * @since 9 - * @version 1.0 - */ -OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model); - -/** - * @brief Specifies the device for model compilation and computing. - * - * In the compilation phase, you need to specify the device for model compilation and computing. Call {@link OH_NNDevice_GetAllDevicesID} - * to obtain available device IDs. Call {@link OH_NNDevice_GetType} and {@link OH_NNDevice_GetName} to obtain device information - * and pass target device IDs to this method for setting. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param deviceID Device ID. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID); - -/** - * @brief Set the cache directory and version of the compiled model. - * - * On the device that supports caching, a model can be saved as a cache file after being compiled at the device driver layer. - * The model can be directly read from the cache file in the next compilation, saving recompilation time. - * This method performs different operations based on the passed cache directory and version:\n - * - * - No file exists in the cache directory: - * Caches the compiled model to the directory and sets the cache version to version. \n - * - * - A complete cache file exists in the cache directory, and its version is version: - * Reads the cache file in the path and passes the data to the underlying device for conversion into executable model instances. \n - * - * - A complete cache file exists in the cache directory, and its version is earlier than version: - * When model compilation is complete on the underlying device, overwrites the cache file and changes the version number to version. \n - * - * - A complete cache file exists in the cache directory, and its version is later than version: - * Returns the {@link OH_NN_INVALID_PARAMETER} error code without reading the cache file. \n - * - * - The cache file in the cache directory is incomplete or you do not have the permission to access the cache file. - * Returns the {@link OH_NN_INVALID_FILE} error code. \n - * - * - The cache directory does not exist or you do not have the access permission. - * Returns the {@link OH_NN_INVALID_PATH} error code. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param cachePath Directory for storing model cache files. This method creates directories for different devices in the cachePath directory. - * You are advised to use a separate cache directory for each model. - * @param version Cache version. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const char *cachePath, uint32_t version); - -/** - * @brief Sets the performance mode for model computing. - * - * Neural Network Runtime allows you to set the performance mode for model computing to meet the requirements of low power consumption - * and ultimate performance. If this method is not called to set the performance mode in the compilation phase, the compilation instance assigns - * the {@link OH_NN_PERFORMANCE_NONE} mode for the model by default. In this case, the device performs computing in the default performance mode. \n - * - * If this method is called on the device that does not support the setting of the performance mode, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param performanceMode Performance mode. For details about the available performance modes, see {@link OH_NN_PerformanceMode}. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, - OH_NN_PerformanceMode performanceMode); - -/** - * @brief Sets the model computing priority. - * - * Neural Network Runtime allows you to set computing priorities for models. - * The priorities apply only to models created by the process with the same UID. - * The settings will not affect models created by processes with different UIDs on different devices. \n - * - * If this method is called on the device that does not support the priority setting, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param priority Priority. For details about the optional priorities, see {@link OH_NN_Priority}. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_NN_Priority priority); - -/** - * @brief Enables float16 for computing. - * - * Currently, Neural Network Runtime supports only float32 and int8. If this method is called on a device that supports float16, - * float16 will be used for computing the float32 model to reduce memory usage and execution time. \n - * - * If this method is called on the device that does not support float16, the {@link OH_NN_UNAVALIDABLE_DEVICE} error code is returned. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param enableFloat16 Indicates whether to enable float16. If this parameter is set to true, float16 inference is performed. - * If this parameter is set to false, float32 inference is performed. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, an error code is returned. - * For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16); - -/** - * @brief Compiles a model. - * - * After the compilation configuration is complete, call this method to return the compilation result. The compilation instance pushes the model and - * compilation options to the device for compilation. After this method is called, additional compilation operations cannot be performed. - * If the {@link OH_NNCompilation_SetDevice}, {@link OH_NNCompilation_SetCache}, {@link OH_NNCompilation_SetPerformanceMode}, - * {@link OH_NNCompilation_SetPriority}, and {@link OH_NNCompilation_EnableFloat16} methods are called, {@link OH_NN_OPERATION_FORBIDDEN} is returned. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation); - -/** - * @brief Releases the Compilation object. - * - * This method needs to be called to release the compilation instance created by calling {@link OH_NNCompilation_Construct}. Otherwise, memory leak will occur. \n - * - * If compilation or *compilation is a null pointer, this method only prints warning logs and does not execute the release logic. \n - * - * @param compilation Level-2 pointer to the {@link OH_NNCompilation} instance. After a compilation instance is destroyed, - * this method sets *compilation to a null pointer. - * @since 9 - * @version 1.0 - */ -void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); - - -/** - * @brief Creates an executor instance of the {@link OH_NNExecutor} type. - * - * This method constructs a model inference executor associated with the device based on the passed compiler. Use {@link OH_NNExecutor_SetInput} - * to set the model input data. After the input data is set, call {@link OH_NNExecutor_Run} to perform inference and then call - * {@link OH_NNExecutor_SetOutput} to obtain the computing result. \n - * - * After calling this method to create the {@link OH_NNExecutor} instance, you can release the {@link OH_NNCompilation} - * instance if you do not need to create any other executors. \n - * - * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @return Pointer to a {@link OH_NNExecutor} instance. - * @since 9 - * @version 1.0 - */ -OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation); - /** * @brief Sets the single input data for a model. * * This method copies the data whose length is specified by length (in bytes) in dataBuffer to the shared memory - * of the underlying device. inputIndex specifies the input to be set and tensor sets information such as the input shape, + * of the underlying device. inputIndex specifies the input to be set and tensor sets information such as the input shape, * type, and quantization parameters. \n * * Neural Network Runtime supports models with dynamical shape input. For fixed shape input and dynamic shape input scenarios, - * this method uses different processing policies. + * this method uses different processing policies. \n * * - Fixed shape input: The attributes of tensor must be the same as those of the tensor added by calling * {@link OH_NNModel_AddTensor} in the composition phase. * - Dynamic shape input: In the composition phase, because the shape is not fixed, each value in tensor.dimensions must be greater than * 0 in the method calls to determine the shape input in the calculation phase. When setting the shape, you can modify - * only the dimension whose value is -1. Assume that [-1, 224, 224, 3] is input as the the dimension of A in the composition phase. - * When this method is called, only the size of the first dimension can be modified, for example, to [3, 224, 224, 3]. + * only the dimension whose value is -1. Assume that [-1, 224, 224, 3] is input as the the dimension of A in the composition phase. + * When this method is called, only the size of the first dimension can be modified, for example, to [3, 224, 224, 3]. * If other dimensions are adjusted, {@link OH_NN_INVALID_PARAMETER} is returned. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * In input settings, the index value for the three inputs is {0, 1, 2}. \n * * @param tensor Sets the tensor corresponding to the input data. * @param dataBuffer Pointer to the input data. * @param length Length of the data buffer, in bytes. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNExecutor_RunSync} * @since 9 * @version 1.0 */ @@ -435,26 +110,28 @@ OH_NN_ReturnCode OH_NNExecutor_SetInput(OH_NNExecutor *executor, /** * @brief Sets the buffer for a single output of a model. * - * This method binds the buffer to which dataBuffer points to the output specified by outputIndex. + * This method binds the buffer to which dataBuffer points to the output specified by outputIndex. * The length of the buffer is specified by length. \n * * After {@link OH_NNExecutor_Run} is called to complete a single model inference, Neural Network Runtime compares - * the length of the buffer to which dataBuffer points with the length of the output data and returns different results + * the length of the buffer to which dataBuffer points with the length of the output data and returns different results * based on the actual situation. \n * * - If the buffer length is greater than or equal to the data length, the inference result is copied to the buffer and - * {@link OH_NN_SUCCESS} is returned. You can read the inference result from dataBuffer. + * {@link OH_NN_SUCCESS} is returned. You can read the inference result from dataBuffer. * - If the buffer length is smaller than the data length, {@link OH_NNExecutor_Run} returns {@link OH_NN_INVALID_PARAMETER} * and generates a log indicating that the buffer is too small. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} + * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} * is called. In output buffer settings, the index value for the three outputs is {0, 1, 2}. * @param dataBuffer Pointer to the output data. * @param length Length of the data buffer, in bytes. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNExecutor_RunSync} * @since 9 * @version 1.0 */ @@ -463,38 +140,16 @@ OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, void *dataBuffer, size_t length); -/** - * @brief Obtains the dimension information about the output tensor. - * - * After {@link OH_NNExecutor_Run} is called to complete a single inference, call this method to obtain the specified output dimension - * information and number of dimensions. It is commonly used in dynamic shape input and output scenarios. \n - * - * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * When {@link OH_NNExecutor_GetOutputShape} is called to obtain dimension information about the output tensor, - * outputIndices is {0, 1, 2}. - * - * @param shape Pointer to the int32_t array. The value of each element in the array is the length of the output tensor in each dimension. - * @param shapeLength Pointer to the uint32_t type. The number of output dimensions is returned. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, - uint32_t outputIndex, - int32_t **shape, - uint32_t *shapeLength); - /** * @brief Performs inference. * * Performs end-to-end inference and computing of the model on the device associated with the executor. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNExecutor_RunSync} * @since 9 * @version 1.0 */ @@ -503,16 +158,18 @@ OH_NN_ReturnCode OH_NNExecutor_Run(OH_NNExecutor *executor); /** * @brief Allocates shared memory to a single input on a device. * - * Neural Network Runtime provides a method for proactively allocating shared memory on a device. By specifying the executor and input index value, - * this method allocates shared memory whose size is specified by length on the device associated with a single input and returns the + * Neural Network Runtime provides a method for proactively allocating shared memory on a device. By specifying the executor and input index value, + * this method allocates shared memory whose size is specified by length on the device associated with a single input and returns the * operation result through the {@link OH_NN_Memory} instance. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * In the memory input application, the index value for the three inputs is {0, 1, 2}. * @param length Memory size to be applied for, in bytes. * @return Pointer to a {@link OH_NN_Memory} instance. + * @deprecated since 11 + * @useinstead {@link OH_NNTensor_CreateWithSize} * @since 9 * @version 1.0 */ @@ -521,16 +178,18 @@ OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_ /** * @brief Allocates shared memory to a single output on a device. * - * Neural Network Runtime provides a method for proactively allocating shared memory on a device. By specifying the executor and - * output index value, this method allocates shared memory whose size is specified by length on the device associated with + * Neural Network Runtime provides a method for proactively allocating shared memory on a device. By specifying the executor and + * output index value, this method allocates shared memory whose size is specified by length on the device associated with * a single output and returns the operation result through the {@link OH_NN_Memory} instance. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * In output memory application, the index value for the three outputs is {0, 1, 2}. * @param length Memory size to be applied for, in bytes. * @return Pointer to a {@link OH_NN_Memory} instance. + * @deprecated since 11 + * @useinstead {@link OH_NNTensor_CreateWithSize} * @since 9 * @version 1.0 */ @@ -540,16 +199,18 @@ OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32 * @brief Releases the input memory to which the {@link OH_NN_Memory} instance points. * * This method needs to be called to release the memory instance created by calling {@link OH_NNExecutor_AllocateInputMemory}. - * Otherwise, memory leak will occur. + * Otherwise, memory leak will occur. * The mapping between inputIndex and memory must be the same as that in memory instance creation. \n * * If memory or *memory is a null pointer, this method only prints warning logs and does not execute the release logic. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * In memory input release, the index value for the three inputs is {0, 1, 2}. - * @param memory Level-2 pointer to the {@link OH_NN_Memory} instance. After shared memory is destroyed, this method sets *memory to a null pointer. + * @param memory Double pointer to the {@link OH_NN_Memory} instance. After shared memory is destroyed, this method sets *memory to a null pointer. + * @deprecated since 11 + * @useinstead {@link OH_NNTensor_Destroy} * @since 9 * @version 1.0 */ @@ -558,16 +219,18 @@ void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputInd /** * @brief Releases the output memory to which the {@link OH_NN_Memory} instance points. * - * This method needs to be called to release the memory instance created by calling {@link OH_NNExecutor_AllocateOutputMemory}. Otherwise, memory leak will occur. + * This method needs to be called to release the memory instance created by calling {@link OH_NNExecutor_AllocateOutputMemory}. Otherwise, memory leak will occur. * The mapping between outputIndex and memory must be the same as that in memory instance creation. \n * * If memory or *memory is a null pointer, this method only prints warning logs and does not execute the release logic. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * In output memory release, the index value for the three outputs is {0, 1, 2}. - * @param memory Level-2 pointer to the {@link OH_NN_Memory} instance. After shared memory is destroyed, this method sets *memory to a null pointer. + * @param memory Double pointer to the {@link OH_NN_Memory} instance. After shared memory is destroyed, this method sets *memory to a null pointer. + * @deprecated since 11 + * @useinstead {@link OH_NNTensor_Destroy} * @since 9 * @version 1.0 */ @@ -576,18 +239,20 @@ void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputI /** * @brief Specifies the hardware shared memory pointed to by the {@link OH_NN_Memory} instance as the shared memory used by a single input. * - * In scenarios where memory needs to be managed by yourself, this method binds the execution input to the {@link OH_NN_Memory} memory instance. - * During computing, the underlying device reads the input data from the shared memory pointed to by the memory instance. + * In scenarios where memory needs to be managed by yourself, this method binds the execution input to the {@link OH_NN_Memory} memory instance. + * During computing, the underlying device reads the input data from the shared memory pointed to by the memory instance. * By using this method, concurrent execution of input setting, computing, and read can be implemented to improve inference efficiency of a data flow. \n * * @param executor Pointer to the {@link OH_NNExecutor} instance. - * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param inputIndex Input index value, which is in the same sequence of the data input when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of inputIndices is {1, 5, 9} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * When the input shared memory is specified, the index value for the three inputs is {0, 1, 2}. * @param tensor Pointer to {@link OH_NN_Tensor}, used to set the tensor corresponding to a single input. * @param memory Pointer to {@link OH_NN_Memory}. * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNExecutor_RunSync} * @since 9 * @version 1.0 */ @@ -599,17 +264,19 @@ OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, /** * @brief Specifies the hardware shared memory pointed to by the {@link OH_NN_Memory} instance as the shared memory used by a single output. * - * In scenarios where memory needs to be managed by yourself, this method binds the execution output to the {@link OH_NN_Memory} memory instance. - * When computing is performed, the underlying hardware directly writes the computing result to the shared memory to which the memory instance points. + * In scenarios where memory needs to be managed by yourself, this method binds the execution output to the {@link OH_NN_Memory} memory instance. + * When computing is performed, the underlying hardware directly writes the computing result to the shared memory to which the memory instance points. * By using this method, concurrent execution of input setting, computing, and read can be implemented to improve inference efficiency of a data flow. \n * * @param executor Executor. - * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. - * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * @param outputIndex Output Index value, which is in the same sequence of the data output when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. + * Assume that the value of outputIndices is {4, 6, 8} when {@link OH_NNModel_SpecifyInputsAndOutputs} is called. * When output shared memory is specified, the index value for the three outputs is {0, 1, 2}. * @param memory Pointer to {@link OH_NN_Memory}. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. + * @deprecated since 11 + * @useinstead {@link OH_NNExecutor_RunSync} * @since 9 * @version 1.0 */ @@ -617,75 +284,9 @@ OH_NN_ReturnCode OH_NNExecutor_SetOutputWithMemory(OH_NNExecutor *executor, uint32_t outputIndex, const OH_NN_Memory *memory); -/** - * @brief Destroys an executor instance to release the memory occupied by the executor. - * - * This method needs to be called to release the executor instance created by calling {@link OH_NNExecutor_Construct}. Otherwise, - * memory leak will occur. \n - * - * If executor or *executor is a null pointer, this method only prints warning logs and does not execute the release logic. \n - * - * @param executor Level-2 pointer to the {@link OH_NNExecutor} instance. - * @since 9 - * @version 1.0 - */ -void OH_NNExecutor_Destroy(OH_NNExecutor **executor); - - -/** - * @brief Obtains the ID of the device connected to Neural Network Runtime. - * - * Each device has a unique and fixed ID in Neural Network Runtime. This method returns device IDs on the current device through the uint32_t array. \n - * - * Device IDs are returned through the size_t array. Each element of the array is the ID of a single device. - * The array memory is managed by Neural Network Runtime. - * The data pointer is valid before this method is called next time. \n - * - * @param allDevicesID Pointer to the size_t array. The input *allDevicesID must be a null pointer. Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. - * @param deviceCount Pointer of the uint32_t type, which is used to return the length of (*allDevicesID). - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. - * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount); - -/** - * @brief Obtains the name of the specified device. - * - * deviceID specifies the device whose name will be obtained. The device ID needs to be obtained by calling {@link OH_NNDevice_GetAllDevicesID}. \n - * - * @param deviceID Device ID. - * @param name Pointer to the char array. The passed (*char) must be a null pointer. Otherwise, {@link OH_NN_INVALID_PARAMETER} is returned. - * The value of (*name) is a C-style string ended with '\0'. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name); - -/** - * @brief Obtains the type information of the specified device. - * - * deviceID specifies the device whose type will be obtained. Currently, Neural Network Runtime supports the following device types: - * - OH_NN_CPU: CPU device. - * - OH_NN_GPU: GPU device. - * - OH_NN_ACCELERATOR: machine learning dedicated accelerator. - * - OH_NN_OTHERS: other hardware types. \n - * - * @param deviceID Device ID. - * @param deviceType Pointer to the {@link OH_NN_DeviceType} instance. The device type information is returned. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. If the operation fails, - * an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType *deviceType); - #ifdef __cplusplus } #endif // __cplusplus /** @} */ -#endif // NEURAL_NETWORK_RUNTIME_H +#endif // NEURAL_NETWORK_RUNTIME_COMPAT_H diff --git a/interfaces/kits/c/neural_network_runtime_type.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h similarity index 96% rename from interfaces/kits/c/neural_network_runtime_type.h rename to interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h index 00aefb6..03c9fe9 100644 --- a/interfaces/kits/c/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h @@ -21,17 +21,17 @@ * * @Syscap SystemCapability.Ai.NeuralNetworkRuntime * @since 9 - * @version 1.0 + * @version 2.0 */ /** * @file neural_network_runtime_type.h * - * @brief Defines the structure and enumeration for Neural Network Runtime. + * @brief Defines the structure and enumeration. * * @library libneural_network_runtime.so * @since 9 - * @version 1.0 + * @version 2.0 */ #ifndef NEURAL_NETWORK_RUNTIME_TYPE_H @@ -45,7 +45,7 @@ extern "C" { #endif /** - * @brief Defines the handles of models for Neural Network Runtime. + * @brief Defines the handles of models. * * @since 9 * @version 1.0 @@ -53,7 +53,7 @@ extern "C" { typedef struct OH_NNModel OH_NNModel; /** - * @brief Defines the compiler handle for Neural Network Runtime. + * @brief Defines the compiler handle. * * @since 9 * @version 1.0 @@ -61,13 +61,37 @@ typedef struct OH_NNModel OH_NNModel; typedef struct OH_NNCompilation OH_NNCompilation; /** - * @brief Defines the executor handle for Neural Network Runtime. + * @brief Defines the executor handle. * * @since 9 * @version 1.0 */ typedef struct OH_NNExecutor OH_NNExecutor; +/** + * @brief Defines the quantization parameter handle. + * + * @since 11 + * @version 1.0 + */ +typedef struct NN_QuantParam NN_QuantParam; + +/** + * @brief Defines the tensor descriptor handle. + * + * @since 11 + * @version 1.0 + */ +typedef struct NN_TensorDesc NN_TensorDesc; + +/** + * @brief Defines the tensor handle. + * + * @since 11 + * @version 1.0 + */ +typedef struct NN_Tensor NN_Tensor; + /** * @brief Defines the hardware performance mode. * @@ -105,10 +129,10 @@ typedef enum { } OH_NN_Priority; /** - * @brief Defines error codes for Neural Network Runtime. + * @brief Defines error codes. * * @since 9 - * @version 1.0 + * @version 2.0 */ typedef enum { /** The operation is successful. */ @@ -125,14 +149,69 @@ typedef enum { OH_NN_NULL_PTR = 5, /** Invalid file. */ OH_NN_INVALID_FILE = 6, - /** A hardware error occurs, for example, HDL service crash. */ - OH_NN_UNAVALIDABLE_DEVICE = 7, + /** A hardware error occurs, for example, HDL service crash. + * @deprecated since 11 + * @useinstead {@link OH_NN_UNAVAILABLE_DEVICE} + */ + OH_NN_UNAVALIABLE_DEVICE = 7, /** Invalid path. */ - OH_NN_INVALID_PATH = 8 + OH_NN_INVALID_PATH = 8, + /** A hardware error occurs, for example, HDL service crash. + * @since 11 + */ + OH_NN_UNAVAILABLE_DEVICE = 9, + /** Timeout. + * @since 11 + */ + OH_NN_TIMEOUT = 10, + /** Unsupported. + * @since 11 + */ + OH_NN_UNSUPPORTED = 11, + /** Connection Exception. + * @since 11 + */ + OH_NN_CONNECTION_EXCEPTION = 12, + /** Save cache exception. + * @since 11 + */ + OH_NN_SAVE_CACHE_EXCEPTION = 13, + /** Dynamic shape. + * @since 11 + */ + OH_NN_DYNAMIC_SHAPE = 14 } OH_NN_ReturnCode; + +/** + * @brief Defines the callback function handle for the post-process when the asynchronous execution has been done. + * + * Use the first argument userData<\b> to identify the asynchronous execution you want to get. + * It is the argument userData<\b> passed to {@link OH_NNExecutor_RunAsync}. \n + * Use the second argument errCode<\b> of type {@link OH_NN_ReturnCode} to get the error code returned by the asynchronous execution. \n + * + * @param userData Asynchronous execution identifier, which is the argument userData<\b> passed to {@link OH_NNExecutor_RunAsync}. + * @param errCode Error code {@link OH_NN_ReturnCode} returned by the asynchronous execution. + * @param output Output tensors {@link NN_Tensor} of the model, which are same as argument outputTensor<\b> passed to {@link OH_NNExecutor_RunAsync} + * @param outputCount Output tensor count, which are same as argument outputCount<\b> passed to {@link OH_NNExecutor_RunAsync} + * @since 11 + * @version 1.0 + */ +typedef void (*NN_OnRunDone)(void*, OH_NN_ReturnCode, void* [], int32_t); + +/** + * @brief Defines the callback function handle for the post-process when the device driver service is dead during asynchronous execution. + * + * You should recompile the model if this callback function is called. \n + * + * @param userData Asynchronous execution identifier, which is the argument userData<\b> passed to {@link OH_NNExecutor_RunAsync}. + * @since 11 + * @version 1.0 + */ +typedef void (*NN_OnServiceDied)(void*); + /** - * @brief Defines activation function types in the fusion operator for Neural Network Runtime. + * @brief Defines activation function types in the fusion operator. * * @since 9 * @version 1.0 @@ -150,7 +229,7 @@ typedef enum : int8_t { * @brief Defines the layout type of tensor data. * * @since 9 - * @version 1.0 + * @version 2.0 */ typedef enum { /** The tensor does not have a specific layout type (such as scalar or vector). */ @@ -158,11 +237,15 @@ typedef enum { /** The tensor arranges data in NCHW format.*/ OH_NN_FORMAT_NCHW = 1, /** The tensor arranges data in NHWC format.*/ - OH_NN_FORMAT_NHWC = 2 + OH_NN_FORMAT_NHWC = 2, + /** The tensor arranges data in ND format. + * @since 11 + */ + OH_NN_FORMAT_ND = 3 } OH_NN_Format; /** - * @brief Defines device types supported by Neural Network Runtime. + * @brief Defines device types. * * @since 9 * @version 1.0 @@ -179,7 +262,7 @@ typedef enum { } OH_NN_DeviceType; /** - * @brief Defines tensor data types supported by Neural Network Runtime. + * @brief Defines tensor data types. * * @since 9 * @version 1.0 @@ -215,7 +298,7 @@ typedef enum { /** - * @brief Defines operator types supported by Neural Network Runtime. + * @brief Defines operator types. * * @since 9 * @version 1.0 @@ -1720,6 +1803,8 @@ typedef struct OH_NN_UInt32Array { \end{cases} \f] * + * @deprecated since 11 + * @useinstead {@link NN_QuantParam} * @since 9 * @version 1.0 */ @@ -1744,6 +1829,8 @@ typedef struct OH_NN_QuantParam { * It is usually used to construct data nodes and operator parameters in a model graph. When constructing a tensor, * you need to specify the data type, number of dimensions, dimension information, and quantization information. * + * @deprecated since 11 + * @useinstead {@link NN_TensorDesc} * @since 9 * @version 1.0 */ @@ -1766,6 +1853,8 @@ typedef struct OH_NN_Tensor { /** * @brief Defines the memory structure. * + * @deprecated since 11 + * @useinstead {@link NN_Tensor} * @since 9 * @version 1.0 */ -- Gitee From 11aeceab6104eb2d3e2ff06cc7790449e0b2ba2a Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 12 Dec 2023 15:29:48 +0800 Subject: [PATCH 02/11] update nnrt-new, 1212 Signed-off-by: maoyong --- common/utils.h | 5 +- .../native/{device_registrar.h => backend.h} | 48 +- frameworks/native/backend_manager.cpp | 97 ++ .../{device_manager.h => backend_manager.h} | 65 +- frameworks/native/backend_registrar.cpp | 18 + frameworks/native/backend_registrar.h | 27 + frameworks/native/compilation.cpp | 845 ------------------ frameworks/native/compilation.h | 92 +- .../native/{device_discover.h => compiler.h} | 37 +- frameworks/native/cpp_type.h | 2 +- frameworks/native/device.h | 9 +- frameworks/native/device_manager.cpp | 177 ---- frameworks/native/device_registrar.cpp | 32 - frameworks/native/neural_network_core.cpp | 515 +++++++++++ frameworks/native/nnbackend.cpp | 240 +++++ frameworks/native/nnbackend.h | 48 + frameworks/native/nncompiled_cache.cpp | 391 ++++++++ frameworks/native/nncompiled_cache.h | 78 ++ frameworks/native/nncompiler.cpp | 723 +++++++++++++++ frameworks/native/nncompiler.h | 70 ++ ..._v1_0.cpp => register_hdi_device_v1_0.cpp} | 41 +- ..._v2_0.cpp => register_hdi_device_v2_0.cpp} | 37 +- frameworks/native/utils.cpp | 12 + .../libneural_network_runtime.ndk.json | 95 -- test/system_test/common/nnrt_test.h | 2 +- test/system_test/device_test.cpp | 2 +- test/system_test/end_to_end_test.cpp | 2 +- test/system_test/end_to_end_test.h | 2 +- .../common/v1_0/inner_model_mock_device.cpp | 2 +- .../common/v2_0/inner_model_mock_device.cpp | 2 +- .../device_manager/device_manager_test.cpp | 4 +- .../v1_0/hdi_device/hdi_device_test.cpp | 22 +- .../hdi_prepared_model_test.cpp | 4 +- .../v1_0/inner_model/inner_model_test.cpp | 2 +- .../neural_network_runtime_test.cpp | 4 +- .../neural_network_runtime_test.h | 2 +- .../device_manager/device_manager_test.cpp | 4 +- .../v2_0/hdi_device/hdi_device_test.cpp | 20 +- .../hdi_prepared_model_test.cpp | 4 +- .../v2_0/inner_model/inner_model_test.cpp | 2 +- .../neural_network_runtime_test.cpp | 4 +- .../neural_network_runtime_test.h | 2 +- 42 files changed, 2430 insertions(+), 1360 deletions(-) rename frameworks/native/{device_registrar.h => backend.h} (35%) create mode 100644 frameworks/native/backend_manager.cpp rename frameworks/native/{device_manager.h => backend_manager.h} (35%) create mode 100644 frameworks/native/backend_registrar.cpp create mode 100644 frameworks/native/backend_registrar.h delete mode 100644 frameworks/native/compilation.cpp rename frameworks/native/{device_discover.h => compiler.h} (34%) delete mode 100644 frameworks/native/device_manager.cpp delete mode 100644 frameworks/native/device_registrar.cpp create mode 100644 frameworks/native/nnbackend.cpp create mode 100644 frameworks/native/nnbackend.h create mode 100644 frameworks/native/nncompiled_cache.cpp create mode 100644 frameworks/native/nncompiled_cache.h create mode 100644 frameworks/native/nncompiler.cpp create mode 100644 frameworks/native/nncompiler.h rename frameworks/native/{device_discover_v1_0.cpp => register_hdi_device_v1_0.cpp} (61%) rename frameworks/native/{device_discover_v2_0.cpp => register_hdi_device_v2_0.cpp} (72%) create mode 100644 frameworks/native/utils.cpp delete mode 100644 interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json diff --git a/common/utils.h b/common/utils.h index 7430ad0..e8a957f 100644 --- a/common/utils.h +++ b/common/utils.h @@ -16,6 +16,7 @@ #ifndef NEURAL_NETWORK_RUNTIME_UTILS_H #define NEURAL_NETWORK_RUNTIME_UTILS_H +#include #include #include "log.h" @@ -33,7 +34,9 @@ std::shared_ptr CreateSharedPtr(Args&&... args) return nullptr; } return tPtr; -} +}; + +std::string GenUniqueName(const std::string&, const std::string&, const std::string&); } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/device_registrar.h b/frameworks/native/backend.h similarity index 35% rename from frameworks/native/device_registrar.h rename to frameworks/native/backend.h index 521a075..1d3b21d 100644 --- a/frameworks/native/device_registrar.h +++ b/frameworks/native/backend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,29 +13,39 @@ * limitations under the License. */ -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_REGISTRAR_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_REGISTRAR_H +#ifndef NEURAL_NETWORK_CORE_BACKEND_H +#define NEURAL_NETWORK_CORE_BACKEND_H -#include +#include #include -#include -#include "device.h" +#include "compilation.h" +#include "compiler.h" +#include "executor.h" +#include "tensor.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -using CreateDevice = std::function()>; - -class DeviceRegistrar { +class Backend { public: - DeviceRegistrar(const CreateDevice creator); - ~DeviceRegistrar() = default; -}; + Backend() = default; + virtual ~Backend() = default; + + virtual size_t GetBackendID() const = 0; + virtual OH_NN_ReturnCode GetBackendName(std::string& name) const = 0; + virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; + virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; -#define REGISTER_DEVICE(deviceName, vendorName, creator) \ - namespace { \ - static OHOS::NeuralNetworkRuntime::DeviceRegistrar g_##deviceName##_##vendorName##_device_registrar(creator); \ - } // namespace -} // namespace NeuralNetworkRuntime -} // OHOS -#endif // NEURAL_NETWORK_RUNTIME_DEVICE_REGISTRAR_H \ No newline at end of file + virtual Compiler* CreateCompiler(Compilation* compilation) = 0; + virtual OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) = 0; + + virtual Executor* CreateExecutor(Compilation* compilation) = 0; + virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; + + virtual Tensor* CreateTensor(TensorDesc* desc) = 0; + virtual OH_NN_ReturnCode DestroyTensor(Tensor* tensor) = 0; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_CORE_BACKEND_H diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp new file mode 100644 index 0000000..64a29d9 --- /dev/null +++ b/frameworks/native/backend_manager.cpp @@ -0,0 +1,97 @@ +#include "backend_manager.h" + +#include +#include "common/log.h" +#include "cpp_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +BackendManager::~BackendManager() +{ + m_backends.clear(); + m_backendIDs.clear(); + m_tmpBackendIds.clear(); +} + +const std::vector& BackendManager::GetAllBackendsID() +{ + m_tmpBackendIds.clear(); + std::shared_ptr backend {nullptr}; + for (auto iter = m_backends.begin(); iter != m_backends.end(); ++iter) { + backend = iter->second; + if (!IsValidBackend(backend)) { + continue; + } + m_tmpBackendIds.emplace_back(iter->first); + } + return m_tmpBackendIds; +} + +std::shared_ptr BackendManager::GetBackend(size_t backendID) const +{ + auto iter = m_backends.find(backendID); + if (iter == m_backends.end()) { + LOGE("[BackendManager] GetBackend failed, not find backendId=%{public}zu", backendID); + return nullptr; + } + + return iter->second; +} + +const std::string& BackendManager::GetBackendName(size_t backendID) +{ + m_tmpBackendName.clear(); + auto iter = m_backends.find(backendID); + if (iter == m_backends.end()) { + LOGE("[BackendManager] GetBackendName failed, backendID %{public}zu is not registered.", backendID); + return m_tmpBackendName; + } + + OH_NN_ReturnCode ret = iter->second->GetBackendName(m_tmpBackendName); + if (ret != OH_NN_SUCCESS) { + LOGE("[BackendManager] GetBackendName failed, fail to get backendName from backend."); + } + + return m_tmpBackendName; +} + +OH_NN_ReturnCode BackendManager::RegisterBackend(std::function()> creator) +{ + auto regBackend = creator(); + if (regBackend == nullptr) { + LOGE("[BackendManager] RegisterBackend failed, fail to create backend."); + return OH_NN_FAILED; + } + + if (!IsValidBackend(regBackend)) { + LOGE("[BackendManager] RegisterBackend failed, backend is not available."); + return OH_NN_UNAVAILABLE_DEVICE; + } + + size_t backendID = regBackend->GetBackendID(); + + const std::lock_guard lock(m_mtx); + auto setResult = m_backendIDs.emplace(backendID); + if (!setResult.second) { + LOGE("[BackendManager] RegisterBackend failed, backend already exists, cannot register again. " + "backendID=%{public}zu", backendID); + return OH_NN_FAILED; + } + + m_backends.emplace(backendID, regBackend); + return OH_NN_SUCCESS; +} + +bool BackendManager::IsValidBackend(std::shared_ptr backend) const +{ + DeviceStatus status = UNKNOWN; + + OH_NN_ReturnCode ret = backend->GetBackendStatus(status); + if (ret != OH_NN_SUCCESS || status == UNKNOWN || status == OFFLINE) { + return false; + } + + return true; +} +} // NeuralNetworkCore +} // OHOS \ No newline at end of file diff --git a/frameworks/native/device_manager.h b/frameworks/native/backend_manager.h similarity index 35% rename from frameworks/native/device_manager.h rename to frameworks/native/backend_manager.h index 4d8b9fb..32d3fa5 100644 --- a/frameworks/native/device_manager.h +++ b/frameworks/native/backend_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,59 +13,52 @@ * limitations under the License. */ -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H +#ifndef NEURAL_NETWORK_CORE_BACKEND_MANAGER_H +#define NEURAL_NETWORK_CORE_BACKEND_MANAGER_H #include -#include -#include +#include #include -#include +#include +#include #include +#include -#include "device.h" -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "backend.h" namespace OHOS { namespace NeuralNetworkRuntime { -class DeviceManager { +class BackendManager { public: - const std::vector& GetAllDeviceId(); - std::shared_ptr GetDevice(size_t deviceId) const; - const std::string& GetDeviceName(size_t deviceId); + const std::vector& GetAllBackendsID(); + std::shared_ptr GetBackend(size_t backendID) const; + const std::string& GetBackendName(size_t backendID); - // register device from C++ API - OH_NN_ReturnCode RegisterDevice(std::function()> creator); + // Register backend by C++ API + OH_NN_ReturnCode RegisterBackend(std::function()> creator); - static DeviceManager& GetInstance() + static BackendManager& GetInstance() { - static DeviceManager instance; - instance.DiscoverHDIDevices(); + static BackendManager instance; return instance; } private: - DeviceManager() = default; - DeviceManager(const DeviceManager&) = delete; - DeviceManager& operator=(const DeviceManager&) = delete; - - void AddDevice(const std::string& deviceName, const std::string& vendorName, - const std::string& version, std::shared_ptr device); - void DiscoverHDIDevices(); - std::string GenUniqueName( - const std::string& deviceName, const std::string& vendorName, const std::string& version) const; - bool IsValidDevice(std::shared_ptr device) const; + BackendManager() = default; + BackendManager(const BackendManager&) = delete; + BackendManager& operator=(const BackendManager&) = delete; + virtual ~BackendManager(); + bool IsValidBackend(std::shared_ptr backend) const; private: - std::unordered_set m_uniqueName; - // key is device id, it is the unique number. - std::unordered_map> m_devices; + std::unordered_set m_backendIDs; + // key is the name of backend. + std::unordered_map> m_backends; std::mutex m_mtx; - std::string m_tmpDeviceName; - std::vector m_tmpDeviceIds; + std::string m_tmpBackendName; + std::vector m_tmpBackendIds; }; -} // namespace NeuralNetworkRuntime -} // namespace OHOS - -#endif // NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H \ No newline at end of file +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_CORE_BACKEND_MANAGER_H diff --git a/frameworks/native/backend_registrar.cpp b/frameworks/native/backend_registrar.cpp new file mode 100644 index 0000000..99ec5ce --- /dev/null +++ b/frameworks/native/backend_registrar.cpp @@ -0,0 +1,18 @@ +#include "backend_registrar.h" + +#include "common/log.h" +#include "backend_manager.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +BackendRegistrar::BackendRegistrar(const CreateBackend creator) +{ + auto& backendManager = BackendManager::GetInstance(); + OH_NN_ReturnCode ret = backendManager.RegisterBackend(creator); + if (ret != OH_NN_SUCCESS) { + LOGW("[BackendRegistrar] Register backend failed. ErrorCode=%{public}d", ret); + } +} +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/backend_registrar.h b/frameworks/native/backend_registrar.h new file mode 100644 index 0000000..6646764 --- /dev/null +++ b/frameworks/native/backend_registrar.h @@ -0,0 +1,27 @@ +#include +#include +#include + +#include "backend.h" + +#ifndef NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H +#define NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H + +namespace OHOS { +namespace NeuralNetworkRuntime { +using CreateBackend = std::function()>; + +class BackendRegistrar { +public: + explicit BackendRegistrar(const CreateBackend creator); + ~BackendRegistrar() = default; +}; + +#define REGISTER_BACKEND(backend, creator) \ + namespace { \ + static OHOS::NeuralNetworkRuntime::BackendRegistrar g_##backendName##_backend_registrar(creator); \ + } // namespace +} // NeuralNetworkRuntime +} // OHOS + +#endif // NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H \ No newline at end of file diff --git a/frameworks/native/compilation.cpp b/frameworks/native/compilation.cpp deleted file mode 100644 index eb8b2a3..0000000 --- a/frameworks/native/compilation.cpp +++ /dev/null @@ -1,845 +0,0 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "compilation.h" - -#include -#include -#include -#include -#include -#include - -#include "common/utils.h" -#include "common/scoped_trace.h" -#include "validation.h" -#include "device_manager.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -constexpr int MAX_MODEL_SIZE = 200 * 1024 * 1024; // 200MB -constexpr int OCT_UNIT = 8; -constexpr int NULL_PTR_LENGTH = 0; -constexpr int NUMBER_CACHE_INFO_MEMBERS = 3; - -// CRC16 Table is created based on the Polynomial of G(x) = x^16 + x^12 + x^15 + 1 and -// CRC register initialization value of "0" (0x0000) -static const unsigned short CRC16_TAB[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -Compilation::Compilation(const InnerModel* innerModel) - : m_liteGraph(innerModel->GetLiteGraphs()), - m_inputTensors(innerModel->GetInputTensors()), - m_outputTensors(innerModel->GetOutputTensors()), - m_metaGraph(innerModel->GetMetaGraph()), - m_quantBuffer(innerModel->GetQuantBuffer()), - m_modelName(innerModel->GetModelName()) {} - -OH_NN_ReturnCode Compilation::SetDevice(size_t deviceId) -{ - if (m_isBuild) { - LOGE("Cannot set deviceId after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - auto& deviceManager = DeviceManager::GetInstance(); - std::shared_ptr availableDevice = deviceManager.GetDevice(deviceId); - if (availableDevice == nullptr) { - LOGE("[Compilation] DeviceId does not exist, deviceId=%zu", deviceId); - return OH_NN_INVALID_PARAMETER; - } - - std::vector supportedList; - OH_NN_ReturnCode ret = availableDevice->GetSupportedOperation(m_liteGraph, supportedList); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] SetDevice failed, error happened when getting supported operation."); - return ret; - } - - for (bool isSupport : supportedList) { - if (!isSupport) { - LOGE("[Compilation] SetDevice failed, current device not support the model, device id: %zu.", deviceId); - return OH_NN_FAILED; - } - } - - bool supportDynamic; - ret = availableDevice->IsDynamicInputSupported(supportDynamic); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] SetDevice failed, error happened when checking whether device supports dynamic input."); - return ret; - } - - if (IsDynamicShape() && (!supportDynamic)) { - LOGE("[Compilation] SetDevice failed." - "The device does not support dynamic shape inputs, but the model has dynamic inputs."); - return OH_NN_FAILED; - } - - m_device = availableDevice; - m_deviceId = deviceId; - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::SetCacheDir(const std::string& cacheModelPath, uint32_t version) -{ - if (m_isBuild) { - LOGE("Cannot set cache after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (m_device == nullptr) { - LOGE("The parameter of m_device is nullptr, please call SetDevice function before calling SetCacheDir."); - return OH_NN_OPERATION_FORBIDDEN; - } - - bool isSupportedCache {false}; - OH_NN_ReturnCode ret = m_device->IsModelCacheSupported(isSupportedCache); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Fail to query whether the device is available to save cache model."); - return ret; - } - - if (!isSupportedCache) { - LOGE("[Compilation] The device is unavailable to save cache model."); - return OH_NN_OPERATION_FORBIDDEN; - } - - char realPathRes[PATH_MAX]; - const char* filePath = realpath(cacheModelPath.c_str(), realPathRes); - if (filePath == nullptr) { - LOGE("[Compilation] The cache model path is invalid."); - return OH_NN_INVALID_PARAMETER; - } - - struct stat fileInfo; - if (stat(filePath, &fileInfo) != 0) { - LOGE("[Compilation] The cache directory does not exist or cannot be accessed."); - return OH_NN_INVALID_PARAMETER; - } - - if (!(fileInfo.st_mode & S_IFDIR)) { - LOGE("[Compilation] The cache model path is not a directory."); - return OH_NN_INVALID_PARAMETER; - } - - m_cachePath = (std::string)filePath + "/"; - m_version = version; - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::SetPerformance(OH_NN_PerformanceMode performance) -{ - if (m_isBuild) { - LOGE("[Compilation] Cannot set performance after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (m_device == nullptr) { - LOGE("Cannot set performance before set device, please set device first"); - return OH_NN_OPERATION_FORBIDDEN; - } - - bool isSupportedPerformance {false}; - OH_NN_ReturnCode ret = m_device->IsPerformanceModeSupported(isSupportedPerformance); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Call device %zu failed.", m_deviceId); - return ret; - } - - if (!isSupportedPerformance) { - LOGE("[Compilation] This device %zu is not support performance setting.", m_deviceId); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (!Validation::ValidatePerformanceMode(performance)) { - LOGE("[Compilation] SetPerformance passed invalid performance=%d", performance); - return OH_NN_INVALID_PARAMETER; - } - - m_performance = performance; - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::SetPriority(OH_NN_Priority priority) -{ - if (m_isBuild) { - LOGE("[Compilation] Cannot set priority after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (m_device == nullptr) { - LOGE("Cannot set priority before set device, please set device first"); - return OH_NN_OPERATION_FORBIDDEN; - } - - bool isSupportedPriority {false}; - OH_NN_ReturnCode ret = m_device->IsPrioritySupported(isSupportedPriority); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Call device %zu failed.", m_deviceId); - return ret; - } - - if (!isSupportedPriority) { - LOGE("[Compilation] This device %zu is not support priority setting.", m_deviceId); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (!Validation::ValidatePriority(priority)) { - LOGE("[Compilation] SetPriority passed invalid priority=%d", priority); - return OH_NN_INVALID_PARAMETER; - } - - m_priority = priority; - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::SetEnableFp16(bool isFp16) -{ - if (m_isBuild) { - LOGE("[Compilation] Cannot enable float16 after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (m_device == nullptr) { - LOGE("Cannot set enable fp16 before set device, please set device first"); - return OH_NN_OPERATION_FORBIDDEN; - } - - bool isSupportedFp16 {false}; - OH_NN_ReturnCode ret = m_device->IsFloat16PrecisionSupported(isSupportedFp16); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Call device %zu failed.", m_deviceId); - return ret; - } - - if (!isSupportedFp16) { - LOGE("[Compilation] This device %zu is not support float16 precision setting.", m_deviceId); - return OH_NN_OPERATION_FORBIDDEN; - } - - m_enableFp16 = isFp16; - return OH_NN_SUCCESS; -} - -unsigned short Compilation::GetCrc16(const unsigned char* buffer, size_t length) const -{ - unsigned short crc16 = 0; - for (size_t i = 0; i < length; ++i) { - uint8_t tableIndex = ((crc16 >> OCT_UNIT) ^ *buffer++) & 0x00ff; - crc16 = (crc16 << OCT_UNIT) ^ CRC16_TAB[tableIndex]; - } - return crc16; -} - -OH_NN_ReturnCode Compilation::GenerateCacheInfo(uint32_t cacheSize, std::unique_ptr& cacheInfo) const -{ - std::string cacheInfoPath = m_cachePath + m_modelName + "cache_info.nncache"; - std::ofstream cacheInfoStream(cacheInfoPath, std::ios::binary | std::ios::out | std::ios::trunc); - if (cacheInfoStream.fail()) { - LOGE("[Compilation] Model cache info file is invalid."); - return OH_NN_INVALID_FILE; - } - - if (!cacheInfoStream.write(reinterpret_cast(cacheInfo.get()), cacheSize)) { - LOGE("[Compilation] Fail to write cache info."); - cacheInfoStream.close(); - return OH_NN_FAILED; - } - - cacheInfoStream.close(); - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::GenerateCacheModel(size_t cacheNumber, std::unique_ptr& cacheInfo, - std::vector modelBuffer) const -{ - auto cacheInfoPtr = cacheInfo.get(); - *cacheInfoPtr++ = static_cast(cacheNumber); - *cacheInfoPtr++ = static_cast(m_version); - *cacheInfoPtr++ = static_cast(m_deviceId); - for (uint32_t i = 0; i < cacheNumber; ++i) { - std::string cacheModelFile = m_cachePath + m_modelName + std::to_string(i) + ".nncache"; - std::ofstream cacheModelStream(cacheModelFile, std::ios::binary | std::ios::out | std::ios::trunc); - if (cacheModelStream.fail()) { - LOGE("[Compilation] Model cache file is invalid."); - return OH_NN_INVALID_FILE; - } - - uint64_t checkSum = static_cast(GetCrc16(static_cast(modelBuffer[i].data), - modelBuffer[i].length)); - *cacheInfoPtr++ = checkSum; - if (!cacheModelStream.write(static_cast(modelBuffer[i].data), modelBuffer[i].length)) { - LOGE("[Compilation] Fail to write cache model."); - cacheModelStream.close(); - return OH_NN_FAILED; - }; - - cacheModelStream.close(); - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::GenerateCacheFiles(const std::vector& modelBuffer) const -{ - const size_t cacheNumber = modelBuffer.size(); - uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber; - std::unique_ptr cacheInfo = std::make_unique(cacheSize); - if (cacheInfo == nullptr) { - LOGE("Fail to create cacheInfo instance."); - return OH_NN_MEMORY_ERROR; - } - - OH_NN_ReturnCode ret = GenerateCacheModel(cacheNumber, cacheInfo, modelBuffer); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - uint32_t infoCharNumber = cacheSize * sizeof(uint64_t); - ret = GenerateCacheInfo(infoCharNumber, cacheInfo); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::GetCacheFileLength(std::ifstream& ifs, int& fsize) const -{ - ifs.seekg(0, std::ios::end); - if (!ifs.good()) { - LOGE("[Compilation] Fail to set the position of the next character to be extracted from the input stream."); - return OH_NN_INVALID_FILE; - } - - int handleValue = ifs.tellg(); - if (handleValue == -1) { - LOGE("[Compilation] Unable to get position of the input stream."); - return OH_NN_INVALID_FILE; - } - - if ((handleValue > MAX_MODEL_SIZE) || (handleValue == NULL_PTR_LENGTH)) { - LOGE("[Compilation] Unable to read huge or empty input stream, get cache file size=%d", handleValue); - return OH_NN_INVALID_FILE; - } - - fsize = handleValue; - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::ReadCacheModelFile(const std::string& file, Buffer& modelBuffer) const -{ - // file is validated outside. - std::ifstream ifs(file.c_str(), std::ios::in | std::ios::binary); - if (!ifs) { - LOGE("[Compilation] Fail to open cache file."); - return OH_NN_INVALID_FILE; - } - - int fsize {-1}; - OH_NN_ReturnCode ret = GetCacheFileLength(ifs, fsize); - if (ret != OH_NN_SUCCESS) { - ifs.close(); - return ret; - } - - ifs.seekg(0, std::ios::beg); - if (!ifs.good()) { - LOGE("[Compilation] Fail to set the position of the next character to be extracted" - "from the cache model stream."); - ifs.close(); - return OH_NN_FAILED; - } - - char* ptr = static_cast(m_device->AllocateBuffer(fsize)); - if (ptr == nullptr) { - LOGE("[Compilation] Fail to create file buffer."); - ifs.close(); - return OH_NN_NULL_PTR; - } - - ifs.read(ptr, fsize); - if (!ifs.good()) { - LOGE("[Compilation] Fail to read the characters from the cache model stream."); - ifs.close(); - m_device->ReleaseBuffer(ptr); - ptr = nullptr; - return OH_NN_FAILED; - } - - ifs.close(); - modelBuffer.data = ptr; - modelBuffer.length = static_cast(fsize); // fsize should be non-negative, safe to cast. - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::CheckCacheInfo(ModelCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const -{ - // cacheInfoPath is validated outside. - std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary); - if (!infoCacheFile) { - LOGE("[Compilation] Opening cache info file failed."); - return OH_NN_INVALID_FILE; - } - - int charNumber = NUMBER_CACHE_INFO_MEMBERS * sizeof(uint64_t); - if (!infoCacheFile.read((char*)&(modelCacheInfo), charNumber)) { - LOGE("[Compilation] Fail to get the content of info cache file."); - infoCacheFile.close(); - return OH_NN_INVALID_FILE; - } - - // modelCacheInfo.deviceId type is int64_t, - // it is transformed from size_t value, so the transform here will not truncate value. - size_t deviceId = static_cast(modelCacheInfo.deviceId); - if (deviceId != m_deviceId) { - LOGE("[Compilation] The deviceId=%zu in the cache files is different from current deviceId=%zu," - "please change the cache directory or current deviceId.", deviceId, m_deviceId); - infoCacheFile.close(); - return OH_NN_INVALID_PARAMETER; - } - - std::vector modelCheckSum; - modelCheckSum.resize(modelCacheInfo.fileNumber); - modelCacheInfo.modelCheckSum.resize(modelCacheInfo.fileNumber); - if (!infoCacheFile.read((char*)&modelCheckSum[0], modelCacheInfo.fileNumber * sizeof(uint64_t))) { - LOGE("[Compilation] The info cache file has been changed."); - infoCacheFile.close(); - return OH_NN_INVALID_FILE; - } - - for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { - modelCacheInfo.modelCheckSum[i] = static_cast(modelCheckSum[i]); - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::RemoveCacheFiles(uint32_t fileNumber) const -{ - std::string cacheInfoPath = m_cachePath + m_modelName + "cache_info.nncache"; - if (remove(cacheInfoPath.c_str()) == -1) { - LOGE("[Compilation] Fail to remove the file %s, please delete the file manually.", cacheInfoPath.c_str()); - return OH_NN_FAILED; - } - LOGI("[Compilation] Succeed to remove the file cache_info.nncach."); - - for (uint32_t i = 0; i < fileNumber; ++i) { - std::string fileName = m_modelName + std::to_string(i) + ".nncache"; - std::string cacheModelPath = m_cachePath + fileName; - if (access(cacheModelPath.c_str(), 0) != 0) { - LOGW("[Compilation] The file %s does not exist, no need to delete the file.", cacheModelPath.c_str()); - continue; - } - - if (remove(cacheModelPath.c_str()) == -1) { - LOGE("[Compilation] Fail to remove the file %s, please delete the file manually.", cacheModelPath.c_str()); - return OH_NN_FAILED; - } - LOGI("[Compilation] Succeed to remove the file %s", cacheModelPath.c_str()); - } - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::CheckCacheModel(const ModelCacheInfo& modelCacheInfo, - std::vector& modelBuffers) const -{ - for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { - std::string cacheModelPath = m_cachePath + m_modelName + std::to_string(i) + ".nncache"; - if (access(cacheModelPath.c_str(), 0) != 0) { - LOGE("[Compilation] The cache model file %s does not exist.", cacheModelPath.c_str()); - return OH_NN_INVALID_FILE; - } - - Buffer modelBuffer; - OH_NN_ReturnCode ret = ReadCacheModelFile(cacheModelPath, modelBuffer); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Read cache model file failed."); - return ret; - } - - if (GetCrc16(static_cast(modelBuffer.data), - modelBuffer.length) != modelCacheInfo.modelCheckSum[i]) { - LOGE("[Compilation] The cache model file %s has been changed.", cacheModelPath.c_str()); - return OH_NN_INVALID_FILE; - } - - modelBuffers.emplace_back(std::move(modelBuffer)); - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::NormalBuild(std::shared_ptr& preparedModel) -{ - ModelConfig config {m_enableFp16, m_performance, m_priority}; - if ((m_liteGraph == nullptr) && (m_metaGraph == nullptr)) { - LOGE("[Compilation] Both m_liteGraph and m_metaGraph are nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if ((m_liteGraph != nullptr) && (m_metaGraph != nullptr)) { - LOGE("[Compilation] Neither m_liteGraph nor m_metaGraph are nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - OH_NN_ReturnCode ret {OH_NN_FAILED}; - if (m_liteGraph != nullptr) { - ret = m_device->PrepareModel(m_liteGraph, config, preparedModel); - } - if (m_metaGraph != nullptr) { - ret = m_device->PrepareModel(m_metaGraph, m_quantBuffer, config, preparedModel); - } - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Preparing model failed when normally building."); - return ret; - } - - m_executionPlan = CreateSharedPtr(preparedModel, m_device); - if (m_executionPlan == nullptr) { - LOGE("[Compilation] Fail to create ExecutionPlan instance."); - return OH_NN_MEMORY_ERROR; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::GenCacheBuild(std::shared_ptr& preparedModel) -{ - OH_NN_ReturnCode ret = NormalBuild(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Preparing model failed when generating cache."); - return ret; - } - - std::vector modelBuffers; - ret = preparedModel->ExportModelCache(modelBuffers); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Export model cache failed."); - return ret; - } - - ret = GenerateCacheFiles(modelBuffers); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Generate cache files failed."); - return ret; - } - - LOGI("[Compilation] Export model cache successfully."); - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::ReGenCacheBuild(uint32_t fileNumber, std::shared_ptr& preparedModel) -{ - OH_NN_ReturnCode ret = RemoveCacheFiles(fileNumber); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - ret = GenCacheBuild(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Generating cache building failed."); - return ret; - } - - LOGI("[Compilation] Update model cache successfully."); - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::LoadCacheBuild(std::shared_ptr& preparedModel, - const ModelCacheInfo& cacheInfo) -{ - std::vector modelBuffers; - OH_NN_ReturnCode ret = CheckCacheModel(cacheInfo, modelBuffers); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Checking cache model failed."); - size_t modelBuffersSize = modelBuffers.size(); - for (size_t i = 0; i < modelBuffersSize; ++i) { - m_device->ReleaseBuffer(modelBuffers[i].data); - modelBuffers[i].data = nullptr; - modelBuffers[i].length = 0; - } - return ret; - } - - ModelConfig config {m_enableFp16, m_performance, m_priority}; - ret = m_device->PrepareModelFromModelCache(modelBuffers, config, preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Preparing model from cache failed."); - return ret; - } - - LOGI("[Compilation] Load cache successfully."); - - for (auto& modelBuffer : modelBuffers) { - ret = m_device->ReleaseBuffer(modelBuffer.data); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Release cache model buffer failed."); - return ret; - } - } - modelBuffers.clear(); - - m_executionPlan = CreateSharedPtr(preparedModel, m_device); - if (m_executionPlan == nullptr) { - LOGE("Fail to create ExecutionPlan instance."); - return OH_NN_MEMORY_ERROR; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::BuildCacheModel(std::shared_ptr& preparedModel) -{ - OH_NN_ReturnCode ret; - std::string cacheInfoPath = m_cachePath + m_modelName + "cache_info.nncache"; - if (access(cacheInfoPath.c_str(), 0) != 0) { - ret = GenCacheBuild(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("Fail to build in generating cache mode."); - return ret; - } - - m_isBuild = true; - return OH_NN_SUCCESS; - } - - ModelCacheInfo cacheInfo; - ret = CheckCacheInfo(cacheInfo, cacheInfoPath); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - if (m_version > cacheInfo.version) { - ret = ReGenCacheBuild(cacheInfo.fileNumber, preparedModel); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - m_isBuild = true; - return OH_NN_SUCCESS; - } - - if (m_version < cacheInfo.version) { - LOGE("[Compilation] The current version is lower than the cache files, please set a higher version."); - return OH_NN_OPERATION_FORBIDDEN; - } - - ret = LoadCacheBuild(preparedModel, cacheInfo); - if (ret != OH_NN_SUCCESS) { - // recompile the model online and update the cache when failing to build cache model - ret = ReGenCacheBuild(cacheInfo.fileNumber, preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Failed to re-generate and build cache model."); - return ret; - } - } - - m_isBuild = true; - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::InnerBuild() -{ - OH_NN_ReturnCode ret; - std::shared_ptr preparedModel; - - // Prepare from offline model. - bool isOfflineModel {false}; - ret = IsOfflineModel(isOfflineModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Failed when identifying the offline model."); - return ret; - } - - if (isOfflineModel) { - ret = BuildOfflineModel(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Failed to build offline model."); - return ret; - } - - m_isBuild = true; - return OH_NN_SUCCESS; - } - - if (m_cachePath.empty()) { - ret = NormalBuild(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("Fail to normally build."); - return ret; - } - - m_isBuild = true; - return OH_NN_SUCCESS; - } - - ret = BuildCacheModel(preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("Fail to build cache model."); - return ret; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::Build() -{ - NNRT_TRACE_NAME("Compilation"); - if (m_isBuild) { - LOGE("[Compilation] Cannot enable float16 after compilation finish."); - return OH_NN_OPERATION_FORBIDDEN; - } - - if (m_device == nullptr) { - LOGE("The parameter of m_device is nullptr, please call SetDevice function before build model."); - return OH_NN_OPERATION_FORBIDDEN; - } - - OH_NN_ReturnCode ret = InnerBuild(); - if (ret != OH_NN_SUCCESS) { - return ret; - } - - return OH_NN_SUCCESS; -} - -std::shared_ptr Compilation::GetExecutionPlan() const -{ - return m_executionPlan; -} - -std::vector> Compilation::GetInputTensors() const -{ - return m_inputTensors; -} - -std::vector> Compilation::GetOutputTensors() const -{ - return m_outputTensors; -} - -bool Compilation::IsBuild() const -{ - return m_isBuild; -} - -bool Compilation::IsDynamicShape() const -{ - size_t inputTensorsSize = m_inputTensors.size(); - for (size_t i = 0; i < inputTensorsSize; ++i) { - if (m_inputTensors[i]->IsDynamicShape()) { - return true; - } - } - return false; -} - -OH_NN_ReturnCode Compilation::IsOfflineModel(bool& isOfflineModel) const -{ - isOfflineModel = false; // Initialize the returned value - if ((m_liteGraph == nullptr) && (m_metaGraph == nullptr)) { - LOGE("[Compilation] LiteGraph and metaGraph are empty when identifying the offline model."); - return OH_NN_NULL_PTR; - } - - if ((m_liteGraph != nullptr) && (m_metaGraph != nullptr)) { - LOGE("[Compilation] LiteGraph and metaGraph are not empty when identifying the offline model."); - return OH_NN_INVALID_PARAMETER; - } - - if (m_metaGraph != nullptr) { - isOfflineModel = false; - return OH_NN_SUCCESS; - } - - if (m_liteGraph->all_nodes_.size() == 0) { - LOGE("[Compilation] Find empty node in the model."); - return OH_NN_INVALID_PARAMETER; - } - - // If the model consists of more than 1 node, it will not be considered as offline model. - if (m_liteGraph->all_nodes_.size() > 1) { - isOfflineModel = false; - return OH_NN_SUCCESS; - } - - const mindspore::lite::LiteGraph::Node* pNode = m_liteGraph->all_nodes_[0]; - if (pNode == nullptr) { - LOGE("[Compilation] Find invalid node in the model."); - return OH_NN_NULL_PTR; - } - - const mindspore::lite::NodeType& nodeType = mindspore::lite::MindIR_Primitive_GetType(pNode->primitive_); - if (nodeType == mindspore::lite::NodeType::NODE_TYPE_CUSTOM) { - isOfflineModel = true; - } - - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode Compilation::BuildOfflineModel(std::shared_ptr& preparedModel) -{ - ModelConfig config {m_enableFp16, m_performance, m_priority}; - OH_NN_ReturnCode ret = m_device->PrepareOfflineModel(m_liteGraph, config, preparedModel); - if (ret != OH_NN_SUCCESS) { - LOGE("[Compilation] Preparing model failed when building from offline model."); - return ret; - } - - m_executionPlan = CreateSharedPtr(preparedModel, m_device); - if (m_executionPlan == nullptr) { - LOGE("[Compilation] Failed to create ExecutionPlan when building from offline model."); - return OH_NN_MEMORY_ERROR; - } - - return OH_NN_SUCCESS; -} -} // namespace NeuralNetworkRuntime -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 171badc..b9cb69e 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -12,79 +12,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H #define NEURAL_NETWORK_RUNTIME_COMPILATION_H -#include "inner_model.h" -#include "execution_plan.h" +#include +#include +#include +#include -#include "device.h" -#include "cpp_type.h" +#include "compiler.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -struct ModelCacheInfo { - uint64_t fileNumber = 0; - uint64_t version = 0; - uint64_t deviceId = 0; - std::vector modelCheckSum; -}; - -class Compilation { -public: - explicit Compilation(const InnerModel* innerModel); - - OH_NN_ReturnCode SetDevice(size_t deviceId); - OH_NN_ReturnCode SetCacheDir(const std::string& cacheModelPath, uint32_t version); - OH_NN_ReturnCode SetPerformance(OH_NN_PerformanceMode performance); - OH_NN_ReturnCode SetPriority(OH_NN_Priority priority); - OH_NN_ReturnCode SetEnableFp16(bool isFp16); - - OH_NN_ReturnCode Build(); - - bool IsBuild() const; - bool IsDynamicShape() const; - std::vector>GetInputTensors() const; - std::vector>GetOutputTensors() const; - std::shared_ptr GetExecutionPlan() const; - -private: - std::shared_ptr m_liteGraph {nullptr}; - OH_NN_Priority m_priority {OH_NN_PRIORITY_NONE}; - OH_NN_PerformanceMode m_performance {OH_NN_PERFORMANCE_NONE}; - bool m_enableFp16 {false}; - std::shared_ptr m_device {nullptr}; - std::string m_cachePath; - uint32_t m_version {0}; - size_t m_deviceId {0}; - bool m_isBuild {false}; - std::shared_ptr m_executionPlan {nullptr}; - std::vector> m_inputTensors; - std::vector> m_outputTensors; - void* m_metaGraph {nullptr}; - Buffer m_quantBuffer; - std::string m_modelName; - -private: - OH_NN_ReturnCode GenerateCacheFiles(const std::vector& modelBuffer) const; - OH_NN_ReturnCode GenerateCacheModel(size_t cacheNumber, std::unique_ptr& cacheInfo, - std::vector modelBuffer) const; - OH_NN_ReturnCode GenerateCacheInfo(uint32_t cacheSize, std::unique_ptr& cacheInfo) const; - OH_NN_ReturnCode CheckCacheInfo(ModelCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const; - OH_NN_ReturnCode ReadCacheModelFile(const std::string& file, Buffer& modelBuffer) const; - OH_NN_ReturnCode RemoveCacheFiles(uint32_t fileNumber) const; - unsigned short GetCrc16(const unsigned char* buffer, size_t length) const; - OH_NN_ReturnCode CheckCacheModel(const ModelCacheInfo& modelCacheInfo, - std::vector& modelBuffers) const; - OH_NN_ReturnCode NormalBuild(std::shared_ptr& preparedModel); - OH_NN_ReturnCode BuildCacheModel(std::shared_ptr& preparedModel); - OH_NN_ReturnCode GenCacheBuild(std::shared_ptr& preparedModel); - OH_NN_ReturnCode ReGenCacheBuild(uint32_t fileNumber, std::shared_ptr& preparedModel); - OH_NN_ReturnCode LoadCacheBuild(std::shared_ptr& preparedModel, const ModelCacheInfo& cacheInfo); - OH_NN_ReturnCode InnerBuild(); - OH_NN_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fsize) const; - OH_NN_ReturnCode IsOfflineModel(bool& isOfflineModel) const; - OH_NN_ReturnCode BuildOfflineModel(std::shared_ptr& preparedModel); +struct Compilation { + size_t backendID {0}; + void* nnModel {nullptr}; + char* offlineModelPath {nullptr}; + std::pair offlineModelBuffer; + char* cachePath {nullptr}; + uint32_t cacheVersion {0}; + std::pair cacheBuffer; + OH_NN_Priority priority {OH_NN_PRIORITY_NONE}; + OH_NN_PerformanceMode performance {OH_NN_PERFORMANCE_NONE}; + bool enableFp16 {false}; + Compiler* compiler {nullptr}; + std::vector> options; + std::unordered_map> configs; + + ~Compilation() + { + options.clear(); + } }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/device_discover.h b/frameworks/native/compiler.h similarity index 34% rename from frameworks/native/device_discover.h rename to frameworks/native/compiler.h index ae61475..3b98440 100644 --- a/frameworks/native/device_discover.h +++ b/frameworks/native/compiler.h @@ -12,16 +12,41 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef NEURAL_NETWORK_RUNTIME_COMPILER_H +#define NEURAL_NETWORK_RUNTIME_COMPILER_H -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H +#include +#include -#include "device.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" +#include "cpp_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -std::shared_ptr DiscoverHDIDevicesV1_0(std::string& deviceName, std::string& vendorName, std::string& version); -std::shared_ptr DiscoverHDIDevicesV2_0(std::string& deviceName, std::string& vendorName, std::string& version); +class Compiler { +public: + Compiler() = default; + virtual ~Compiler() = default; + + virtual size_t GetBackendID() const = 0; + + virtual OH_NN_ReturnCode SetCacheDir(const std::string& cacheModelPath, uint32_t version) = 0; + virtual OH_NN_ReturnCode SetPerformance(OH_NN_PerformanceMode performance) = 0; + virtual OH_NN_ReturnCode SetPriority(OH_NN_Priority priority) = 0; + virtual OH_NN_ReturnCode SetEnableFp16(bool isFp16) = 0; + + virtual bool IsBuild() const = 0; + virtual OH_NN_ReturnCode Build() = 0; + + virtual OH_NN_ReturnCode SaveToCacheFile() const = 0; + virtual OH_NN_ReturnCode RestoreFromCacheFile() = 0; + virtual OH_NN_ReturnCode SaveToCacheBuffer(const void* buffer, size_t length, size_t* modelSize) const = 0; + virtual OH_NN_ReturnCode RestoreFromCacheBuffer(const void* buffer, size_t length) = 0; + + virtual OH_NN_ReturnCode SetExtensionConfig(const std::unordered_map>& configs) = 0; + virtual OH_NN_ReturnCode SetOptions(const std::vector>& options) = 0; +}; } // namespace NeuralNetworkRuntime } // namespace OHOS -#endif // NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H + +#endif // NEURAL_NETWORK_RUNTIME_COMPILER_H \ No newline at end of file diff --git a/frameworks/native/cpp_type.h b/frameworks/native/cpp_type.h index 2f256cc..96d6594 100644 --- a/frameworks/native/cpp_type.h +++ b/frameworks/native/cpp_type.h @@ -20,7 +20,7 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/device.h b/frameworks/native/device.h index f8f3ecc..274b979 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.h @@ -20,11 +20,12 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "cpp_type.h" -#include "nn_tensor.h" +#include "tensor_desc.h" #include "prepared_model.h" #include "mindir.h" +#include "nn_tensor.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -62,8 +63,12 @@ public: std::shared_ptr& preparedModel) = 0; virtual void* AllocateBuffer(size_t length) = 0; + virtual void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) = 0; virtual void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) = 0; virtual OH_NN_ReturnCode ReleaseBuffer(const void* buffer) = 0; + + virtual OH_NN_ReturnCode AllocateBuffer(size_t length, int& fd) = 0; + virtual OH_NN_ReturnCode ReleaseBuffer(int fd, size_t length) = 0; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/device_manager.cpp b/frameworks/native/device_manager.cpp deleted file mode 100644 index 75ac674..0000000 --- a/frameworks/native/device_manager.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "device_manager.h" -#include "device_discover.h" - -#include "common/log.h" -#include "common/utils.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -const std::vector& DeviceManager::GetAllDeviceId() -{ - m_tmpDeviceIds.clear(); - std::shared_ptr device {nullptr}; - for (auto iter = m_devices.begin(); iter != m_devices.end(); ++iter) { - device = iter->second; - if (!IsValidDevice(device)) { - continue; - } - m_tmpDeviceIds.emplace_back(iter->first); - } - return m_tmpDeviceIds; -} - -std::shared_ptr DeviceManager::GetDevice(size_t deviceId) const -{ - auto iter = m_devices.find(deviceId); - if (iter == m_devices.end()) { - LOGE("DeviceId is not found, deviceId=%zu", deviceId); - return nullptr; - } - - return iter->second; -} - -const std::string& DeviceManager::GetDeviceName(size_t deviceId) -{ - m_tmpDeviceName.clear(); - auto iter = m_devices.find(deviceId); - if (iter == m_devices.end()) { - LOGE("DeviceId is not found, deviceId=%zu", deviceId); - return m_tmpDeviceName; - } - - std::string deviceName; - auto ret = iter->second->GetDeviceName(deviceName); - if (ret != OH_NN_SUCCESS) { - LOGE("Get device name failed."); - return m_tmpDeviceName; - } - - std::string vendorName; - ret = iter->second->GetVendorName(vendorName); - if (ret != OH_NN_SUCCESS) { - LOGE("Get vendor name failed."); - return m_tmpDeviceName; - } - - std::string version; - ret = iter->second->GetVersion(version); - if (ret != OH_NN_SUCCESS) { - LOGE("Get version failed."); - return m_tmpDeviceName; - } - - m_tmpDeviceName = GenUniqueName(deviceName, vendorName, version); - return m_tmpDeviceName; -} - -std::string DeviceManager::GenUniqueName( - const std::string& deviceName, const std::string& vendorName, const std::string& version) const -{ - return deviceName + "_" + vendorName + "_" + version; -} - -OH_NN_ReturnCode DeviceManager::RegisterDevice(std::function()> creator) -{ - auto regDevice = creator(); - if (regDevice == nullptr) { - LOGE("Cannot create device, register device failed."); - return OH_NN_INVALID_PARAMETER; - } - - if (!IsValidDevice(regDevice)) { - LOGE("Device is not avaliable."); - return OH_NN_UNAVALIDABLE_DEVICE; - } - - std::string deviceName; - auto ret = regDevice->GetDeviceName(deviceName); - if (ret != OH_NN_SUCCESS) { - LOGE("Get device name failed."); - return ret; - } - - std::string vendorName; - ret = regDevice->GetVendorName(vendorName); - if (ret != OH_NN_SUCCESS) { - LOGE("Get vendor name failed."); - return ret; - } - - std::string version; - ret = regDevice->GetVersion(version); - if (ret != OH_NN_SUCCESS) { - LOGE("Get version failed."); - return ret; - } - - const std::lock_guard lock(m_mtx); - std::string uniqueName = GenUniqueName(deviceName, vendorName, version); - auto setResult = m_uniqueName.emplace(uniqueName); - if (!setResult.second) { - LOGE("Device already exists, cannot register again. deviceName=%s, vendorName=%s", - deviceName.c_str(), vendorName.c_str()); - return OH_NN_FAILED; - } - - m_devices.emplace(std::hash{}(uniqueName), regDevice); - return OH_NN_SUCCESS; -} - -void DeviceManager::AddDevice(const std::string& deviceName, const std::string& vendorName, - const std::string& version, std::shared_ptr device) -{ - std::string uniqueName = GenUniqueName(deviceName, vendorName, version); - const std::lock_guard lock(m_mtx); - auto setResult = m_uniqueName.emplace(uniqueName); - if (!setResult.second) { - LOGW("Device already exists, cannot register again. deviceName=%s, vendorName=%s", - deviceName.c_str(), vendorName.c_str()); - return; - } - - m_devices.emplace(std::hash{}(uniqueName), device); -} - -void DeviceManager::DiscoverHDIDevices() -{ - std::string deviceName; - std::string vendorName; - std::string version; - std::shared_ptr deviceV1_0 = DiscoverHDIDevicesV1_0(deviceName, vendorName, version); - if (deviceV1_0 != nullptr) { - AddDevice(deviceName, vendorName, version, deviceV1_0); - } - - std::shared_ptr deviceV2_0 = DiscoverHDIDevicesV2_0(deviceName, vendorName, version); - if (deviceV2_0 != nullptr) { - AddDevice(deviceName, vendorName, version, deviceV2_0); - } -} - -bool DeviceManager::IsValidDevice(std::shared_ptr device) const -{ - DeviceStatus status {DeviceStatus::UNKNOWN}; - auto ret = device->GetDeviceStatus(status); - if (ret != OH_NN_SUCCESS || status == DeviceStatus::UNKNOWN || status == DeviceStatus::OFFLINE) { - return false; - } - return true; -} -} // NeuralNetworkRuntime -} // OHOS \ No newline at end of file diff --git a/frameworks/native/device_registrar.cpp b/frameworks/native/device_registrar.cpp deleted file mode 100644 index fa2f6ff..0000000 --- a/frameworks/native/device_registrar.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "device_registrar.h" - -#include "device_manager.h" -#include "common/log.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -DeviceRegistrar::DeviceRegistrar(const CreateDevice creator) -{ - auto& deviceManager = DeviceManager::GetInstance(); - auto ret = deviceManager.RegisterDevice(creator); - if (ret != OH_NN_SUCCESS) { - LOGW("Register device failed. ErrorCode=%d", ret); - } -} -} // NeuralNetworkRuntime -} // OHOS \ No newline at end of file diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 426ba5d..fe84057 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -27,6 +27,521 @@ using namespace OHOS::NeuralNetworkRuntime; #define NNRT_API __attribute__((visibility("default"))) +NNRT_API OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount) +{ + if (allDevicesID == nullptr) { + LOGE("OH_NNDevice_GetAllDevicesID failed, passed nullptr to allDevicesID."); + return OH_NN_INVALID_PARAMETER; + } + + if ((*allDevicesID) != nullptr) { + LOGE("OH_NNDevice_GetAllDevicesID failed, *allDevicesID should be nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (deviceCount == nullptr) { + LOGE("OH_NNDevice_GetAllDevicesID failed, passed nullptr to deviceCount."); + return OH_NN_INVALID_PARAMETER; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + const std::vector& allDevices = backendManager.GetAllBackendsID(); + + if (allDevices.empty()) { + LOGW("OH_NNDevice_GetAllDevicesID got no device."); + *allDevicesID = nullptr; + *deviceCount = 0; + return OH_NN_SUCCESS; + } + + *allDevicesID = allDevices.data(); + // allDevices.size() will not exceed UINT32_MAX, it is safe to cast to uint32_t. + *deviceCount = static_cast(allDevices.size()); + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name) +{ + if (name == nullptr) { + LOGE("OH_NNDevice_GetName failed, passed nullptr to name."); + return OH_NN_INVALID_PARAMETER; + } + + if ((*name) != nullptr) { + LOGE("OH_NNDevice_GetName failed, *name should be nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + const std::string& backendName = backendManager.GetBackendName(deviceID); + if (backendName.empty()) { + LOGE("OH_NNDevice_GetName failed, error happened when getting name of deviceID %{public}zu.", deviceID); + *name = nullptr; + return OH_NN_FAILED; + } + + *name = backendName.data(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType* deviceType) +{ + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("OH_NNDevice_GetType failed, passed invalid deviceID."); + return OH_NN_INVALID_PARAMETER; + } + + if (deviceType == nullptr) { + LOGE("OH_NNDevice_GetType failed, passed nullptr to deviceType."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = backend->GetBackendType(*deviceType); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNDevice_GetType failed, device id: %{public}zu.", deviceID); + return ret; + } + return OH_NN_SUCCESS; +} + +NNRT_API OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) +{ + if (model == nullptr) { + LOGE("OH_NNCompilation_Construct failed, passed nullptr to model."); + return nullptr; + } + + Compilation *compilation = new (std::nothrow) Compilation(); + if (compilation == nullptr) { + LOGE("OH_NNCompilation_Construct failed, please check whether it has enough memory."); + return nullptr; + } + + compilation->nnModel = const_cast(reinterpret_cast(model)); + OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); + + return nnCompilation; +} + +NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *modelPath) +{ + if (modelPath == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelFile failed, passed nullptr to modelPath."); + return nullptr; + } + + Compilation *compilation = new (std::nothrow) Compilation(); + if (compilation == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelFile failed, please check whether it has enough memory."); + return nullptr; + } + + compilation->offlineModelPath = const_cast(modelPath); + OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); + + return nnCompilation; +} + +NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *modelBuffer, size_t modelSize) +{ + if (modelBuffer == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, modelBuffer is nullptr."); + return nullptr; + } + + if (modelSize == static_cast(0)) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, modelSize is 0."); + return nullptr; + } + + Compilation *compilation = new (std::nothrow) Compilation(); + if (compilation == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, please check whether it has enough memory."); + return nullptr; + } + + compilation->offlineModelBuffer.first = const_cast(modelBuffer); + compilation->offlineModelBuffer.second = modelSize; + OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); + + return nnCompilation; +} + +NNRT_API NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructForCache() +{ + Compilation *compilation = new (std::nothrow) Compilation(); + if (compilation == nullptr) { + LOGE("OH_NNCompilation_ConstructForCache failed, please check whether it has enough memory."); + return nullptr; + } + + OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); + return nnCompilation; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t length, + size_t *modelSize) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (buffer == nullptr) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, buffer is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (length == static_cast(0)) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, pass length equals to 0."); + return OH_NN_INVALID_PARAMETER; + } + + if (modelSize == nullptr) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, modelSize is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + if (compilationImpr->compiler == nullptr) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, should call OH_NNCompilation_Build before export cache."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = compilationImpr->compiler->SaveToCacheBuffer(buffer, length, modelSize); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, fail to save cache to buffer."); + } + + return ret; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t modelSize) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (buffer == nullptr) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, buffer is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (modelSize == static_cast(0)) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, modelSize is 0."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->offlineModelBuffer.first = const_cast(buffer); + compilationImpr->offlineModelBuffer.second = modelSize; + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, + const char *configName, + const void *configValue, + const size_t configValueSize) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (configName == nullptr) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, configName is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (configValue == nullptr) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, configValue is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (configValueSize == static_cast(0)) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, configValueSize is 0."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + + std::string configNameStr = configName; + if (configNameStr.empty()) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, configName is empty."); + return OH_NN_INVALID_PARAMETER; + } + + std::vector configValueVec(configValueSize, '0'); + void* configValueAddr = reinterpret_cast(configValueVec.data()); + uint32_t ret = memcpy_s(configValueAddr, configValueVec.size(), configValue, configValueSize); + if (ret != EOK) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, copy config value failed."); + return OH_NN_FAILED; + } + + auto emplaceResult = compilationImpr->configs.emplace(configNameStr, configValueVec); + if (!emplaceResult.second) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, configName %{public}s already exists," + "don't set again.", configName); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_SetDevice failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->backendID = deviceID; + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, + const char *cachePath, + uint32_t version) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_SetCache failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (cachePath == nullptr) { + LOGE("OH_NNCompilation_SetCache failed, cachePath is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->cachePath = const_cast(cachePath); + compilationImpr->cacheVersion = version; + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, + OH_NN_PerformanceMode performanceMode) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_SetPerformanceMode failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->performance = performanceMode; + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_NN_Priority priority) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_SetPriority failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->priority = priority; + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_EnableFloat16 failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + compilationImpr->enableFp16 = enableFloat16; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode CreateCompiler(Compilation* compilation, Compiler** compiler) +{ + if (compilation == nullptr) { + LOGE("CreateCompiler failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (compiler == nullptr) { + LOGE("CreateCompiler failed, compiler is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + BackendManager& manager = BackendManager::GetInstance(); + std::shared_ptr backend = manager.GetBackend(compilation->backendID); + if(backend == nullptr) { + LOGE("CreateCompiler failed, fail to get backend %{public}zu.", compilation->backendID); + return OH_NN_FAILED; + } + + *compiler = backend->CreateCompiler(compilation); + if (*compiler == nullptr) { + LOGE("CreateCompiler failed, fail to create compiler."); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) +{ + if (compilation == nullptr) { + LOGE("SetCompilationOptions failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (compilation->compiler == nullptr) { + LOGE("SetCompilationOptions failed, compiler is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = OH_NN_SUCCESS; + if (compilation->cachePath != nullptr) { + ret = compilation->compiler->SetCacheDir(compilation->cachePath, compilation->cacheVersion); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set cache dir."); + return ret; + } + } + + ret = compilation->compiler->SetEnableFp16(compilation->enableFp16); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set enable fp16."); + return ret; + } + + ret = compilation->compiler->SetPerformance(compilation->performance); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set performance."); + return ret; + } + + ret = compilation->compiler->SetPriority(compilation->priority); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set priority."); + return ret; + } + + ret = compilation->compiler->SetExtensionConfig(compilation->configs); + if ((ret != OH_NN_SUCCESS) && (ret != OH_NN_UNSUPPORTED)) { + LOGE("SetCompilationOptions failed, fail to set extenstion configs."); + return ret; + } + + ret = compilation->compiler->SetOptions(compilation->options); + if ((ret != OH_NN_SUCCESS) && (ret != OH_NN_UNSUPPORTED)) { + LOGE("SetCompilationOptions failed, fail to set extenstion options."); + return ret; + } + + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_Build failed, compilation is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + Compilation* compilationImpr = reinterpret_cast(compilation); + + if (((compilationImpr->nnModel != nullptr) && (compilationImpr->offlineModelPath != nullptr)) || + ((compilationImpr->nnModel != nullptr) && + ((compilationImpr->offlineModelBuffer.first != nullptr) || + (compilationImpr->offlineModelBuffer.second != static_cast(0)))) || + ((compilationImpr->offlineModelPath != nullptr) && + ((compilationImpr->offlineModelBuffer.first != nullptr) || + (compilationImpr->offlineModelBuffer.second != static_cast(0))))) { + LOGE("OH_NNCompilation_Build failed, find multi model to build compilation."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = OH_NN_SUCCESS; + if (compilationImpr->compiler != nullptr) { + LOGE("OH_NNCompilation_Build failed, the compiler in compilation is not nullptr, " + "please input a new compilation."); + return OH_NN_INVALID_PARAMETER; + } + + Compiler* compiler = nullptr; + ret = CreateCompiler(compilationImpr, &compiler); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Build failed, faile to create compiler."); + return ret; + } + compilationImpr->compiler = compiler; + + ret = SetCompilationOptions(compilationImpr); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Build failed, faile to create compiler."); + return ret; + } + + bool isBuild = compilationImpr->compiler->IsBuild(); + if (isBuild) { + LOGE("OH_NNCompilation_Build failed, compilation has been built, don't build again."); + return OH_NN_OPERATION_FORBIDDEN; + } + + ret = compilationImpr->compiler->Build(); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Build failed, faile to build compilation."); + return ret; + } + + return OH_NN_SUCCESS; +} + +NNRT_API void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_Destroy failed, compilation is nullptr."); + return; + } + + if (*compilation == nullptr) { + LOGE("OH_NNCompilation_Destroy failed, compilation is nullptr."); + return; + } + + Compilation* compilationImpr = reinterpret_cast(*compilation); + if (compilationImpr->compiler != nullptr) { + BackendManager& manager = BackendManager::GetInstance(); + std::shared_ptr backend = manager.GetBackend(compilationImpr->backendID); + if(backend == nullptr) { + LOGE("OH_NNCompilation_Destroy failed, fail to get backend %{public}zu.", compilationImpr->backendID); + return; + } + + OH_NN_ReturnCode ret = backend->DestroyCompiler(compilationImpr->compiler); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Destroy failed, fail to destroy compiler."); + return; + } + } + + delete compilationImpr; + *compilation = nullptr; +} + NNRT_API NN_TensorDesc *OH_NNTensorDesc_Create() { TensorDesc *tensorDescImpl = new (std::nothrow) TensorDesc(); diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp new file mode 100644 index 0000000..fde6190 --- /dev/null +++ b/frameworks/native/nnbackend.cpp @@ -0,0 +1,240 @@ +#include "nnbackend.h" + +#include +#include "common/log.h" +#include "common/utils.h" +#include "nncompiler.h" +#include "nnexecutor.h" +#include "nntensor.h" +#include "tensor_desc.h" +#include "device.h" + + +namespace OHOS { +namespace NeuralNetworkRuntime { +NNBackend::NNBackend(const std::shared_ptr& device, size_t backendID) + : m_device(device), + m_backendID(backendID) {} + +NNBackend::~NNBackend() +{ + if (m_device != nullptr) { + m_device = nullptr; + } +} + +size_t NNBackend::GetBackendID() const +{ + return m_backendID; +} + +OH_NN_ReturnCode NNBackend::GetBackendName(std::string& backendName) const +{ + if (m_device == nullptr) { + LOGE("[NNBackend] GetBackendName failed, m_device is nullptr"); + return OH_NN_FAILED; + } + + std::string deviceName; + OH_NN_ReturnCode ret = m_device->GetDeviceName(deviceName); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetBackendName failed, get device name failed."); + return ret; + } + + std::string vendorName; + ret = m_device->GetVendorName(vendorName); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetBackendName failed, get vendor name failed."); + return ret; + } + + std::string version; + ret = m_device->GetVersion(version); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetBackendName failed, get version failed."); + return ret; + } + + backendName = GenUniqueName(deviceName, vendorName, version); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNBackend::GetBackendType(OH_NN_DeviceType& backendType) const +{ + if (m_device == nullptr) { + LOGE("[NNBackend] GetBackendType failed, m_device is nullptr"); + return OH_NN_FAILED; + } + + OH_NN_ReturnCode ret = m_device->GetDeviceType(backendType); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetBackendType failed, fail to get device type"); + return ret; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNBackend::GetBackendStatus(DeviceStatus& status) const +{ + if (m_device == nullptr) { + LOGE("[NNBackend] GetBackendStatus failed, m_device is nullptr"); + return OH_NN_FAILED; + } + + OH_NN_ReturnCode ret = m_device->GetDeviceStatus(status); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetBackendStatus failed, fail to get device status"); + return ret; + } + return OH_NN_SUCCESS; +} + +Compiler* NNBackend::CreateCompiler(Compilation* compilation) +{ + if (compilation == nullptr) { + LOGE("[NNBackend] CreateCompiler failed, compilation is nullptr"); + return nullptr; + } + + // 仅支持从nnmodel 和 nnmodel-cache构建编译器 + if ((compilation->offlineModelPath != nullptr) || + ((compilation->offlineModelBuffer.first != nullptr) || + (compilation->offlineModelBuffer.second != static_cast(0)))) { + LOGE("[NNBackend] CreateCompiler failed, only support build NN model and NN model cache."); + return nullptr; + } + + // 如果nnmodel是空值,构建空的编译器,后续从cache编译模型, + // 如果nnmodel不为空,则从对应模型构建编译器 + NNCompiler* nnCompiler = nullptr; + if (compilation->nnModel == nullptr) { + nnCompiler = new (std::nothrow) NNCompiler(m_device, m_backendID); + } else { + nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); + } + + if (nnCompiler == nullptr) { + LOGE("[NNBackend] CreateCompiler failed, error happend when allocating NN Compiler."); + return nullptr; + } + + return reinterpret_cast(nnCompiler); +} + +OH_NN_ReturnCode NNBackend::DestroyCompiler(Compiler* compiler) +{ + if (compiler == nullptr) { + LOGE("[NNBackend] DestroyCompiler failed, compiler is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + delete compiler; + compiler = nullptr; + + return OH_NN_SUCCESS; +} + +Executor* NNBackend::CreateExecutor(Compilation* compilation) +{ + if (compilation == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, compilation is nullptr."); + return nullptr; + } + + if (compilation->compiler == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, the compiler in compilation is nullptr, create complier first."); + return nullptr; + } + + NNCompiler* nnCompiler = reinterpret_cast(compilation->compiler); + NNExecutor* nnExecutor = nnCompiler->CreateExecutor(); + if (nnExecutor == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, fail to create NN Executor."); + return nullptr; + } + + return reinterpret_cast(nnExecutor); +} + +OH_NN_ReturnCode NNBackend::DestroyExecutor(Executor* executor) +{ + if (executor == nullptr) { + LOGE("[NNBackend] DestroyExecutor failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + delete executor; + executor = nullptr; + + return OH_NN_SUCCESS; +} + +Tensor* NNBackend::CreateTensor(TensorDesc* desc) +{ + if (desc == nullptr) { + LOGE("[NNBackend] CreateTensor failed, tensor desc is nullptr."); + return nullptr; + } + + NNTensor2_0* tensorImpl = new (std::nothrow) NNTensor2_0(m_backendID); + if (tensorImpl == nullptr) { + LOGE("[NNBackend] CreateTensor failed, error happend when allocating NN Tensor."); + return nullptr; + } + + auto ret = tensorImpl->SetTensorDesc(desc); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] CreateTensor failed, error happend when setting tensor desc."); + delete tensorImpl; + return nullptr; + } + + return reinterpret_cast(tensorImpl); +} + +OH_NN_ReturnCode NNBackend::DestroyTensor(Tensor* tensor) +{ + if (tensor == nullptr) { + LOGE("[NNBackend] DestroyTensor failed, tensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + delete tensor; + tensor = nullptr; + + return OH_NN_SUCCESS; +} + +std::shared_ptr NNBackend::GetDevice() const +{ + if (m_device == nullptr) { + LOGE("[NNBackend] GetDevice failed, m_device is nullptr."); + } + return m_device; +} + +OH_NN_ReturnCode NNBackend::GetSupportedOperation(std::shared_ptr model, + std::vector& ops) +{ + if (model == nullptr) { + LOGE("[NNBackend] GetSupportedOperation failed, model is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_device == nullptr) { + LOGE("[NNBackend] GetSupportedOperation failed, device is nullptr, some error happend."); + return OH_NN_FAILED; + } + + OH_NN_ReturnCode ret = m_device->GetSupportedOperation(model, ops); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] GetSupportedOperation failed, fail to get supportted ops from device."); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} +} // NeuralNetworkRuntime +} // OHOS \ No newline at end of file diff --git a/frameworks/native/nnbackend.h b/frameworks/native/nnbackend.h new file mode 100644 index 0000000..5359773 --- /dev/null +++ b/frameworks/native/nnbackend.h @@ -0,0 +1,48 @@ +#include "backend.h" +#include "executor.h" +#include "tensor.h" +#include "tensor_desc.h" +#include "device.h" +#include "nncompiler.h" + +#ifndef NEURAL_NETWORK_RUNTIME_NNBACKEND_H +#define NEURAL_NETWORK_RUNTIME_NNBACKEND_H + +namespace OHOS { +namespace NeuralNetworkRuntime { +class NNBackend : public Backend { +public: + explicit NNBackend(const std::shared_ptr& device, size_t backendID); + ~NNBackend(); + + // Backend Info + size_t GetBackendID() const override; + OH_NN_ReturnCode GetBackendName(std::string& backendName) const override; + OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const override; + OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const override; + + // Create & Destory compiler + Compiler* CreateCompiler(Compilation* compilation) override; + OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) override; + + // Create & Destory Executor + Executor* CreateExecutor(Compilation* compilation) override; + OH_NN_ReturnCode DestroyExecutor(Executor* executor) override; + + // Create & Destory Tensor + Tensor* CreateTensor(TensorDesc* desc) override; + OH_NN_ReturnCode DestroyTensor(Tensor* tensor) override; + + // external methods + std::shared_ptr GetDevice() const; + OH_NN_ReturnCode GetSupportedOperation(std::shared_ptr model, + std::vector& ops); + +private: + std::shared_ptr m_device; + size_t m_backendID; +}; +} // NeuralNetworkRuntime +} // OHOS + +#endif // NEURAL_NETWORK_RUNTIME_NNBACKEND_H \ No newline at end of file diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp new file mode 100644 index 0000000..75c2ce6 --- /dev/null +++ b/frameworks/native/nncompiled_cache.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nncompiled_cache.h" + +#include +#include +#include + +#include "common/log.h" +#include "backend_manager.h" +#include "nnbackend.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +constexpr int MAX_MODEL_SIZE = 200 * 1024 * 1024; // 200MB +constexpr int OCT_UNIT = 8; +constexpr int NULL_PTR_LENGTH = 0; +constexpr int NUMBER_CACHE_INFO_MEMBERS = 3; + +// CRC16 Table is created based on the Polynomial of G(x) = x^16 + x^12 + x^15 + 1 and +// CRC register initialization value of "0" (0x0000) +static const unsigned short CRC16_TAB[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, + 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, + 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, + 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, + 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, + 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, + 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, + 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, + 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, + 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, + 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, + 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, + 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, + 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + +OH_NN_ReturnCode NNCompiledCache::Save(const std::vector& caches, + const std::string& cacheDir, + uint32_t version) +{ + if (caches.empty()) { + LOGE("[NNCompiledCache] Save failed, caches is empty."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_device == nullptr) { + LOGE("[NNCompiledCache] Save failed, m_device is empty."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = GenerateCacheFiles(caches, cacheDir, version); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiledCache] Save failed, error happened when calling GenerateCacheFiles."); + return ret; + } + + LOGI("[NNCompiledCache] Save success. %zu caches are saved.", caches.size()); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, + uint32_t version, + std::vector& caches) +{ + if (cacheDir.empty()) { + LOGE("[NNCompiledCache] Restore failed, cacheDir is empty."); + return OH_NN_INVALID_PARAMETER; + } + + if (!caches.empty()) { + LOGE("[NNCompiledCache] Restore failed, caches is not empty."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_device == nullptr) { + LOGE("[NNCompiledCache] Restore failed, m_device is empty."); + return OH_NN_INVALID_PARAMETER; + } + + std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; + if (access(cacheInfoPath.c_str(), 0) != 0) { + LOGE("[NNCompiledCache] Restore failed, cacheInfoPath is not exist."); + return OH_NN_INVALID_PARAMETER; + } + + NNCompiledCacheInfo cacheInfo; + OH_NN_ReturnCode ret = CheckCacheInfo(cacheInfo, cacheInfoPath); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiledCache] Restore failed, error happened when calling CheckCacheInfo."); + return ret; + } + + if ((uint64_t)version > cacheInfo.version) { + LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %{public}u, but the cache files " + "version is %{public}zu.", + version, + (size_t)cacheInfo.version); + return OH_NN_INVALID_PARAMETER; + } + + if ((uint64_t)version < cacheInfo.version) { + LOGE("[NNCompiledCache] Restore failed, the current version is lower than the cache files, " + "please set a higher version."); + return OH_NN_OPERATION_FORBIDDEN; + } + + for (uint32_t i = 0; i < cacheInfo.fileNumber; ++i) { + std::string cacheModelPath = cacheDir + "/" + m_modelName + std::to_string(i) + ".nncache"; + if (access(cacheModelPath.c_str(), 0) != 0) { + LOGE("[NNCompiledCache] Restore failed, %s is not exist.", cacheModelPath.c_str()); + return OH_NN_INVALID_PARAMETER; + } + + OHOS::NeuralNetworkRuntime::Buffer modelBuffer; + ret = ReadCacheModelFile(cacheModelPath, modelBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiledCache] Restore failed, error happened when calling ReadCacheModelFile."); + return ret; + } + + if (GetCrc16(static_cast(modelBuffer.data), modelBuffer.length) != + cacheInfo.modelCheckSum[i]) { + LOGE("[NNCompiledCache] Restore failed, the cache model file %s has been changed.", + cacheModelPath.c_str()); + return OH_NN_INVALID_FILE; + } + + caches.emplace_back(std::move(modelBuffer)); + } + + return ret; +} + +OH_NN_ReturnCode NNCompiledCache::SetBackend(size_t backendID) +{ + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendID); + if (backend == nullptr) { + LOGE("[NNCompiledCache] SetBackend failed, backend with backendID %{public}zu is not exist.", backendID); + return OH_NN_INVALID_PARAMETER; + } + + std::shared_ptr nnBackend = std::reinterpret_pointer_cast(backend); + m_device = nnBackend->GetDevice(); + if (m_device == nullptr) { + LOGE("[NNCompiledCache] SetBackend failed, device with backendID %{public}zu is not exist.", backendID); + return OH_NN_FAILED; + } + + m_backendID = backendID; + return OH_NN_SUCCESS; +} + +void NNCompiledCache::SetModelName(const std::string& modelName) +{ + m_modelName = modelName; +} + +OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, + const std::string& cacheDir, + uint32_t version) const +{ + const size_t cacheNumber = caches.size(); + uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber; + std::unique_ptr cacheInfo = std::make_unique(cacheSize); + if (cacheInfo == nullptr) { + LOGE("[NNCompiledCache] GenerateCacheFiles failed, fail to create cacheInfo instance."); + return OH_NN_MEMORY_ERROR; + } + + OH_NN_ReturnCode ret = GenerateCacheModel(caches, cacheInfo, cacheDir, version); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling GenerateCacheModel."); + return ret; + } + + uint32_t infoCharNumber = cacheSize * sizeof(uint64_t); + ret = WriteCacheInfo(infoCharNumber, cacheInfo, cacheDir); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling WriteCacheInfo."); + return ret; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector& caches, + std::unique_ptr& cacheInfo, + const std::string& cacheDir, + uint32_t version) const +{ + size_t cacheNumber = caches.size(); + + auto cacheInfoPtr = cacheInfo.get(); + *cacheInfoPtr++ = static_cast(cacheNumber); + *cacheInfoPtr++ = static_cast(version); + *cacheInfoPtr++ = static_cast(m_backendID); // Should call SetBackend first. + + for (size_t i = 0; i < cacheNumber; ++i) { + std::string cacheModelFile = cacheDir + "/" + m_modelName + std::to_string(i) + ".nncache"; + std::ofstream cacheModelStream(cacheModelFile, std::ios::binary | std::ios::out | std::ios::trunc); + if (cacheModelStream.fail()) { + LOGE("[NNCompiledCache] GenerateCacheModel failed, model cache file is invalid."); + return OH_NN_INVALID_PARAMETER; + } + + uint64_t checkSum = + static_cast(GetCrc16(static_cast(caches[i].data), caches[i].length)); + *cacheInfoPtr++ = checkSum; + if (!cacheModelStream.write(static_cast(caches[i].data), caches[i].length)) { + LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to write cache model."); + cacheModelStream.close(); + return OH_NN_SAVE_CACHE_EXCEPTION; + }; + + cacheModelStream.close(); + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, + std::unique_ptr& cacheInfo, + const std::string& cacheDir) const +{ + std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; + std::ofstream cacheInfoStream(cacheInfoPath, std::ios::binary | std::ios::out | std::ios::trunc); + if (cacheInfoStream.fail()) { + LOGE("[NNCompiledCache] WriteCacheInfo failed, model cache info file is invalid."); + return OH_NN_INVALID_FILE; + } + + if (!cacheInfoStream.write(reinterpret_cast(cacheInfo.get()), cacheSize)) { + LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to write cache info."); + cacheInfoStream.close(); + return OH_NN_SAVE_CACHE_EXCEPTION; + } + + cacheInfoStream.close(); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, + const std::string& cacheInfoPath) const +{ + // cacheInfoPath is validated outside. + std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary); + if (!infoCacheFile) { + LOGE("[NNCompiledCache] CheckCacheInfo failed, error happened when opening cache info file."); + return OH_NN_INVALID_FILE; + } + + int charNumber = NUMBER_CACHE_INFO_MEMBERS * sizeof(uint64_t); + if (!infoCacheFile.read((char*)&(modelCacheInfo), charNumber)) { + LOGE("[NNCompiledCache] CheckCacheInfo failed, error happened when reading cache info file."); + infoCacheFile.close(); + return OH_NN_INVALID_FILE; + } + + // modelCacheInfo.deviceId type is int64_t, + // it is transformed from size_t value, so the transform here will not truncate value. + size_t deviceId = static_cast(modelCacheInfo.deviceId); + if (deviceId != m_backendID) { + LOGE("[NNCompiledCache] CheckCacheInfo failed. The deviceId=%{public}zu in the cache files " + "is different from current deviceId=%{public}zu," + "please change the cache directory or current deviceId.", + deviceId, + m_backendID); + infoCacheFile.close(); + return OH_NN_INVALID_PARAMETER; + } + + std::vector modelCheckSum; + modelCheckSum.resize(modelCacheInfo.fileNumber); + modelCacheInfo.modelCheckSum.resize(modelCacheInfo.fileNumber); + if (!infoCacheFile.read((char*)&modelCheckSum[0], modelCacheInfo.fileNumber * sizeof(uint64_t))) { + LOGE("[NNCompiledCache] CheckCacheInfo failed. The info cache file has been changed."); + infoCacheFile.close(); + return OH_NN_INVALID_FILE; + } + + for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { + modelCacheInfo.modelCheckSum[i] = static_cast(modelCheckSum[i]); + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, + OHOS::NeuralNetworkRuntime::Buffer& cache) const +{ + // filePath is validate in NNCompiledCache::Restore, no need to check again. + std::ifstream ifs(filePath.c_str(), std::ios::in | std::ios::binary); + if (!ifs) { + LOGE("[NNCompiledCache] ReadCacheModelFile failed, file is invalid."); + return OH_NN_INVALID_FILE; + } + + int fsize{-1}; + OH_NN_ReturnCode ret = GetCacheFileLength(ifs, fsize); + if (ret != OH_NN_SUCCESS) { + ifs.close(); + LOGE("[NNCompiledCache] ReadCacheModelFile failed, get file %{public}s length fialed.", filePath.c_str()); + return ret; + } + + ifs.seekg(0, std::ios::beg); + if (!ifs.good()) { + LOGE("[NNCompiledCache] ReadCacheModelFile failed, file is invalid."); + ifs.close(); + return OH_NN_INVALID_FILE; + } + + char* ptr = static_cast(m_device->AllocateBuffer(fsize)); + if (ptr == nullptr) { + LOGE("[NNCompiledCache] ReadCacheModelFile failed, failed to allocate memory."); + ifs.close(); + return OH_NN_MEMORY_ERROR; + } + + ifs.read(ptr, fsize); + if (!ifs.good()) { + LOGE("[NNCompiledCache] ReadCacheModelFile failed, failed to read file."); + ifs.close(); + m_device->ReleaseBuffer(ptr); + ptr = nullptr; + return OH_NN_INVALID_FILE; + } + + ifs.close(); + cache.data = ptr; + cache.length = static_cast(fsize); // fsize should be non-negative, safe to cast. + return OH_NN_SUCCESS; +} + +unsigned short NNCompiledCache::GetCrc16(const unsigned char* buffer, size_t length) const +{ + unsigned short crc16 = 0; + for (size_t i = 0; i < length; ++i) { + uint8_t tableIndex = ((crc16 >> OCT_UNIT) ^ *buffer++) & 0x00ff; + crc16 = (crc16 << OCT_UNIT) ^ CRC16_TAB[tableIndex]; + } + return crc16; +} + +OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fileSize) const +{ + ifs.seekg(0, std::ios::end); + if (!ifs.good()) { + LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to set the position of the next character " + "to be extracted from the input stream."); + return OH_NN_FAILED; + } + + int handleValue = ifs.tellg(); + if (handleValue == -1) { + LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to get position of the input stream."); + return OH_NN_INVALID_FILE; + } + + if ((handleValue > MAX_MODEL_SIZE) || (handleValue == NULL_PTR_LENGTH)) { + LOGE("[NNCompiledCache] GetCacheFileLength failed, unable to read huge or empty input stream, " + "get cache file size=%{public}d", + handleValue); + return OH_NN_INVALID_FILE; + } + + fileSize = handleValue; + return OH_NN_SUCCESS; +} +} // namespace NeuralNetworkRuntime +} // namespace OHOS diff --git a/frameworks/native/nncompiled_cache.h b/frameworks/native/nncompiled_cache.h new file mode 100644 index 0000000..2664cac --- /dev/null +++ b/frameworks/native/nncompiled_cache.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_BACKEND_NNCOMPILED_CACHE_H +#define NEURAL_NETWORK_BACKEND_NNCOMPILED_CACHE_H + +#include +#include +#include + +#include "device.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" +#include "tensor_desc.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +const uint32_t INVALID_CAHCE_VERSION = UINT32_MAX; // UINT32_MAX is reserved for invalid cache version. + +struct NNCompiledCacheInfo { + uint64_t fileNumber{0}; + uint64_t version{0}; + uint64_t deviceId{0}; + std::vector modelCheckSum; +}; + +class NNCompiledCache { +public: + NNCompiledCache() = default; + ~NNCompiledCache() = default; + + OH_NN_ReturnCode Save(const std::vector& caches, + const std::string& cacheDir, + uint32_t version); + OH_NN_ReturnCode Restore(const std::string& cacheDir, + uint32_t version, + std::vector& caches); + + OH_NN_ReturnCode SetBackend(size_t backendID); + void SetModelName(const std::string& modelName); + +private: + OH_NN_ReturnCode GenerateCacheFiles(const std::vector& caches, + const std::string& cacheDir, + uint32_t version) const; + OH_NN_ReturnCode GenerateCacheModel(const std::vector& caches, + std::unique_ptr& cacheInfo, + const std::string& cacheDir, + uint32_t version) const; + OH_NN_ReturnCode WriteCacheInfo(uint32_t cacheSize, + std::unique_ptr& cacheInfo, + const std::string& cacheDir) const; + OH_NN_ReturnCode CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const; + OH_NN_ReturnCode ReadCacheModelFile(const std::string& file, Buffer& cache) const; + unsigned short GetCrc16(const unsigned char* buffer, size_t length) const; + OH_NN_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fileSize) const; + +private: + size_t m_backendID {0}; + std::string m_modelName; + std::shared_ptr m_device {nullptr}; +}; + +} // namespace NeuralNetworkRuntime +} // namespace OHOS + +#endif // NEURAL_NETWORK_BACKEND_NNCOMPILED_CACHE_H diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp new file mode 100644 index 0000000..275843d --- /dev/null +++ b/frameworks/native/nncompiler.cpp @@ -0,0 +1,723 @@ +#include "nncompiler.h" + +#include +#include +#include +#include + +#include "inner_model.h" +#include "validation.h" +#include "nncompiled_cache.h" +#include "common/utils.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +namespace { +struct SerializedTensorDesc { +public: + SerializedTensorDesc() = default; + ~SerializedTensorDesc() = default; + + OH_NN_ReturnCode CopyFromTensorDesc(const std::pair, OH_NN_TensorType>& tensorDesc) + { + if (tensorDesc.first == nullptr) { + LOGE("CopyFromTensorDesc failed, tensor desc is nullptr."); + return OH_NN_NULL_PTR; + } + OH_NN_ReturnCode ret = tensorDesc.first->GetDataType(&m_dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting data type from tensor desc."); + return ret; + } + + ret = tensorDesc.first->GetFormat(&m_format); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting format from tensor desc."); + return ret; + } + + ret = tensorDesc.first->GetShape(&m_shape, &m_shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting shape from tensor desc."); + return ret; + } + + ret = tensorDesc.first->GetName(&m_name); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting name from tensor desc."); + return ret; + } + + m_tensorType = tensorDesc.second; + + return ret; + } + + OH_NN_ReturnCode CopyToTensorDesc(TensorDesc& tensorDesc) const + { + OH_NN_ReturnCode ret = tensorDesc.SetDataType(m_dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyToTensorDesc failed, error happened when setting data type to tensor desc."); + return ret; + } + + ret = tensorDesc.SetFormat(m_format); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyToTensorDesc failed, error happened when setting format to tensor desc."); + return ret; + } + + ret = tensorDesc.SetShape(m_shape, m_shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyToTensorDesc failed, error happened when setting shape to tensor desc."); + return ret; + } + + ret = tensorDesc.SetName(m_name); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyToTensorDesc failed, error happened when setting name to tensor desc."); + } + + return ret; + } + +public: + OH_NN_DataType m_dataType{OH_NN_UNKNOWN}; + OH_NN_Format m_format{OH_NN_FORMAT_NONE}; + OH_NN_TensorType m_tensorType{OH_NN_TENSOR}; + size_t m_shapeNum{0}; + int32_t* m_shape{nullptr}; + const char* m_name{nullptr}; // null-terminated +}; + +const size_t SIZE_OF_DATATYPE = sizeof(SerializedTensorDesc::m_dataType); +const size_t SIZE_OF_FORMAT = sizeof(SerializedTensorDesc::m_format); +const size_t SIZE_OF_TENSOR_TYPE = sizeof(SerializedTensorDesc::m_tensorType); +const size_t SIZE_OF_SHAPE_NUM = sizeof(SerializedTensorDesc::m_shapeNum); +} // namespace + +NNCompiler::NNCompiler(std::shared_ptr device, size_t backendID) + : m_device(device), + m_backendID(backendID) {} + +NNCompiler::NNCompiler(const void* model, std::shared_ptr device, size_t backendID) + : m_model(const_cast(model)), + m_device(device), + m_backendID(backendID) {} + +NNCompiler::~NNCompiler() +{ + if (m_preparedModel != nullptr) { + m_preparedModel.reset(); + } + m_inputTensorDescs.clear(); + m_outputTensorDescs.clear(); + m_model = nullptr; +} + +size_t NNCompiler::GetBackendID() const +{ + return m_backendID; +} + +OH_NN_ReturnCode NNCompiler::SetCacheDir(const std::string& cacheModelPath, uint32_t version) +{ + if (m_device == nullptr) { + LOGE("[NNCompiler] SetCacheDir failed, m_device is nullptr"); + return OH_NN_OPERATION_FORBIDDEN; + } + + bool isSupportedCache {false}; + OH_NN_ReturnCode ret = m_device->IsModelCacheSupported(isSupportedCache); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SetCacheDir failed, fail to call device."); + return ret; + } + + if (!isSupportedCache && !cacheModelPath.empty()) { + LOGE("[NNCompiler] SetCacheDir failed, this device is not support cache setting."); + return OH_NN_OPERATION_FORBIDDEN; + } + + m_cachePath = cacheModelPath; + m_cacheVersion = version; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) +{ + if (m_device == nullptr) { + LOGE("[NNCompiler] SetPerformance failed, m_device is nullptr"); + return OH_NN_OPERATION_FORBIDDEN; + } + + bool isSupportedPerformance {false}; + OH_NN_ReturnCode ret = m_device->IsPerformanceModeSupported(isSupportedPerformance); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SetPerformance failed, fail to call device."); + return OH_NN_FAILED; + } + + if (!isSupportedPerformance && (performance != OH_NN_PERFORMANCE_NONE)) { + LOGE("[NNCompiler] SetPerformance failed, this device is not support performance setting."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (!Validation::ValidatePerformanceMode(performance)) { + LOGE("[NNCompiler] SetPerformance failed, performance=%{public}d is invalid", performance); + return OH_NN_INVALID_PARAMETER; + } + + m_performance = performance; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) +{ + if (m_device == nullptr) { + LOGE("[NNCompiler] SetPriority failed, m_device is nullptr"); + return OH_NN_OPERATION_FORBIDDEN; + } + + bool isSupportedPriority {false}; + OH_NN_ReturnCode ret = m_device->IsPrioritySupported(isSupportedPriority); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SetPriority failed, fail to call device."); + return ret; + } + + if (!isSupportedPriority && (priority != OH_NN_PRIORITY_NONE)) { + LOGE("[NNCompiler] SetPriority failed, this device is not support priority setting."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (!Validation::ValidatePriority(priority)) { + LOGE("[NNCompiler] SetPriority failed, priority=%{public}d is invalid.", priority); + return OH_NN_INVALID_PARAMETER; + } + + m_priority = priority; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) +{ + if (m_device == nullptr) { + LOGE("[NNCompiler] SetEnableFp16 failed, m_device is nullptr"); + return OH_NN_OPERATION_FORBIDDEN; + } + + bool isSupportedFp16 {false}; + OH_NN_ReturnCode ret = m_device->IsFloat16PrecisionSupported(isSupportedFp16); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SetEnableFp16 failed, fail to call device."); + return ret; + } + + if (!isSupportedFp16 && isFp16) { + LOGE("[NNCompiler] SetEnableFp16 failed, this device is not support float16 precision setting."); + return OH_NN_OPERATION_FORBIDDEN; + } + + m_enableFp16 = isFp16; + return OH_NN_SUCCESS; +} + +bool NNCompiler::IsBuild() const +{ + return m_isBuild; +} + +OH_NN_ReturnCode NNCompiler::IsSupporttedModel(const std::shared_ptr& liteGraph, + bool& isSupporttedModel) const +{ + std::vector supportedList; + OH_NN_ReturnCode ret = m_device->GetSupportedOperation(liteGraph, supportedList); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build failed, error happened when getting supported operation."); + return ret; + } + + for (bool isSupport : supportedList) { + if (!isSupport) { + LOGE("[NNCompiler] Build failed, current device not support the model, device id: %{public}zu.", + m_backendID); + isSupporttedModel = false; + return OH_NN_FAILED; + } + } + + isSupporttedModel = true; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::Build() +{ + if (m_isBuild) { + LOGE("[NNCompiler] Build failed, cannot build again."); + return OH_NN_OPERATION_FORBIDDEN; + } + + // cache存在,从cache直接复原prepareModel、input/output TensorDesc + OH_NN_ReturnCode ret = RestoreFromCacheFile(); + if (ret == OH_NN_OPERATION_FORBIDDEN) { + LOGE("[NNCompiler] Build failed, operation is forbidden."); + return ret; + } + if (ret == OH_NN_SUCCESS) { + LOGI("[NNCompiler] Build success, restore from cache file."); + m_isBuild = true; + return OH_NN_SUCCESS; + } else if (m_model == nullptr) { + LOGI("[NNCompiler] Build failed, fail to restore from cache file."); + return ret; + } + + // cache不存在,正常在线构图 + const InnerModel* innerModel = reinterpret_cast(m_model); + std::shared_ptr liteGraph = innerModel->GetLiteGraphs(); + m_inputTensorDescs = innerModel->GetInputTensorDescs(); + m_outputTensorDescs = innerModel->GetOutputTensorDescs(); + void* metaGraph = innerModel->GetMetaGraph(); + Buffer quantBuffer = innerModel->GetQuantBuffer(); + + if ((liteGraph == nullptr) && (metaGraph == nullptr)) { + LOGE("[NNCompiler] Build failed, both liteGraph and metaGraph are nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if ((liteGraph != nullptr) && (metaGraph != nullptr)) { + LOGE("[NNCompiler] Build failed, neither liteGraph nor metaGraph are nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + // 判断是否支持模型 + bool isSupporttedModel = true; + ret = IsSupporttedModel(liteGraph, isSupporttedModel); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build failed, error happend when judge if support the model."); + return ret; + } else if (!isSupporttedModel) { + LOGE("[NNCompiler] Build failed, current device not support the model."); + return OH_NN_FAILED; + } + + ModelConfig config {m_enableFp16, static_cast(m_performance), + static_cast(m_priority)}; + if (liteGraph != nullptr) { + ret = m_device->PrepareModel(liteGraph, config, m_preparedModel); + } + if (metaGraph != nullptr) { + ret = m_device->PrepareModel(metaGraph, quantBuffer, config, m_preparedModel); + } + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build failed, fail to prepare model when normally building."); + return ret; + } + m_isBuild = true; + + // 保存cache + if (!m_cachePath.empty()) { + ret = SaveToCacheFile(); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build success, but fail to save cache to file."); + return ret; + } + } + + return OH_NN_SUCCESS; +} + +void NNCompiler::ReleaseBuffer(std::vector& buffers) const +{ + for (size_t i = 0; i < buffers.size(); ++i) { + // release tensor buffer which is allocated by new method. + delete[] (char*)buffers[i].data; + } + buffers.clear(); +} + +void NNCompiler::ReleaseBufferByDevice(std::vector& buffers) const +{ + for (size_t i = 0; i < buffers.size(); ++i) { + // release cache buffer which is allocated by idevice. + m_device->ReleaseBuffer(buffers[i].data); + } + buffers.clear(); +} + +OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const +{ + if (m_cachePath.empty()) { + LOGE("[NNCompiler] SaveToCacheFile failed, m_cachePath is empty."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_cacheVersion == INVALID_CAHCE_VERSION) { + LOGE("[NNCompiler] SaveToCacheFile failed, cache version is invalid. Please set a valid cache version."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_preparedModel == nullptr) { + LOGE("[NNCompiler] SaveToCacheFile failed, m_preparedModel is nullptr. Please construct prepareModel first."); + return OH_NN_FAILED; + } + + std::vector caches; + std::vector tensorBuffers; + OH_NN_ReturnCode ret = m_preparedModel->ExportModelCache(caches); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, error happened when exporting model cache."); + return ret; + } + + NNCompiledCache compiledCache; + ret = compiledCache.SetBackend(m_backendID); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, fail to set backend."); + return ret; + } + + Buffer inputTensorDescBuffer; + ret = SerializeTensorsToBuffer(m_inputTensorDescs, inputTensorDescBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing input tensor desc."); + return ret; + } + caches.emplace_back(inputTensorDescBuffer); + tensorBuffers.emplace_back(inputTensorDescBuffer); + + Buffer outputTensorDescBuffer; + ret = SerializeTensorsToBuffer(m_outputTensorDescs, outputTensorDescBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing output tensor desc."); + ReleaseBuffer(tensorBuffers); + return ret; + } + caches.emplace_back(outputTensorDescBuffer); + tensorBuffers.emplace_back(outputTensorDescBuffer); + + ret = compiledCache.Save(caches, m_cachePath, m_cacheVersion); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, error happened when saving model cache."); + ReleaseBuffer(tensorBuffers); + return ret; + } + + ReleaseBuffer(tensorBuffers); + LOGI("[NNCompiler] Export model cache successfully."); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() +{ + if (m_cachePath.empty()) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, path is empty."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_cacheVersion == INVALID_CAHCE_VERSION) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, cache version is invalid. Please set a valid cache version."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_preparedModel != nullptr) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, m_preparedModel is not nullptr."); + return OH_NN_FAILED; + } + + NNCompiledCache compiledCache; + OH_NN_ReturnCode ret = compiledCache.SetBackend(m_backendID); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, fail to set backend."); + return ret; + } + + std::vector caches; + ret = compiledCache.Restore(m_cachePath, m_cacheVersion, caches); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when restoring model cache."); + ReleaseBufferByDevice(caches); + return ret; + } + + size_t cacheNum = caches.size(); + ret = DeserializedTensorsFromBuffer(caches[cacheNum-2], m_inputTensorDescs); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing input tensor desc."); + ReleaseBufferByDevice(caches); + return ret; + } + + ret = DeserializedTensorsFromBuffer(caches[cacheNum-1], m_outputTensorDescs); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing output tensor desc."); + ReleaseBufferByDevice(caches); + return ret; + } + + ModelConfig config; + config.enableFloat16 = m_enableFp16; + config.mode = m_performance; + config.priority = m_priority; + std::vector modelOnlyCaches(caches.begin(), caches.end()-2); + ret = m_device->PrepareModelFromModelCache(modelOnlyCaches, config, m_preparedModel); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when preparing model from cache."); + ReleaseBufferByDevice(caches); + return ret; + } + ReleaseBufferByDevice(caches); + + LOGI("[NNCompiler] Restore model cache successfully."); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SaveToCacheBuffer(const void* buffer, size_t length, size_t* modelSize) const +{ + LOGE("[NNCompiler] SaveToCacheBuffer is not supported currently."); + return OH_NN_UNSUPPORTED; +} + +OH_NN_ReturnCode NNCompiler::RestoreFromCacheBuffer(const void* buffer, size_t length) +{ + LOGE("[NNCompiler] RestoreFromCacheBuffer is not supported currently."); + return OH_NN_UNSUPPORTED; +} + +OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& configs) +{ + LOGI("[NNCompiler] SetExtensionConfig successfully."); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector>& options) +{ + LOGE("[NNCompiler] SetOptions is not supported for NN compiler currently."); + return OH_NN_UNSUPPORTED; +} + +NNExecutor* NNCompiler::CreateExecutor() +{ + if (m_device == nullptr) { + LOGE("[NNCompiler] CreateExecutor failed, m_device is nullptr"); + return nullptr; + } + + if (m_preparedModel == nullptr) { + LOGE("[NNCompiler] CreateExecutor failed, m_device is nullptr"); + return nullptr; + } + + if (m_inputTensorDescs.empty()) { + LOGE("[NNCompiler] CreateExecutor failed, m_inputTensorDescs is empty"); + return nullptr; + } + + if (m_outputTensorDescs.empty()) { + LOGE("[NNCompiler] CreateExecutor failed, m_outputTensorDescs is empty"); + return nullptr; + } + + NNExecutor* nnExecutor = new (std::nothrow) NNExecutor( + m_backendID, m_device, m_preparedModel, m_inputTensorDescs, m_outputTensorDescs); + if (nnExecutor == nullptr) { + LOGE("[NNCompiler] CreateExecutor failed, error happend when allocating NN Executor."); + return nullptr; + } + + return nnExecutor; +} + +OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( + const std::vector, OH_NN_TensorType>>& tensorDescs, Buffer& buffer) const +{ + std::vector immediateTensorDescs; + OH_NN_ReturnCode ret = OH_NN_SUCCESS; + for (const auto& tensorDesc : tensorDescs) { + SerializedTensorDesc immediateTensorDesc; + ret = immediateTensorDesc.CopyFromTensorDesc(tensorDesc); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, error happened when copying tensorDesc to " + "SerializedTensorDesc."); + immediateTensorDescs.clear(); + return ret; + } + immediateTensorDescs.emplace_back(immediateTensorDesc); + } + + size_t totalSize = 0; + for (const auto& tensorDesc : immediateTensorDescs) { + totalSize += SIZE_OF_DATATYPE; + totalSize += SIZE_OF_FORMAT; + totalSize += SIZE_OF_TENSOR_TYPE; + totalSize += SIZE_OF_SHAPE_NUM; + totalSize += tensorDesc.m_shapeNum * sizeof(int32_t); + totalSize += strlen(tensorDesc.m_name) + 1; + } + + // Allocate memory for the serialized data + char* serializedData = new char[totalSize]; + if (serializedData == nullptr) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to create serialized data."); + return OH_NN_NULL_PTR; + } + char* currentPos = serializedData; + + // Serialize each tensor description + for (const auto& tensorDesc : immediateTensorDescs) { + auto memRet = memcpy_s(currentPos, SIZE_OF_DATATYPE, &tensorDesc.m_dataType, SIZE_OF_DATATYPE); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s data type."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += SIZE_OF_DATATYPE; + + memRet = memcpy_s(currentPos, SIZE_OF_FORMAT, &tensorDesc.m_format, SIZE_OF_FORMAT); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s format."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += SIZE_OF_FORMAT; + + memRet = memcpy_s(currentPos, SIZE_OF_TENSOR_TYPE, &tensorDesc.m_tensorType, SIZE_OF_TENSOR_TYPE); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s tensor type."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += SIZE_OF_TENSOR_TYPE; + + memRet = memcpy_s(currentPos, SIZE_OF_SHAPE_NUM, &tensorDesc.m_shapeNum, SIZE_OF_SHAPE_NUM); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s shape num."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += SIZE_OF_SHAPE_NUM; + + size_t sizeOfShape = tensorDesc.m_shapeNum * sizeof(int32_t); + memRet = memcpy_s(currentPos, sizeOfShape, tensorDesc.m_shape, sizeOfShape); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s shape."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += sizeOfShape; + + memRet = strcpy_s(currentPos, strlen(tensorDesc.m_name) + 1, tensorDesc.m_name); + if (memRet != EOK) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, failed to memcpy_s name."); + delete[] serializedData; + return OH_NN_MEMORY_ERROR; + } + currentPos += strlen(tensorDesc.m_name) + 1; + } + + buffer.data = serializedData; + buffer.length = totalSize; + + return OH_NN_SUCCESS; +} + +void ReleaseDescShape(std::vector& immediateTensorDescs) +{ + for (auto desc : immediateTensorDescs) { + delete[] desc.m_shape; + } + immediateTensorDescs.clear(); +} + +OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( + const Buffer& buffer, std::vector, OH_NN_TensorType>>& tensorDescs) +{ + std::vector immediateTensorDescs; + const char* ptr = static_cast(buffer.data); + const char* end = ptr + buffer.length; + while (ptr < end) { + SerializedTensorDesc desc; + + auto memRet = memcpy_s(&desc.m_dataType, SIZE_OF_DATATYPE, ptr, sizeof(desc.m_dataType)); + if (memRet != EOK) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to memcpy_s data type."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_MEMORY_ERROR; + } + ptr += sizeof(desc.m_dataType); + + memRet = memcpy_s(&desc.m_format, SIZE_OF_FORMAT, ptr, sizeof(desc.m_format)); + if (memRet != EOK) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to memcpy_s format."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_MEMORY_ERROR; + } + ptr += sizeof(desc.m_format); + + memRet = memcpy_s(&desc.m_tensorType, SIZE_OF_TENSOR_TYPE, ptr, sizeof(desc.m_tensorType)); + if (memRet != EOK) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to memcpy_s tensor type."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_MEMORY_ERROR; + } + ptr += sizeof(desc.m_tensorType); + + memRet = memcpy_s(&desc.m_shapeNum, SIZE_OF_SHAPE_NUM, ptr, sizeof(desc.m_shapeNum)); + if (memRet != EOK) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to memcpy_s shape num."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_MEMORY_ERROR; + } + ptr += sizeof(desc.m_shapeNum); + + desc.m_shape = new int32_t[desc.m_shapeNum]; + if (desc.m_shape == nullptr) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to create shape buffer."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_NULL_PTR; + } + memRet = memcpy_s(desc.m_shape, desc.m_shapeNum * sizeof(int32_t), ptr, desc.m_shapeNum * sizeof(int32_t)); + if (memRet != EOK) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to memcpy_s shape."); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_MEMORY_ERROR; + } + ptr += desc.m_shapeNum * sizeof(int32_t); + + desc.m_name = ptr; + ptr += std::strlen(desc.m_name) + 1; // +1 for null terminator + + immediateTensorDescs.push_back(desc); + } + + OH_NN_ReturnCode ret {OH_NN_SUCCESS}; + for (const auto& immediateTensorDesc : immediateTensorDescs) { + std::pair, OH_NN_TensorType> tensorDescPair; + tensorDescPair.first = CreateSharedPtr(); + if (tensorDescPair.first == nullptr) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to create tensor desc."); + tensorDescs.clear(); + ReleaseDescShape(immediateTensorDescs); + return OH_NN_NULL_PTR; + } + ret = immediateTensorDesc.CopyToTensorDesc(*(tensorDescPair.first.get())); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, error happened when copying " + "SerializedTensorDesc to TensorDesc."); + tensorDescs.clear(); + ReleaseDescShape(immediateTensorDescs); + return ret; + } + tensorDescPair.second = immediateTensorDesc.m_tensorType; + + tensorDescs.emplace_back(tensorDescPair); + } + + ReleaseDescShape(immediateTensorDescs); + return ret; +} + +} // NeuralNetworkRuntime +} // OHOS \ No newline at end of file diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h new file mode 100644 index 0000000..8d35056 --- /dev/null +++ b/frameworks/native/nncompiler.h @@ -0,0 +1,70 @@ +#include "compiler.h" + +#include "mindir.h" +#include "device.h" +#include "inner_model.h" +#include "prepared_model.h" +#include "nnexecutor.h" + +#ifndef NEURAL_NETWORK_RUNTIME_NNCOMPILER_H +#define NEURAL_NETWORK_RUNTIME_NNCOMPILER_H + +namespace OHOS { +namespace NeuralNetworkRuntime { + +class NNCompiler : public Compiler { +public: + NNCompiler() = delete; + NNCompiler(std::shared_ptr device, size_t backendID); + NNCompiler(const void* model, std::shared_ptr device, size_t backendID); + ~NNCompiler(); + + size_t GetBackendID() const override; + + OH_NN_ReturnCode SetCacheDir(const std::string& cacheModelPath, uint32_t version) override; + OH_NN_ReturnCode SetPerformance(OH_NN_PerformanceMode performance) override; + OH_NN_ReturnCode SetPriority(OH_NN_Priority priority) override; + OH_NN_ReturnCode SetEnableFp16(bool isFp16) override; + + bool IsBuild() const override; + OH_NN_ReturnCode Build() override; + + OH_NN_ReturnCode SaveToCacheFile() const override; + OH_NN_ReturnCode RestoreFromCacheFile() override; + OH_NN_ReturnCode SaveToCacheBuffer(const void* buffer, size_t length, size_t* modelSize) const override; + OH_NN_ReturnCode RestoreFromCacheBuffer(const void* buffer, size_t length) override; + + OH_NN_ReturnCode SetExtensionConfig(const std::unordered_map>& configs) override; + OH_NN_ReturnCode SetOptions(const std::vector>& options) override; + + NNExecutor* CreateExecutor(); + OH_NN_ReturnCode IsSupporttedModel(const std::shared_ptr& liteGraph, + bool& isSupporttedModel) const; + +private: + void ReleaseBuffer(std::vector& buffers) const; + void ReleaseBufferByDevice(std::vector& buffers) const; + OH_NN_ReturnCode SerializeTensorsToBuffer( + const std::vector, OH_NN_TensorType>>& tensorDescs, + Buffer& buffer) const; + OH_NN_ReturnCode DeserializedTensorsFromBuffer( + const Buffer& buffer, std::vector, OH_NN_TensorType>>& tensorDescs); + +private: + void* m_model {nullptr}; + bool m_isBuild {false}; + bool m_enableFp16 {false}; + std::string m_cachePath; + uint32_t m_cacheVersion {0}; + std::shared_ptr m_device {nullptr}; + size_t m_backendID {0}; + OH_NN_Priority m_priority {OH_NN_PRIORITY_NONE}; + OH_NN_PerformanceMode m_performance {OH_NN_PERFORMANCE_NONE}; + std::shared_ptr m_preparedModel {nullptr}; + std::vector, OH_NN_TensorType>> m_inputTensorDescs; + std::vector, OH_NN_TensorType>> m_outputTensorDescs; +}; +} // NeuralNetworkRuntime +} // OHOS + +#endif // NEURAL_NETWORK_RUNTIME_NNCOMPILER_H \ No newline at end of file diff --git a/frameworks/native/device_discover_v1_0.cpp b/frameworks/native/register_hdi_device_v1_0.cpp similarity index 61% rename from frameworks/native/device_discover_v1_0.cpp rename to frameworks/native/register_hdi_device_v1_0.cpp index e5f802e..e3328c1 100644 --- a/frameworks/native/device_discover_v1_0.cpp +++ b/frameworks/native/register_hdi_device_v1_0.cpp @@ -1,27 +1,19 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "device_discover.h" +#include + #include "hdi_device_v1_0.h" #include "common/log.h" #include "common/utils.h" +#include "nnbackend.h" +#include "backend_registrar.h" namespace OHOS { namespace NeuralNetworkRuntime { -std::shared_ptr DiscoverHDIDevicesV1_0(std::string& deviceName, std::string& vendorName, std::string& version) +std::shared_ptr HDIDeviceV1_0Creator() { + std::string deviceName; + std::string vendorName; + std::string version; + // only one device from HDI now. OHOS::sptr iDevice = V1_0::INnrtDevice::Get(); if (iDevice == nullptr) { @@ -34,11 +26,13 @@ std::shared_ptr DiscoverHDIDevicesV1_0(std::string& deviceName, std::str LOGW("Get device name failed. ErrorCode=%d", hdiRet); return nullptr; } + hdiRet = iDevice->GetVendorName(vendorName); if (hdiRet != HDF_SUCCESS) { LOGW("Get vendor name failed. ErrorCode=%d", hdiRet); return nullptr; } + std::pair hdiVersion; hdiRet = iDevice->GetVersion(hdiVersion.first, hdiVersion.second); if (hdiRet != HDF_SUCCESS) { @@ -46,12 +40,21 @@ std::shared_ptr DiscoverHDIDevicesV1_0(std::string& deviceName, std::str return nullptr; } version = 'v' + std::to_string(hdiVersion.first) + '_' + std::to_string(hdiVersion.second); + const std::string& backendName = GenUniqueName(deviceName, vendorName, version); std::shared_ptr device = CreateSharedPtr(iDevice); if (device == nullptr) { LOGW("Failed to register device, because fail to create device instance."); + return nullptr; + } + + std::shared_ptr backend = std::make_shared(device, std::hash{}(backendName)); + if (backend == nullptr) { + LOGW("Failed to register backend, because fail to create backend."); } - return device; + return backend; } + +REGISTER_BACKEND(HDIDeviceV1_0, HDIDeviceV1_0Creator) } // namespace NeuralNetworkRuntime -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/frameworks/native/device_discover_v2_0.cpp b/frameworks/native/register_hdi_device_v2_0.cpp similarity index 72% rename from frameworks/native/device_discover_v2_0.cpp rename to frameworks/native/register_hdi_device_v2_0.cpp index d71ff33..e84e7da 100644 --- a/frameworks/native/device_discover_v2_0.cpp +++ b/frameworks/native/register_hdi_device_v2_0.cpp @@ -1,28 +1,20 @@ -/* - * Copyright (c) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +#include -#include "device_discover.h" #include "hdi_device_v2_0.h" #include "hdi_returncode_utils.h" #include "common/log.h" #include "common/utils.h" +#include "nnbackend.h" +#include "backend_registrar.h" namespace OHOS { namespace NeuralNetworkRuntime { -std::shared_ptr DiscoverHDIDevicesV2_0(std::string& deviceName, std::string& vendorName, std::string& version) +std::shared_ptr HDIDeviceV2_0Creator() { + std::string deviceName; + std::string vendorName; + std::string version; + // only one device from HDI now. OHOS::sptr iDevice = V2_0::INnrtDevice::Get(); if (iDevice == nullptr) { @@ -65,12 +57,21 @@ std::shared_ptr DiscoverHDIDevicesV2_0(std::string& deviceName, std::str return nullptr; } version = 'v' + std::to_string(hdiVersion.first) + '_' + std::to_string(hdiVersion.second); + const std::string& backendName = GenUniqueName(deviceName, vendorName, version); std::shared_ptr device = CreateSharedPtr(iDevice); if (device == nullptr) { - LOGW("Failed to register device, because fail to create device instance."); + LOGW("Failed to create device, because fail to create device instance."); + return nullptr; } - return device; + + std::shared_ptr backend = std::make_shared(device, std::hash{}(backendName)); + if (backend == nullptr) { + LOGW("Failed to register backend, because fail to create backend."); + } + return backend; } + +REGISTER_BACKEND(HDIDeviceV2_0, HDIDeviceV2_0Creator) } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/utils.cpp b/frameworks/native/utils.cpp new file mode 100644 index 0000000..be8d768 --- /dev/null +++ b/frameworks/native/utils.cpp @@ -0,0 +1,12 @@ +#include "common/utils.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +std::string GenUniqueName( + const std::string& deviceName, const std::string& vendorName, const std::string& version) +{ + return deviceName + "_" + vendorName + "_" + version; +} + +} // namespace NeuralNetworkRuntime +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json b/interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json deleted file mode 100644 index 0d58444..0000000 --- a/interfaces/kits/c/neural_network_runtime/libneural_network_runtime.ndk.json +++ /dev/null @@ -1,95 +0,0 @@ -[ - { - "name": "OH_NNModel_Construct" - }, - { - "name": "OH_NNModel_AddTensor" - }, - { - "name": "OH_NNModel_SetTensorData" - }, - { - "name": "OH_NNModel_AddOperation" - }, - { - "name": "OH_NNModel_SpecifyInputsAndOutputs" - }, - { - "name": "OH_NNModel_Finish" - }, - { - "name": "OH_NNModel_Destroy" - }, - { - "name": "OH_NNModel_GetAvailableOperations" - }, - { - "name": "OH_NNCompilation_Construct" - }, - { - "name": "OH_NNCompilation_SetDevice" - }, - { - "name": "OH_NNCompilation_SetCache" - }, - { - "name": "OH_NNCompilation_SetPerformanceMode" - }, - { - "name": "OH_NNCompilation_SetPriority" - }, - { - "name": "OH_NNCompilation_EnableFloat16" - }, - { - "name": "OH_NNCompilation_Build" - }, - { - "name": "OH_NNCompilation_Destroy" - }, - { - "name": "OH_NNExecutor_Construct" - }, - { - "name": "OH_NNExecutor_SetInput" - }, - { - "name": "OH_NNExecutor_SetOutput" - }, - { - "name": "OH_NNExecutor_GetOutputShape" - }, - { - "name": "OH_NNExecutor_Run" - }, - { - "name": "OH_NNExecutor_AllocateInputMemory" - }, - { - "name": "OH_NNExecutor_AllocateOutputMemory" - }, - { - "name": "OH_NNExecutor_DestroyInputMemory" - }, - { - "name": "OH_NNExecutor_DestroyOutputMemory" - }, - { - "name": "OH_NNExecutor_SetInputWithMemory" - }, - { - "name": "OH_NNExecutor_SetOutputWithMemory" - }, - { - "name": "OH_NNExecutor_Destroy" - }, - { - "name": "OH_NNDevice_GetAllDevicesID" - }, - { - "name": "OH_NNDevice_GetName" - }, - { - "name": "OH_NNDevice_GetType" - } -] \ No newline at end of file diff --git a/test/system_test/common/nnrt_test.h b/test/system_test/common/nnrt_test.h index a117096..6e057f6 100644 --- a/test/system_test/common/nnrt_test.h +++ b/test/system_test/common/nnrt_test.h @@ -21,7 +21,7 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/test/system_test/device_test.cpp b/test/system_test/device_test.cpp index 0fe24de..5694873 100644 --- a/test/system_test/device_test.cpp +++ b/test/system_test/device_test.cpp @@ -18,7 +18,7 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" using namespace testing; using namespace testing::ext; diff --git a/test/system_test/end_to_end_test.cpp b/test/system_test/end_to_end_test.cpp index c668209..9248993 100644 --- a/test/system_test/end_to_end_test.cpp +++ b/test/system_test/end_to_end_test.cpp @@ -24,7 +24,7 @@ #include "securec.h" #include "common/log.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" namespace fs = std::filesystem; diff --git a/test/system_test/end_to_end_test.h b/test/system_test/end_to_end_test.h index 7255bce..ae05663 100644 --- a/test/system_test/end_to_end_test.h +++ b/test/system_test/end_to_end_test.h @@ -20,7 +20,7 @@ #include #include -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "test/system_test/common/nnrt_test.h" namespace OHOS { diff --git a/test/unittest/common/v1_0/inner_model_mock_device.cpp b/test/unittest/common/v1_0/inner_model_mock_device.cpp index d9be0bd..0702b96 100644 --- a/test/unittest/common/v1_0/inner_model_mock_device.cpp +++ b/test/unittest/common/v1_0/inner_model_mock_device.cpp @@ -63,7 +63,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::GetSupportedOperation(std::shared_ptrname_ == "Loaded_NNR_Model") { - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } else { return OH_NN_SUCCESS; } diff --git a/test/unittest/common/v2_0/inner_model_mock_device.cpp b/test/unittest/common/v2_0/inner_model_mock_device.cpp index cffa3cc..996ae63 100644 --- a/test/unittest/common/v2_0/inner_model_mock_device.cpp +++ b/test/unittest/common/v2_0/inner_model_mock_device.cpp @@ -63,7 +63,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetSupportedOperation(std::shared_ptrname_ == "Loaded_NNR_Model") { - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } else { return OH_NN_SUCCESS; } diff --git a/test/unittest/components/v1_0/device_manager/device_manager_test.cpp b/test/unittest/components/v1_0/device_manager/device_manager_test.cpp index 583f3f8..9f83369 100644 --- a/test/unittest/components/v1_0/device_manager/device_manager_test.cpp +++ b/test/unittest/components/v1_0/device_manager/device_manager_test.cpp @@ -165,7 +165,7 @@ HWTEST_F(DeviceManagerTest, devicemanager_registerdevice_003, TestSize.Level0) [&device]()->std::shared_ptr {return std::make_shared(device);}; auto& deviceManager = DeviceManager::GetInstance(); OH_NN_ReturnCode result = deviceManager.RegisterDevice(creator); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** @@ -187,7 +187,7 @@ HWTEST_F(DeviceManagerTest, devicemanager_registerdevice_004, TestSize.Level0) [&device]()->std::shared_ptr {return std::make_shared(device);}; auto& deviceManager = DeviceManager::GetInstance(); OH_NN_ReturnCode result = deviceManager.RegisterDevice(creator); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** diff --git a/test/unittest/components/v1_0/hdi_device/hdi_device_test.cpp b/test/unittest/components/v1_0/hdi_device/hdi_device_test.cpp index 2c1be5a..5ce08e8 100644 --- a/test/unittest/components/v1_0/hdi_device/hdi_device_test.cpp +++ b/test/unittest/components/v1_0/hdi_device/hdi_device_test.cpp @@ -163,7 +163,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicename_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), GetDeviceName(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(deviceName), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceName(deviceName); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -201,7 +201,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getvendorname_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), GetVendorName(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(vendorName), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetVendorName(vendorName); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -241,7 +241,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicetype_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), GetDeviceType(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(iDeviceType), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceType(deviceType); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -281,7 +281,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicestatus_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), GetDeviceStatus(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(iDeviceStatus), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceStatus(deviceStatus); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -374,7 +374,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getsupportedoperation_004, TestSize.Level0) std::vector newOps {true}; OH_NN_ReturnCode result = hdiDevice->GetSupportedOperation(model, newOps); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -410,7 +410,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isfloat16precisionsupported_002, TestSize.Leve EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), IsFloat16PrecisionSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsFloat16PrecisionSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -450,7 +450,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isperformancemodesupported_002, TestSize.Level EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), IsPerformanceModeSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsPerformanceModeSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -490,7 +490,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isprioritysupported_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), IsPrioritySupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsPrioritySupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -530,7 +530,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isdynamicinputsupported_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), IsDynamicInputSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsDynamicInputSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -570,7 +570,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_ismodelcachesupported_002, TestSize.Level0) EXPECT_CALL(*((V1_0::MockIDevice *)device.GetRefPtr()), IsModelCacheSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsModelCacheSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -694,7 +694,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_preparemodelfrommodelcache_002, TestSize.Level .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<2>(iPreparedModel), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->PrepareModelFromModelCache(modelCache, config, preparedModel); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * diff --git a/test/unittest/components/v1_0/hdi_prepared_model/hdi_prepared_model_test.cpp b/test/unittest/components/v1_0/hdi_prepared_model/hdi_prepared_model_test.cpp index 413fb5c..1173113 100644 --- a/test/unittest/components/v1_0/hdi_prepared_model/hdi_prepared_model_test.cpp +++ b/test/unittest/components/v1_0/hdi_prepared_model/hdi_prepared_model_test.cpp @@ -201,7 +201,7 @@ HWTEST_F(HDIPreparedModelTest, hidpreparedmodel_exportmodelcache_004, TestSize.L ); OH_NN_ReturnCode result = preparedModel->ExportModelCache(modelCache); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** @@ -291,7 +291,7 @@ HWTEST_F(HDIPreparedModelTest, hidpreparedmodel_run_003, TestSize.Level0) ); OH_NN_ReturnCode result = preparedModel->Run(inputs, outputs, outputsDims, isOutputBufferEnough); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); const auto& memoryManager = MemoryManager::GetInstance(); memoryManager->UnMapMemory(buffer); } diff --git a/test/unittest/components/v1_0/inner_model/inner_model_test.cpp b/test/unittest/components/v1_0/inner_model/inner_model_test.cpp index 7e6dbb2..c51b6ae 100644 --- a/test/unittest/components/v1_0/inner_model/inner_model_test.cpp +++ b/test/unittest/components/v1_0/inner_model/inner_model_test.cpp @@ -777,7 +777,7 @@ HWTEST_F(InnerModelTest, inner_model_get_supported_operation_002, TestSize.Level SetLiteGraph(liteGraph); EXPECT_EQ(OH_NN_SUCCESS, m_innerModelTest.BuildFromLiteGraph(liteGraph)); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, m_innerModelTest.GetSupportedOperations(deviceID, &isSupported, opCount)); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, m_innerModelTest.GetSupportedOperations(deviceID, &isSupported, opCount)); } /** diff --git a/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.cpp b/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.cpp index 159ae96..b869f13 100644 --- a/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.cpp +++ b/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.cpp @@ -73,7 +73,7 @@ std::shared_ptr DeviceManager::GetDevice(size_t deviceId) const OH_NN_ReturnCode HDIDeviceV1_0::GetDeviceType(OH_NN_DeviceType& deviceType) { if (deviceType == OH_NN_OTHERS) { - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; @@ -2254,7 +2254,7 @@ HWTEST_F(NeuralNetworkRuntimeTest, device_get_type_003, testing::ext::TestSize.L OH_NN_DeviceType deviceType = OH_NN_OTHERS; OH_NN_DeviceType* pDeviceType = &deviceType; OH_NN_ReturnCode ret = OH_NNDevice_GetType(deviceID, pDeviceType); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, ret); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, ret); } /* diff --git a/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.h b/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.h index 963ab7d..a79fb48 100644 --- a/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.h +++ b/test/unittest/components/v1_0/neural_network_runtime_test/neural_network_runtime_test.h @@ -18,7 +18,7 @@ #include -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "frameworks/native/inner_model.h" #include "frameworks/native/executor.h" diff --git a/test/unittest/components/v2_0/device_manager/device_manager_test.cpp b/test/unittest/components/v2_0/device_manager/device_manager_test.cpp index 7213c43..3e1040a 100644 --- a/test/unittest/components/v2_0/device_manager/device_manager_test.cpp +++ b/test/unittest/components/v2_0/device_manager/device_manager_test.cpp @@ -165,7 +165,7 @@ HWTEST_F(DeviceManagerTest, devicemanager_registerdevice_003, TestSize.Level0) [&device]()->std::shared_ptr {return std::make_shared(device);}; auto& deviceManager = DeviceManager::GetInstance(); OH_NN_ReturnCode result = deviceManager.RegisterDevice(creator); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** @@ -187,7 +187,7 @@ HWTEST_F(DeviceManagerTest, devicemanager_registerdevice_004, TestSize.Level0) [&device]()->std::shared_ptr {return std::make_shared(device);}; auto& deviceManager = DeviceManager::GetInstance(); OH_NN_ReturnCode result = deviceManager.RegisterDevice(creator); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** diff --git a/test/unittest/components/v2_0/hdi_device/hdi_device_test.cpp b/test/unittest/components/v2_0/hdi_device/hdi_device_test.cpp index 7a6452b..b98529b 100644 --- a/test/unittest/components/v2_0/hdi_device/hdi_device_test.cpp +++ b/test/unittest/components/v2_0/hdi_device/hdi_device_test.cpp @@ -194,7 +194,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicename_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), GetDeviceName(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(deviceName), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceName(deviceName); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -232,7 +232,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getvendorname_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), GetVendorName(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(vendorName), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetVendorName(vendorName); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -272,7 +272,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicetype_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), GetDeviceType(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(iDeviceType), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceType(deviceType); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -312,7 +312,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getdevicestatus_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), GetDeviceStatus(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(iDeviceStatus), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->GetDeviceStatus(deviceStatus); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -414,7 +414,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_getsupportedoperation_004, TestSize.Level0) std::vector newOps {true}; OH_NN_ReturnCode result = hdiDevice->GetSupportedOperation(model, newOps); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -450,7 +450,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isfloat16precisionsupported_002, TestSize.Leve EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), IsFloat16PrecisionSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsFloat16PrecisionSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -490,7 +490,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isperformancemodesupported_002, TestSize.Level EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), IsPerformanceModeSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsPerformanceModeSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -530,7 +530,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isprioritysupported_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), IsPrioritySupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsPrioritySupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -570,7 +570,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_isdynamicinputsupported_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), IsDynamicInputSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsDynamicInputSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * @@ -610,7 +610,7 @@ HWTEST_F(HDIDeviceTest, hdidevice_ismodelcachesupported_002, TestSize.Level0) EXPECT_CALL(*((V2_0::MockIDevice *)device.GetRefPtr()), IsModelCacheSupported(::testing::_)) .WillRepeatedly(::testing::DoAll(::testing::SetArgReferee<0>(isSupported), ::testing::Return(HDF_FAILURE))); OH_NN_ReturnCode result = hdiDevice->IsModelCacheSupported(isSupported); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /* * diff --git a/test/unittest/components/v2_0/hdi_prepared_model/hdi_prepared_model_test.cpp b/test/unittest/components/v2_0/hdi_prepared_model/hdi_prepared_model_test.cpp index b23ec37..a354e58 100644 --- a/test/unittest/components/v2_0/hdi_prepared_model/hdi_prepared_model_test.cpp +++ b/test/unittest/components/v2_0/hdi_prepared_model/hdi_prepared_model_test.cpp @@ -199,7 +199,7 @@ HWTEST_F(HDIPreparedModelTest, hidpreparedmodel_exportmodelcache_004, TestSize.L ); OH_NN_ReturnCode result = preparedModel->ExportModelCache(modelCache); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); } /** @@ -288,7 +288,7 @@ HWTEST_F(HDIPreparedModelTest, hidpreparedmodel_run_003, TestSize.Level0) ); OH_NN_ReturnCode result = preparedModel->Run(inputs, outputs, outputsDims, isOutputBufferEnough); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, result); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, result); const auto& memoryManager = MemoryManager::GetInstance(); memoryManager->UnMapMemory(buffer); } diff --git a/test/unittest/components/v2_0/inner_model/inner_model_test.cpp b/test/unittest/components/v2_0/inner_model/inner_model_test.cpp index 7e6dbb2..c51b6ae 100644 --- a/test/unittest/components/v2_0/inner_model/inner_model_test.cpp +++ b/test/unittest/components/v2_0/inner_model/inner_model_test.cpp @@ -777,7 +777,7 @@ HWTEST_F(InnerModelTest, inner_model_get_supported_operation_002, TestSize.Level SetLiteGraph(liteGraph); EXPECT_EQ(OH_NN_SUCCESS, m_innerModelTest.BuildFromLiteGraph(liteGraph)); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, m_innerModelTest.GetSupportedOperations(deviceID, &isSupported, opCount)); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, m_innerModelTest.GetSupportedOperations(deviceID, &isSupported, opCount)); } /** diff --git a/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.cpp b/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.cpp index aba6b07..6c7d9f8 100644 --- a/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.cpp +++ b/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.cpp @@ -73,7 +73,7 @@ std::shared_ptr DeviceManager::GetDevice(size_t deviceId) const OH_NN_ReturnCode HDIDeviceV2_0::GetDeviceType(OH_NN_DeviceType& deviceType) { if (deviceType == OH_NN_OTHERS) { - return OH_NN_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; @@ -2254,7 +2254,7 @@ HWTEST_F(NeuralNetworkRuntimeTest, device_get_type_003, testing::ext::TestSize.L OH_NN_DeviceType deviceType = OH_NN_OTHERS; OH_NN_DeviceType* pDeviceType = &deviceType; OH_NN_ReturnCode ret = OH_NNDevice_GetType(deviceID, pDeviceType); - EXPECT_EQ(OH_NN_UNAVALIDABLE_DEVICE, ret); + EXPECT_EQ(OH_NN_UNAVAILABLE_DEVICE, ret); } /* diff --git a/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.h b/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.h index 963ab7d..a79fb48 100644 --- a/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.h +++ b/test/unittest/components/v2_0/neural_network_runtime_test/neural_network_runtime_test.h @@ -18,7 +18,7 @@ #include -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "frameworks/native/inner_model.h" #include "frameworks/native/executor.h" -- Gitee From 9e9fcc332aa2a829d837400c23d7d58d3e6e1175 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 12 Dec 2023 16:22:07 +0800 Subject: [PATCH 03/11] bugfix, 1212-v2 Signed-off-by: maoyong --- frameworks/native/nncompiler.cpp | 41 +++++++++++++++----------------- frameworks/native/nncompiler.h | 5 +++- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 275843d..f5d7c2d 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -100,10 +100,17 @@ NNCompiler::NNCompiler(std::shared_ptr device, size_t backendID) : m_device(device), m_backendID(backendID) {} -NNCompiler::NNCompiler(const void* model, std::shared_ptr device, size_t backendID) - : m_model(const_cast(model)), - m_device(device), - m_backendID(backendID) {} +NNCompiler::NNCompiler(const void* model, std::shared_ptr device, size_t backendID) { + m_device = device; + m_backendID = backendID; + const InnerModel* innerModel = reinterpret_cast(model); + m_liteGraph = innerModel->GetLiteGraphs(); + m_inputTensorDescs = innerModel->GetInputTensorDescs(); + m_outputTensorDescs = innerModel->GetOutputTensorDescs(); + m_metaGraph = innerModel->GetMetaGraph(); + m_quantBuffer = innerModel->GetQuantBuffer(); + m_modelName = innerModel->GetModelName(); +} NNCompiler::~NNCompiler() { @@ -112,7 +119,6 @@ NNCompiler::~NNCompiler() } m_inputTensorDescs.clear(); m_outputTensorDescs.clear(); - m_model = nullptr; } size_t NNCompiler::GetBackendID() const @@ -269,32 +275,22 @@ OH_NN_ReturnCode NNCompiler::Build() LOGI("[NNCompiler] Build success, restore from cache file."); m_isBuild = true; return OH_NN_SUCCESS; - } else if (m_model == nullptr) { - LOGI("[NNCompiler] Build failed, fail to restore from cache file."); - return ret; } // cache不存在,正常在线构图 - const InnerModel* innerModel = reinterpret_cast(m_model); - std::shared_ptr liteGraph = innerModel->GetLiteGraphs(); - m_inputTensorDescs = innerModel->GetInputTensorDescs(); - m_outputTensorDescs = innerModel->GetOutputTensorDescs(); - void* metaGraph = innerModel->GetMetaGraph(); - Buffer quantBuffer = innerModel->GetQuantBuffer(); - - if ((liteGraph == nullptr) && (metaGraph == nullptr)) { + if ((m_liteGraph == nullptr) && (m_metaGraph == nullptr)) { LOGE("[NNCompiler] Build failed, both liteGraph and metaGraph are nullptr."); return OH_NN_INVALID_PARAMETER; } - if ((liteGraph != nullptr) && (metaGraph != nullptr)) { + if ((m_liteGraph != nullptr) && (m_metaGraph != nullptr)) { LOGE("[NNCompiler] Build failed, neither liteGraph nor metaGraph are nullptr."); return OH_NN_INVALID_PARAMETER; } // 判断是否支持模型 bool isSupporttedModel = true; - ret = IsSupporttedModel(liteGraph, isSupporttedModel); + ret = IsSupporttedModel(m_liteGraph, isSupporttedModel); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] Build failed, error happend when judge if support the model."); return ret; @@ -305,11 +301,11 @@ OH_NN_ReturnCode NNCompiler::Build() ModelConfig config {m_enableFp16, static_cast(m_performance), static_cast(m_priority)}; - if (liteGraph != nullptr) { - ret = m_device->PrepareModel(liteGraph, config, m_preparedModel); + if (m_liteGraph != nullptr) { + ret = m_device->PrepareModel(m_liteGraph, config, m_preparedModel); } - if (metaGraph != nullptr) { - ret = m_device->PrepareModel(metaGraph, quantBuffer, config, m_preparedModel); + if (m_metaGraph != nullptr) { + ret = m_device->PrepareModel(m_metaGraph, m_quantBuffer, config, m_preparedModel); } if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] Build failed, fail to prepare model when normally building."); @@ -398,6 +394,7 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const caches.emplace_back(outputTensorDescBuffer); tensorBuffers.emplace_back(outputTensorDescBuffer); + compiledCache.SetModelName(m_modelName); ret = compiledCache.Save(caches, m_cachePath, m_cacheVersion); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, error happened when saving model cache."); diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 8d35056..bdde2b7 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -51,7 +51,6 @@ private: const Buffer& buffer, std::vector, OH_NN_TensorType>>& tensorDescs); private: - void* m_model {nullptr}; bool m_isBuild {false}; bool m_enableFp16 {false}; std::string m_cachePath; @@ -61,6 +60,10 @@ private: OH_NN_Priority m_priority {OH_NN_PRIORITY_NONE}; OH_NN_PerformanceMode m_performance {OH_NN_PERFORMANCE_NONE}; std::shared_ptr m_preparedModel {nullptr}; + Buffer m_quantBuffer {nullptr, 0}; + std::string m_modelName; + void* m_metaGraph {nullptr}; + std::shared_ptr m_liteGraph {nullptr}; std::vector, OH_NN_TensorType>> m_inputTensorDescs; std::vector, OH_NN_TensorType>> m_outputTensorDescs; }; -- Gitee From f30d4dd44d8be34ccdd99a1a2aa7e5835e280b97 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 12 Dec 2023 17:28:45 +0800 Subject: [PATCH 04/11] fix codecheck warning Signed-off-by: maoyong --- frameworks/native/backend_manager.cpp | 15 ++++++++++++ frameworks/native/backend_registrar.cpp | 15 ++++++++++++ frameworks/native/backend_registrar.h | 21 +++++++++++++--- frameworks/native/compiler.h | 1 + frameworks/native/neural_network_core.cpp | 4 ++-- frameworks/native/nnbackend.cpp | 15 ++++++++++++ frameworks/native/nnbackend.h | 24 +++++++++++++++---- frameworks/native/nncompiled_cache.cpp | 2 +- frameworks/native/nncompiled_cache.h | 2 +- frameworks/native/nncompiler.cpp | 24 ++++++++++++++++--- frameworks/native/nncompiler.h | 23 ++++++++++++++---- .../native/register_hdi_device_v1_0.cpp | 15 ++++++++++++ .../native/register_hdi_device_v2_0.cpp | 15 ++++++++++++ frameworks/native/utils.cpp | 15 ++++++++++++ 14 files changed, 173 insertions(+), 18 deletions(-) diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp index 64a29d9..0428e47 100644 --- a/frameworks/native/backend_manager.cpp +++ b/frameworks/native/backend_manager.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "backend_manager.h" #include diff --git a/frameworks/native/backend_registrar.cpp b/frameworks/native/backend_registrar.cpp index 99ec5ce..e37cf14 100644 --- a/frameworks/native/backend_registrar.cpp +++ b/frameworks/native/backend_registrar.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "backend_registrar.h" #include "common/log.h" diff --git a/frameworks/native/backend_registrar.h b/frameworks/native/backend_registrar.h index 6646764..277b0bf 100644 --- a/frameworks/native/backend_registrar.h +++ b/frameworks/native/backend_registrar.h @@ -1,12 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H +#define NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H + #include #include #include #include "backend.h" -#ifndef NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H -#define NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H - namespace OHOS { namespace NeuralNetworkRuntime { using CreateBackend = std::function()>; diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h index 3b98440..3b946ff 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef NEURAL_NETWORK_RUNTIME_COMPILER_H #define NEURAL_NETWORK_RUNTIME_COMPILER_H diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index fe84057..55082f7 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -386,7 +386,7 @@ OH_NN_ReturnCode CreateCompiler(Compilation* compilation, Compiler** compiler) BackendManager& manager = BackendManager::GetInstance(); std::shared_ptr backend = manager.GetBackend(compilation->backendID); - if(backend == nullptr) { + if (backend == nullptr) { LOGE("CreateCompiler failed, fail to get backend %{public}zu.", compilation->backendID); return OH_NN_FAILED; } @@ -526,7 +526,7 @@ NNRT_API void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) if (compilationImpr->compiler != nullptr) { BackendManager& manager = BackendManager::GetInstance(); std::shared_ptr backend = manager.GetBackend(compilationImpr->backendID); - if(backend == nullptr) { + if (backend == nullptr) { LOGE("OH_NNCompilation_Destroy failed, fail to get backend %{public}zu.", compilationImpr->backendID); return; } diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index fde6190..62b2f9b 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "nnbackend.h" #include diff --git a/frameworks/native/nnbackend.h b/frameworks/native/nnbackend.h index 5359773..8268170 100644 --- a/frameworks/native/nnbackend.h +++ b/frameworks/native/nnbackend.h @@ -1,19 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_NNBACKEND_H +#define NEURAL_NETWORK_RUNTIME_NNBACKEND_H + #include "backend.h" + #include "executor.h" #include "tensor.h" #include "tensor_desc.h" #include "device.h" #include "nncompiler.h" -#ifndef NEURAL_NETWORK_RUNTIME_NNBACKEND_H -#define NEURAL_NETWORK_RUNTIME_NNBACKEND_H - namespace OHOS { namespace NeuralNetworkRuntime { class NNBackend : public Backend { public: explicit NNBackend(const std::shared_ptr& device, size_t backendID); - ~NNBackend(); + ~NNBackend() override; // Backend Info size_t GetBackendID() const override; diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 75c2ce6..615ade2 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/frameworks/native/nncompiled_cache.h b/frameworks/native/nncompiled_cache.h index 2664cac..d8f245a 100644 --- a/frameworks/native/nncompiled_cache.h +++ b/frameworks/native/nncompiled_cache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index f5d7c2d..2d9168e 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "nncompiler.h" #include @@ -13,6 +28,9 @@ namespace OHOS { namespace NeuralNetworkRuntime { namespace { +const int CACHE_INPUT_TENSORDESC_OFFSET = 2; +const int CACHE_OUTPUT_TENSORDESC_OFFSET = 1; + struct SerializedTensorDesc { public: SerializedTensorDesc() = default; @@ -440,14 +458,14 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } size_t cacheNum = caches.size(); - ret = DeserializedTensorsFromBuffer(caches[cacheNum-2], m_inputTensorDescs); + ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_INPUT_TENSORDESC_OFFSET], m_inputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing input tensor desc."); ReleaseBufferByDevice(caches); return ret; } - ret = DeserializedTensorsFromBuffer(caches[cacheNum-1], m_outputTensorDescs); + ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_OUTPUT_TENSORDESC_OFFSET], m_outputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing output tensor desc."); ReleaseBufferByDevice(caches); @@ -458,7 +476,7 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() config.enableFloat16 = m_enableFp16; config.mode = m_performance; config.priority = m_priority; - std::vector modelOnlyCaches(caches.begin(), caches.end()-2); + std::vector modelOnlyCaches(caches.begin(), caches.end() - CACHE_INPUT_TENSORDESC_OFFSET); ret = m_device->PrepareModelFromModelCache(modelOnlyCaches, config, m_preparedModel); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when preparing model from cache."); diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index bdde2b7..3abb29a 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NEURAL_NETWORK_RUNTIME_NNCOMPILER_H +#define NEURAL_NETWORK_RUNTIME_NNCOMPILER_H + #include "compiler.h" #include "mindir.h" @@ -6,9 +24,6 @@ #include "prepared_model.h" #include "nnexecutor.h" -#ifndef NEURAL_NETWORK_RUNTIME_NNCOMPILER_H -#define NEURAL_NETWORK_RUNTIME_NNCOMPILER_H - namespace OHOS { namespace NeuralNetworkRuntime { @@ -17,7 +32,7 @@ public: NNCompiler() = delete; NNCompiler(std::shared_ptr device, size_t backendID); NNCompiler(const void* model, std::shared_ptr device, size_t backendID); - ~NNCompiler(); + ~NNCompiler() override; size_t GetBackendID() const override; diff --git a/frameworks/native/register_hdi_device_v1_0.cpp b/frameworks/native/register_hdi_device_v1_0.cpp index e3328c1..bbd9bc1 100644 --- a/frameworks/native/register_hdi_device_v1_0.cpp +++ b/frameworks/native/register_hdi_device_v1_0.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include "hdi_device_v1_0.h" diff --git a/frameworks/native/register_hdi_device_v2_0.cpp b/frameworks/native/register_hdi_device_v2_0.cpp index e84e7da..689682e 100644 --- a/frameworks/native/register_hdi_device_v2_0.cpp +++ b/frameworks/native/register_hdi_device_v2_0.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include "hdi_device_v2_0.h" diff --git a/frameworks/native/utils.cpp b/frameworks/native/utils.cpp index be8d768..2a635fe 100644 --- a/frameworks/native/utils.cpp +++ b/frameworks/native/utils.cpp @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "common/utils.h" namespace OHOS { -- Gitee From 8e49af00617e25351417f39cd2260d7ae325b721 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 12 Dec 2023 22:18:51 +0800 Subject: [PATCH 05/11] fix codecheck Signed-off-by: maoyong --- frameworks/native/neural_network_core.cpp | 37 ++++++++--- frameworks/native/neural_network_runtime.cpp | 4 +- .../native/neural_network_runtime_compat.cpp | 1 - frameworks/native/nn_tensor.h | 2 +- frameworks/native/nncompiled_cache.cpp | 8 +-- frameworks/native/nncompiler.cpp | 8 ++- frameworks/native/nnexecutor.cpp | 4 +- frameworks/native/nnexecutor.h | 44 ++++++------- frameworks/native/nntensor.cpp | 7 +- frameworks/native/nntensor.h | 6 +- frameworks/native/ops/ops_validation.cpp | 2 - frameworks/native/tensor.h | 2 +- frameworks/native/tensor_desc.h | 2 +- .../neural_network_core.h | 66 ++++++++++--------- 14 files changed, 109 insertions(+), 84 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 55082f7..fe71934 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -649,7 +649,9 @@ NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, co return tensorDescImpl->SetShape(shape, shapeLength); } -NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength) +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, + int32_t **shape, + size_t *shapeLength) { if (tensorDesc == nullptr) { LOGE("OH_NNTensorDesc_GetShape failed, tensorDesc is nullptr."); @@ -792,8 +794,10 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *t return tensor; } -NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( - size_t deviceID, NN_TensorDesc *tensorDesc, int fd, size_t size, size_t offset) +NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, + NN_TensorDesc *tensorDesc, + int fd, size_t size, + size_t offset) { if (tensorDesc == nullptr) { LOGE("OH_NNTensor_CreateWithFd failed, tensorDesc is nullptr."); @@ -1012,8 +1016,10 @@ NNRT_API void OH_NNExecutor_Destroy(OH_NNExecutor **executor) *executor = nullptr; } -NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape( - OH_NNExecutor *executor, uint32_t outputIndex, int32_t **shape, uint32_t *shapeLength) +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, + uint32_t outputIndex, + int32_t **shape, + uint32_t *shapeLength) { if (executor == nullptr) { LOGE("OH_NNExecutor_GetOutputShape failed, executor is nullptr."); @@ -1091,7 +1097,10 @@ NNRT_API NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor } NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, - size_t index, size_t **minInputDims, size_t **maxInputDims, size_t *shapeLength) + size_t index, + size_t **minInputDims, + size_t **maxInputDims, + size_t *shapeLength) { if (executor == nullptr) { LOGE("OH_NNExecutor_GetInputDimRange failed, executor is nullptr."); @@ -1145,7 +1154,10 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor } NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, - NN_Tensor *inputTensor[], size_t inputCount, NN_Tensor *outputTensor[], size_t outputCount) + NN_Tensor *inputTensor[], + size_t inputCount, + NN_Tensor *outputTensor[], + size_t outputCount) { if (executor == nullptr) { LOGE("OH_NNExecutor_RunSync failed, executor is nullptr."); @@ -1172,8 +1184,13 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, return executorImpl->RunSync(inputTensor, inputCount, outputTensor, outputCount); } -NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Tensor* inputTensor[], - size_t inputCount, NN_Tensor* outputTensor[], size_t outputCount, int32_t timeout, void* userData) +NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, + NN_Tensor* inputTensor[], + size_t inputCount, + NN_Tensor* outputTensor[], + size_t outputCount, + int32_t timeout, + void* userData) { if (executor == nullptr) { LOGE("OH_NNExecutor_RunAsync failed, executor is nullptr."); @@ -1195,7 +1212,7 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Ten LOGE("OH_NNExecutor_RunAsync failed, outputCount is 0."); return OH_NN_INVALID_PARAMETER; } - if (userData == 0) { + if (userData == nullptr) { LOGE("OH_NNExecutor_RunAsync failed, userData is nullptr."); return OH_NN_INVALID_PARAMETER; } diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp index b34fce5..dc7a613 100644 --- a/frameworks/native/neural_network_runtime.cpp +++ b/frameworks/native/neural_network_runtime.cpp @@ -68,7 +68,9 @@ NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam* quantParams, return OH_NN_SUCCESS; } -NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam* quantParams, const int32_t* zeroPoints, size_t quantNum) +NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam* quantParams, + const int32_t* zeroPoints, + size_t quantNum) { if (quantParams == nullptr) { LOGE("OH_NNQuantParam_SetZeroPoints failed, passed nullptr to quantParams."); diff --git a/frameworks/native/neural_network_runtime_compat.cpp b/frameworks/native/neural_network_runtime_compat.cpp index c6e3cd2..d1b348a 100644 --- a/frameworks/native/neural_network_runtime_compat.cpp +++ b/frameworks/native/neural_network_runtime_compat.cpp @@ -84,7 +84,6 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, NNExecutor *executorImpl = reinterpret_cast(executor); return executorImpl->SetOutput(outputIndex, dataBuffer, length); - } NNRT_API OH_NN_ReturnCode OH_NNExecutor_Run(OH_NNExecutor *executor) diff --git a/frameworks/native/nn_tensor.h b/frameworks/native/nn_tensor.h index f2d091d..9eec18d 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -20,9 +20,9 @@ #include #include "cpp_type.h" +#include "tensor_desc.h" #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "interfaces/innerkits/c/neural_network_runtime_inner.h" -#include "tensor_desc.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 615ade2..8093c19 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -110,8 +110,8 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, } if ((uint64_t)version > cacheInfo.version) { - LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %{public}u, but the cache files " - "version is %{public}zu.", + LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %{public}u, " + "but the cache files version is %{public}zu.", version, (size_t)cacheInfo.version); return OH_NN_INVALID_PARAMETER; @@ -126,7 +126,7 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, for (uint32_t i = 0; i < cacheInfo.fileNumber; ++i) { std::string cacheModelPath = cacheDir + "/" + m_modelName + std::to_string(i) + ".nncache"; if (access(cacheModelPath.c_str(), 0) != 0) { - LOGE("[NNCompiledCache] Restore failed, %s is not exist.", cacheModelPath.c_str()); + LOGE("[NNCompiledCache] Restore failed, %{public}s is not exist.", cacheModelPath.c_str()); return OH_NN_INVALID_PARAMETER; } @@ -139,7 +139,7 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, if (GetCrc16(static_cast(modelBuffer.data), modelBuffer.length) != cacheInfo.modelCheckSum[i]) { - LOGE("[NNCompiledCache] Restore failed, the cache model file %s has been changed.", + LOGE("[NNCompiledCache] Restore failed, the cache model file %{public}s has been changed.", cacheModelPath.c_str()); return OH_NN_INVALID_FILE; } diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 2d9168e..eae2022 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -105,7 +105,7 @@ public: OH_NN_TensorType m_tensorType{OH_NN_TENSOR}; size_t m_shapeNum{0}; int32_t* m_shape{nullptr}; - const char* m_name{nullptr}; // null-terminated + const char* m_name{nullptr}; // null-terminated }; const size_t SIZE_OF_DATATYPE = sizeof(SerializedTensorDesc::m_dataType); @@ -118,7 +118,8 @@ NNCompiler::NNCompiler(std::shared_ptr device, size_t backendID) : m_device(device), m_backendID(backendID) {} -NNCompiler::NNCompiler(const void* model, std::shared_ptr device, size_t backendID) { +NNCompiler::NNCompiler(const void* model, std::shared_ptr device, size_t backendID) +{ m_device = device; m_backendID = backendID; const InnerModel* innerModel = reinterpret_cast(model); @@ -450,6 +451,7 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } std::vector caches; + compiledCache.SetModelName(m_modelName); ret = compiledCache.Restore(m_cachePath, m_cacheVersion, caches); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when restoring model cache."); @@ -458,6 +460,7 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } size_t cacheNum = caches.size(); + m_inputTensorDescs.clear(); ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_INPUT_TENSORDESC_OFFSET], m_inputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing input tensor desc."); @@ -465,6 +468,7 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() return ret; } + m_outputTensorDescs.clear(); ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_OUTPUT_TENSORDESC_OFFSET], m_outputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing output tensor desc."); diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 6bd9671..2ac49b0 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -566,8 +566,8 @@ OH_NN_ReturnCode NNExecutor::SetInput(uint32_t index, const OH_NN_Tensor& nnTens return OH_NN_SUCCESS; } - -OH_NN_ReturnCode NNExecutor::SetInputFromMemory(uint32_t index, const OH_NN_Tensor& nnTensor, const OH_NN_Memory& memory) +OH_NN_ReturnCode NNExecutor::SetInputFromMemory( + uint32_t index, const OH_NN_Tensor& nnTensor,const OH_NN_Memory& memory) { auto nnRet = CheckInputDimRanges(index, nnTensor); if (nnRet == OH_NN_OPERATION_FORBIDDEN) { diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index bf011c7..8ad766f 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -32,30 +32,30 @@ public: const std::vector, OH_NN_TensorType>>& outputTensorDescs); virtual ~NNExecutor(); - virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, - size_t** minInputDims, - size_t** maxInputDims, - size_t* shapeNum) const override; - virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) const override; + OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, + size_t** minInputDims, + size_t** maxInputDims, + size_t* shapeNum) const override; + OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) const override; - virtual size_t GetInputNum() const override; - virtual size_t GetOutputNum() const override; - virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) const override; - virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) const override; + size_t GetInputNum() const override; + size_t GetOutputNum() const override; + NN_TensorDesc* CreateInputTensorDesc(size_t index) const override; + NN_TensorDesc* CreateOutputTensorDesc(size_t index) const override; - virtual OH_NN_ReturnCode SetOnRunDone(NN_OnRunDone onRunDone) override; - virtual OH_NN_ReturnCode SetOnServiceDied(NN_OnServiceDied onServiceDied) override; - virtual OH_NN_ReturnCode RunSync(NN_Tensor* inputTensors[], - size_t inputSize, - NN_Tensor* outputTensors[], - size_t outputSize) override; - virtual OH_NN_ReturnCode RunAsync(NN_Tensor* inputTensors[], - size_t inputSize, - NN_Tensor* outputTensors[], - size_t outputSize, - int32_t timeout, - void* userData) override; - virtual size_t GetBackendID() override; + OH_NN_ReturnCode SetOnRunDone(NN_OnRunDone onRunDone) override; + OH_NN_ReturnCode SetOnServiceDied(NN_OnServiceDied onServiceDied) override; + OH_NN_ReturnCode RunSync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize) override; + OH_NN_ReturnCode RunAsync(NN_Tensor* inputTensors[], + size_t inputSize, + NN_Tensor* outputTensors[], + size_t outputSize, + int32_t timeout, + void* userData) override; + size_t GetBackendID() override; // The following APIs are compatible with older versions OH_NN_ReturnCode SetInput(uint32_t index, const OH_NN_Tensor& nnTensor, const void* buffer, size_t length); diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index dfbf242..e0befa9 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -13,12 +13,13 @@ * limitations under the License. */ +#include +#include + +#include "common/log.h" #include "backend_manager.h" #include "nnbackend.h" #include "nntensor.h" -#include "common/log.h" -#include -#include #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { diff --git a/frameworks/native/nntensor.h b/frameworks/native/nntensor.h index 24ba9fc..c15e3cd 100644 --- a/frameworks/native/nntensor.h +++ b/frameworks/native/nntensor.h @@ -16,15 +16,15 @@ #ifndef NEURAL_NETWORK_RUNTIME_NNTENSOR_H #define NEURAL_NETWORK_RUNTIME_NNTENSOR_H -#include "tensor.h" #include +#include "tensor.h" namespace OHOS { namespace NeuralNetworkRuntime { class NNTensor2_0 : public Tensor { public: - NNTensor2_0(size_t backendID) : m_backendID(backendID) {} - virtual ~NNTensor2_0(); + explicit NNTensor2_0(size_t backendID) : m_backendID(backendID) {} + ~NNTensor2_0() override; OH_NN_ReturnCode SetTensorDesc(const TensorDesc* tensorDesc) override; OH_NN_ReturnCode CreateData() override; diff --git a/frameworks/native/ops/ops_validation.cpp b/frameworks/native/ops/ops_validation.cpp index 988ffd8..c042d25 100644 --- a/frameworks/native/ops/ops_validation.cpp +++ b/frameworks/native/ops/ops_validation.cpp @@ -13,8 +13,6 @@ * limitations under the License. */ -// #include "mindir_types.h" // todo - #include "ops_validation.h" #include "mindir_types.h" diff --git a/frameworks/native/tensor.h b/frameworks/native/tensor.h index 0ab606f..49d56a4 100644 --- a/frameworks/native/tensor.h +++ b/frameworks/native/tensor.h @@ -16,8 +16,8 @@ #ifndef NEURAL_NETWORK_RUNTIME_TENSOR_H #define NEURAL_NETWORK_RUNTIME_TENSOR_H -#include "tensor_desc.h" #include +#include "tensor_desc.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/tensor_desc.h b/frameworks/native/tensor_desc.h index b16e379..6286797 100644 --- a/frameworks/native/tensor_desc.h +++ b/frameworks/native/tensor_desc.h @@ -16,9 +16,9 @@ #ifndef NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H #define NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H -#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include #include +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_core.h b/interfaces/kits/c/neural_network_runtime/neural_network_core.h index 7ba73a2..3e7ae31 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_core.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -81,7 +81,6 @@ OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model); * * You should perform the offline compilation during your development and deploy the offline model in your app package. \n * - * * @param modelPath Offline model file path. * @return Pointer to an {@link OH_NNCompilation} instance. * @since 11 @@ -95,7 +94,8 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *mod * This method conflicts with the way of passing an online built model or an offline model file path, * and you have to choose only one of the three construction methods. \n * - * After {@link OH_NNCompilation_Build} is called, the modelBuffer<\b> can be released. \n + * Note that the returned {@link OH_NNCompilation} instance only saves the modelBuffer<\b> pointer inside, instead of + * copying its data. You should not release modelBuffer<\b> before the {@link OH_NNCompilation} instance is destroied. \n * * @param modelBuffer Offline model file buffer. * @param modelSize Offfline model buffer size. @@ -143,7 +143,8 @@ OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilat * * {@link OH_NNCompilation_Build} should be called to complete the restoration after {@link OH_NNCompilation_ImportCacheFromBuffer} is called. \n * - * After {@link OH_NNCompilation_Build} is called, the buffer<\b> can be released. \n + * Note that compilation<\b> only saves the buffer<\b> pointer inside, instead of copying its data. You should not + * release buffer<\b> before compilation<\b> is destroied. \n * * @param compilation Pointer to the {@link OH_NNCompilation} instance. * @param buffer Pointer to the given buffer. @@ -186,10 +187,11 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati * * In the compilation phase, you need to specify the device for model compilation and computing. Call {@link OH_NNDevice_GetAllDevicesID} * to obtain available device IDs. Call {@link OH_NNDevice_GetType} and {@link OH_NNDevice_GetName} to obtain device information - * and pass target device IDs to this method for setting. \n + * and pass target device ID to this method for setting. \n + * * * @param compilation Pointer to the {@link OH_NNCompilation} instance. - * @param deviceID Device ID. + * @param deviceID Device id. If it is 0, the 0th device in the current device list will be used. * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. * @since 9 @@ -308,8 +310,9 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation); /** * @brief Releases the Compilation object. * - * This method needs to be called to release the compilation instance created by calling {@link OH_NNCompilation_Construct}. - * Otherwise, the memory leak will occur. \n + * This method needs to be called to release the compilation instance created by {@link OH_NNCompilation_Construct}, + * {@link OH_NNCompilation_ConstructWithOfflineModelFile}, {@link OH_NNCompilation_ConstructWithOfflineModelBuffer} and + * {@link OH_NNCompilation_ConstructForCache}. Otherwise, the memory leak will occur. \n * * If compilation or *compilation is a null pointer, this method only prints warning logs and does not execute the release. \n * @@ -431,7 +434,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH * * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor shape. \n * - * if tensorDesc or shape is a null pointer, or shapeNum is 0, this method will return error code. \n + * if tensorDesc or shape is a null pointer, or shapeLength is 0, this method will return error code. \n * * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param shape The shape list of the tensor that needs to be set. @@ -448,7 +451,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32 * * Call this method to obtain the shape of the specified {@link NN_TensorDesc} instance. \n * - * if tensorDesc, shape or shapeNum is a null pointer, this method will return error code. + * if tensorDesc, shape or shapeLength is a null pointer, this method will return error code. * As an output parameter, *shape must be a null pointer, otherwise the method will return an error code. * Fou example, you should define int32_t* tensorShape = NULL, and pass &tensorShape as the argument of shape. \n * @@ -546,13 +549,13 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, si * * If the tensor shape is dynamic, this method will return error code. \n * - * deviceID indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. \n + * deviceID indicates the selected device. If it is 0, the 0th device is used. \n * * tensorDesc must be provided, and this method will return an error code if it is a null pointer. \n * * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param deviceID Device id. If it is 0, the 0th device in the current device list will be used. * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @return Pointer to a {@link NN_Tensor} instance. * @since 11 @@ -569,7 +572,7 @@ NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); * Note that this method will copy the tensorDesc into {@link NN_Tensor}. Therefore you should destroy tensorDesc * by {@link OH_NNTensorDesc_Destroy} when it is no longer used. \n * - * deviceName indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. \n + * deviceID indicates the selected device. If it is 0, the 0th device is used. \n * * tensorDesc must be provided, if it is a null pointer, the method returns an error code. * size must be no less than the byte size of tensorDesc. Otherwise, this method will return an error code. If the tensor @@ -577,7 +580,7 @@ NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); * * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param deviceID Device id. If it is 0, the 0th device in the current device list will be used. * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param size Size of tensor data that need to be allocated. * @return Pointer to a {@link NN_Tensor} instance. @@ -599,12 +602,13 @@ NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc * instance you created must use a new tensorDesc that has not been used by another {@link NN_Tensor} instance. * Otherwise, a tensorDesc will be released twice, which will bring a memory corruption of doulbe free. \n * - * deviceName indicates the selected device, which can be a null pointer. If it is a null pointer, the 0th device is used by default. + * deviceID indicates the selected device. If it is 0, the 0th device is used. \n + * * tensorDesc must be provided, if it is a null pointer, the method returns an error code. \n * * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceID The device id which can be a null pointer. If it is a null pointer, the 0th device in the current device list will be used by default. + * @param deviceID Device id. If it is 0, the 0th device in the current device list will be used. * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param fd Fd of the shared memory to be resued. * @param size Size of the shared memory to be resued. @@ -671,40 +675,40 @@ NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor); void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); /** - * @brief Gets the data size of a {@link NN_Tensor}. + * @brief Gets the data fd of a {@link NN_Tensor}. * - * The tensor data size is as same as the argument size of {@link OH_NNTensor_CreateWithSize} and {@link OH_NNTensor_CreateWithFd}. - * But for a tensor created by {@link OH_NNTensor_Create}, it equals to the tensor byte size. \n - * - * Note that you are only allowed to access the tensor data buffer with length of (size - offset), otherwise a heap corruption may occur. \n + * The fd corresponds to a shared memory on device driver, and can be resued by another {@link NN_Tensor} through + * {@link OH_NNTensor_CreateWithFd}. \n * - * if tensor or size is a null pointer, this method will return error code. \n + * if tensor or fd is a null pointer, this method will return error code. \n * * @param tensor Pointer to the {@link NN_Tensor} instance. - * @param size The returned size of tensor data. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * @param fd The returned fd of tensor data. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); +OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); /** - * @brief Gets the data fd of a {@link NN_Tensor}. + * @brief Gets the data size of a {@link NN_Tensor}. * - * The fd corresponds to a shared memory on device driver, and can be resued by another {@link NN_Tensor} through - * {@link OH_NNTensor_CreateWithFd}. \n + * The tensor data size is as same as the argument size of {@link OH_NNTensor_CreateWithSize} and {@link OH_NNTensor_CreateWithFd}. + * But for a tensor created by {@link OH_NNTensor_Create}, it equals to the tensor byte size. \n * - * if tensor or fd is a null pointer, this method will return error code. \n + * Note that you are only allowed to access the tensor data buffer with length of (size - offset), otherwise a heap corruption may occur. \n + * + * if tensor or size is a null pointer, this method will return error code. \n * * @param tensor Pointer to the {@link NN_Tensor} instance. - * @param fd The returned fd of tensor data. - * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. + * @param size The returned size of tensor data. + * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. * If the operation fails, an error code is returned. For details about the error codes, see {@link OH_NN_ReturnCode}. * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); +OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); /** * @brief Get the data offset of a tensor. -- Gitee From 0163f7c7d2bd9c1973fc75e653255f07f7e0e2ec Mon Sep 17 00:00:00 2001 From: maoyong Date: Wed, 13 Dec 2023 09:15:40 +0800 Subject: [PATCH 06/11] fixbug, 1213-v2 Signed-off-by: maoyong --- frameworks/native/nncompiler.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index eae2022..14113f2 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -460,16 +460,16 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } size_t cacheNum = caches.size(); - m_inputTensorDescs.clear(); - ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_INPUT_TENSORDESC_OFFSET], m_inputTensorDescs); + std::vector, OH_NN_TensorType>> inputTensorDescs; + ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_INPUT_TENSORDESC_OFFSET], inputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing input tensor desc."); ReleaseBufferByDevice(caches); return ret; } - m_outputTensorDescs.clear(); - ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_OUTPUT_TENSORDESC_OFFSET], m_outputTensorDescs); + std::vector, OH_NN_TensorType>> outputTensorDescs; + ret = DeserializedTensorsFromBuffer(caches[cacheNum - CACHE_OUTPUT_TENSORDESC_OFFSET], outputTensorDescs); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when deserializing output tensor desc."); ReleaseBufferByDevice(caches); @@ -489,6 +489,8 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } ReleaseBufferByDevice(caches); + m_inputTensorDescs = inputTensorDescs; + m_outputTensorDescs = outputTensorDescs; LOGI("[NNCompiler] Restore model cache successfully."); return OH_NN_SUCCESS; } -- Gitee From 7800dd973a488cc4ba70e30226c2c70931ced2a8 Mon Sep 17 00:00:00 2001 From: maoyong Date: Wed, 13 Dec 2023 10:41:06 +0800 Subject: [PATCH 07/11] fix print error, 1213-v2 Signed-off-by: maoyong --- frameworks/native/nnbackend.cpp | 2 +- frameworks/native/nncompiler.cpp | 14 ++++++------- frameworks/native/nncompiler.h | 4 ++-- .../neural_network_core.h | 4 ++-- .../neural_network_runtime_type.h | 20 +++++++++---------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 62b2f9b..9b74d4c 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -245,7 +245,7 @@ OH_NN_ReturnCode NNBackend::GetSupportedOperation(std::shared_ptrGetSupportedOperation(model, ops); if (ret != OH_NN_SUCCESS) { - LOGE("[NNBackend] GetSupportedOperation failed, fail to get supportted ops from device."); + LOGE("[NNBackend] GetSupportedOperation failed, fail to get supported ops from device."); return OH_NN_FAILED; } diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 14113f2..0b43038 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -254,8 +254,8 @@ bool NNCompiler::IsBuild() const return m_isBuild; } -OH_NN_ReturnCode NNCompiler::IsSupporttedModel(const std::shared_ptr& liteGraph, - bool& isSupporttedModel) const +OH_NN_ReturnCode NNCompiler::IsSupportedModel(const std::shared_ptr& liteGraph, + bool& isSupportedModel) const { std::vector supportedList; OH_NN_ReturnCode ret = m_device->GetSupportedOperation(liteGraph, supportedList); @@ -268,12 +268,12 @@ OH_NN_ReturnCode NNCompiler::IsSupporttedModel(const std::shared_ptr>& options) override; NNExecutor* CreateExecutor(); - OH_NN_ReturnCode IsSupporttedModel(const std::shared_ptr& liteGraph, - bool& isSupporttedModel) const; + OH_NN_ReturnCode IsSupportedModel(const std::shared_ptr& liteGraph, + bool& isSupportedModel) const; private: void ReleaseBuffer(std::vector& buffers) const; diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_core.h b/interfaces/kits/c/neural_network_runtime/neural_network_core.h index 3e7ae31..c1fafc3 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_core.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -189,7 +189,7 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati * to obtain available device IDs. Call {@link OH_NNDevice_GetType} and {@link OH_NNDevice_GetName} to obtain device information * and pass target device ID to this method for setting. \n * - * + * * @param compilation Pointer to the {@link OH_NNCompilation} instance. * @param deviceID Device id. If it is 0, the 0th device in the current device list will be used. * @return Execution result of the function. If the operation is successful, OH_NN_SUCCESS is returned. @@ -602,7 +602,7 @@ NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc * instance you created must use a new tensorDesc that has not been used by another {@link NN_Tensor} instance. * Otherwise, a tensorDesc will be released twice, which will bring a memory corruption of doulbe free. \n * - * deviceID indicates the selected device. If it is 0, the 0th device is used. \n + * deviceID indicates the selected device. If it is 0, the 0th device is used. \n * * tensorDesc must be provided, if it is a null pointer, the method returns an error code. \n * diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h index 03c9fe9..46a47ea 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h @@ -153,33 +153,33 @@ typedef enum { * @deprecated since 11 * @useinstead {@link OH_NN_UNAVAILABLE_DEVICE} */ - OH_NN_UNAVALIABLE_DEVICE = 7, + OH_NN_UNAVALIDABLE_DEVICE = 7, /** Invalid path. */ OH_NN_INVALID_PATH = 8, - /** A hardware error occurs, for example, HDL service crash. - * @since 11 - */ - OH_NN_UNAVAILABLE_DEVICE = 9, /** Timeout. * @since 11 */ - OH_NN_TIMEOUT = 10, + OH_NN_TIMEOUT = 9, /** Unsupported. * @since 11 */ - OH_NN_UNSUPPORTED = 11, + OH_NN_UNSUPPORTED = 10, /** Connection Exception. * @since 11 */ - OH_NN_CONNECTION_EXCEPTION = 12, + OH_NN_CONNECTION_EXCEPTION = 11, /** Save cache exception. * @since 11 */ - OH_NN_SAVE_CACHE_EXCEPTION = 13, + OH_NN_SAVE_CACHE_EXCEPTION = 12, /** Dynamic shape. * @since 11 */ - OH_NN_DYNAMIC_SHAPE = 14 + OH_NN_DYNAMIC_SHAPE = 13, + /** A hardware error occurs, for example, HDL service crash. + * @since 11 + */ + OH_NN_UNAVAILABLE_DEVICE = 14 } OH_NN_ReturnCode; -- Gitee From 9a550157f6821e83e2e9f8c2e326a82a2fe0b539 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 13 Dec 2023 11:48:56 +0800 Subject: [PATCH 08/11] codedex Signed-off-by: wangchuanxia --- frameworks/native/neural_network_core.cpp | 2 +- frameworks/native/nnexecutor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index fe71934..26a5cd5 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -170,7 +170,7 @@ NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(cons return nnCompilation; } -NNRT_API NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructForCache() +NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructForCache() { Compilation *compilation = new (std::nothrow) Compilation(); if (compilation == nullptr) { diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index 8ad766f..843539c 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -30,7 +30,7 @@ public: std::shared_ptr preparedModel, const std::vector, OH_NN_TensorType>>& inputTensorDescs, const std::vector, OH_NN_TensorType>>& outputTensorDescs); - virtual ~NNExecutor(); + ~NNExecutor() override; OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, size_t** minInputDims, -- Gitee From 2131f72dc251bd483d5463d90478ef736f651457 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 13 Dec 2023 15:57:48 +0800 Subject: [PATCH 09/11] buildgn format fix Signed-off-by: wangchuanxia --- frameworks/BUILD.gn | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 90d5d4c..e931ef2 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -31,18 +31,18 @@ nnrt_sources = [ "native/neural_network_runtime_compat.cpp", "native/neural_network_runtime.cpp", "native/nn_tensor.cpp", + "native/nnbackend.cpp", + "native/nncompiled_cache.cpp", + "native/nncompiler.cpp", "native/nnexecutor.cpp", "native/nntensor.cpp", "native/ops_builder.cpp", "native/ops_registry.cpp", - "native/transform.cpp", - "native/validation.cpp", "native/quant_param.cpp", - "native/nnbackend.cpp", - "native/nncompiler.cpp", - "native/nncompiled_cache.cpp", "native/register_hdi_device_v1_0.cpp", "native/register_hdi_device_v2_0.cpp", + "native/transform.cpp", + "native/validation.cpp", ] ops_sources = [ @@ -143,12 +143,12 @@ ohos_shared_library("libneural_network_runtime") { } nnrt_core_sources = [ + "native/backend_manager.cpp", + "native/backend_registrar.cpp", "native/neural_network_core.cpp", "native/tensor_desc.cpp", - "native/validation.cpp", - "native/backend_registrar.cpp", - "native/backend_manager.cpp", "native/utils.cpp", + "native/validation.cpp", ] ohos_shared_library("libneural_network_core") { @@ -156,8 +156,8 @@ ohos_shared_library("libneural_network_core") { output_extension = "so" include_dirs = [ "..", - "//third_party/mindspore/mindspore-src/source/mindspore/lite/mindir/include", "../../third_party/bounds_checking_function/include", + "//third_party/mindspore/mindspore-src/source/mindspore/lite/mindir/include", ] install_images = [ -- Gitee From 122e933c20e9f7fac32b730e51ce55217fba1bbc Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 13 Dec 2023 16:15:24 +0800 Subject: [PATCH 10/11] buildgn format fix Signed-off-by: wangchuanxia --- frameworks/BUILD.gn | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index e931ef2..fee1f2a 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -28,8 +28,8 @@ nnrt_sources = [ "native/hdi_prepared_model_v2_0.cpp", "native/inner_model.cpp", "native/memory_manager.cpp", - "native/neural_network_runtime_compat.cpp", "native/neural_network_runtime.cpp", + "native/neural_network_runtime_compat.cpp", "native/nn_tensor.cpp", "native/nnbackend.cpp", "native/nncompiled_cache.cpp", @@ -133,9 +133,7 @@ ohos_shared_library("libneural_network_runtime") { "mindspore:mindir", ] - deps = [ - ":libneural_network_core" - ] + deps = [ ":libneural_network_core" ] subsystem_name = "ai" innerapi_tags = [ "ndk" ] @@ -156,7 +154,6 @@ ohos_shared_library("libneural_network_core") { output_extension = "so" include_dirs = [ "..", - "../../third_party/bounds_checking_function/include", "//third_party/mindspore/mindspore-src/source/mindspore/lite/mindir/include", ] @@ -177,5 +174,4 @@ ohos_shared_library("libneural_network_core") { subsystem_name = "ai" innerapi_tags = [ "ndk" ] part_name = "neural_network_runtime" -} - +} \ No newline at end of file -- Gitee From 4322e09c40f1d7b36ccc245faaf99cc2f589f564 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 13 Dec 2023 16:30:35 +0800 Subject: [PATCH 11/11] buildgn format fix Signed-off-by: wangchuanxia --- frameworks/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index fee1f2a..66c57fb 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -174,4 +174,4 @@ ohos_shared_library("libneural_network_core") { subsystem_name = "ai" innerapi_tags = [ "ndk" ] part_name = "neural_network_runtime" -} \ No newline at end of file +} -- Gitee