From 9144446d67a4e7090eacc9d4b971122a0051b4d5 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 4 Dec 2023 13:48:21 +0800 Subject: [PATCH 01/51] v2 1204 --- interfaces/kits/c/neural_network_core.h | 732 ++++++++++++++++++ interfaces/kits/c/neural_network_runtime.h | 527 +------------ .../kits/c/neural_network_runtime_compat.h | 276 +++++++ .../kits/c/neural_network_runtime_type.h | 10 + 4 files changed, 1046 insertions(+), 499 deletions(-) create mode 100644 interfaces/kits/c/neural_network_core.h create mode 100644 interfaces/kits/c/neural_network_runtime_compat.h diff --git a/interfaces/kits/c/neural_network_core.h b/interfaces/kits/c/neural_network_core.h new file mode 100644 index 0000000..ec8bc18 --- /dev/null +++ b/interfaces/kits/c/neural_network_core.h @@ -0,0 +1,732 @@ +/* + * 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_core.h + * + * @brief Defines the Neural Network Runtime APIs. The AI inference framework uses the Native APIs provided by Neural Network Runtime + * to compile models and perform inference and computing on acceleration hardware. + * 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_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} 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 2.0 + */ +OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model); + +OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *modelPath); + +OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *modelBuffer, size_t modelSize); + +OH_NNCompilation *OH_NNCompilation_ConstructForCache(); + +OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t length, + size_t *modelSize); + +OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compilation, + const void *buffer, + size_t modelSize); + +OH_NN_ReturnCode OH_NNCompilation_SetExtensionConfigs(OH_NNCompilation *compilation, + const char **configNames, + const void **configValues, + const size_t *configValueSizes, + size_t configNum); + +/** + * @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 2.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 2.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 2.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 2.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 2.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 2.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 2.0 + */ +void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); + + +/** + * @brief Creates an instance of the {@link NN_TensorDesc} type. + * + * This method creates an instance of the {@link NN_TensorDesc} type to describe various tensor information, + * including name/data type/shape/format, etc. \n + * + * The following methods can be called to create a tensor instance based on the passed {@link NN_TensorDesc} instance: + * - {@link OH_NNTensor_Create} + * - {@link OH_NNTensor_CreateWithSize} + * - {@link OH_NNTensor_CreateWithFd} \n + * + * @return Returns the pointer to a {@link NN_TensorDesc} instance + * @since 11 + * @version 1.0 + */ +NN_TensorDesc *OH_NNTensorDesc_Create(); + +/** + * @brief Releases an instance of the {@link NN_TensorDesc} type. + * + * After the {@link NN_TensorDesc} instance is created, this method needs to be called to release the instance. + * After creating a tensor and passing the {@link NN_TensorDesc} instance to the tensor, + * the {@link NN_TensorDesc} memory will be released at the same time as the {@link OH_NNTensor_Destroy} call, + * and you do not need to call this method to release the {@link NN_TensorDesc} memory. Otherwise, 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 logic. \n + * + * @param tensorDesc Level-2 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 Set name of a tensorDesc. + * + * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor name. \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 Get name of a tensorDesc. + * + * Call this method to obtain the name of the specified {@link NN_TensorDesc} instance. \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. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param name Return the 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 Set data type of a 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 Get data type of a 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 Return the 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 Set shape of a 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 shapeNum The size 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 shapeNum); + +/** + * @brief Get shape of a 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. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param shape Return the shape list of the tensor. + * @param shapeNum Return the size 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* shapeNum); + +/** + * @brief Set format of a 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 Get format of a 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 Return the 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 Get element number of a tensorDesc. + * + * Call this method to obtain the element number of the specified {@link NN_TensorDesc} instance. + * If you need to obtain byte size of the tensor data, you can call the {@link OH_NNTensorDesc_GetByteSize} method to obtain it. \n + * + * if tensorDesc or elementNum is a null pointer, this method will return error code. \n + * + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. + * @param elementNum Return the element number 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_GetElementNum(const NN_TensorDesc* tensorDesc, size_t* elementNum); + +/** + * @brief Get byte size of a tensorDesc. + * + * Call this method to obtain the byte size of the specified {@link NN_TensorDesc} instance. + * If you need to obtain element number of the tensor data, you can call the {@link OH_NNTensorDesc_GetElementNum} method to obtain it. \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 Return the 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 an instance of the {@link NN_Tensor} type. + * + * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is calculated by {@link OH_NNTensorDesc_GetByteSize} is allocated. + * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. + * desc 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 created by this method. desc will also be released. \n + * + * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @return Returns the pointer to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_Create(const char* deviceName, NN_TensorDesc* desc); + +/** + * @brief Creates an instance of the {@link NN_Tensor} type. + * + * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is specified by size is allocated. + * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. + * desc 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 created by this method. desc will also be released. \n + * + * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @param size Size of tensor data that need to be allocated. + * @return Returns the pointer to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_CreateWithSize(const char* deviceName, NN_TensorDesc* desc, size_t size); + +/** + * @brief Creates an instance of the {@link NN_Tensor} type. + * + * This method creates an instance of the {@link NN_Tensor} type. This method reuses the memory corresponding to the fd passed by the user. + * When you call the {@link OH_NNTensor_DestroyTensor} method to release the tensor created by this method, the data memory is not released. \n + * + * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. + * desc must be provided, if it is a null pointer, the method returns an error code. + * fd, size and offset come from another {@link NN_Tensor} instance. (size - offset) must be greater than or + * equal to the byte size obtained by the {@link OH_NNTensorDesc_GetByteSize} in desc. \n + * + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance created by this method. desc will also be released. \n + * + * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @param fd Fd comes from another {@link NN_Tensor} instance. + * @param size Size comes from another {@link NN_Tensor} instance. + * @param offset Offset comes from another {@link NN_Tensor} instance. + * @return Returns the pointer to a {@link NN_Tensor} instance. + * @since 11 + * @version 1.0 + */ +NN_Tensor* OH_NNTensor_CreateWithFd(const char* deviceName, + NN_TensorDesc* desc, + int fd, + size_t size, + size_t offset); + +/** + * @brief Releases an instance of the {@link NN_Tensor} type. + * + * After the {@link NN_Tensor} instance is created, this method needs to be called to release the instance. Otherwise, memory leak will occur. + * The {@link NN_TensorDesc} memory will be released at the same time as the {@link OH_NNTensor_DestroyTensor} call, + * and you do not need to call {@link OH_NNTensorDesc_Destroy} to release the {@link NN_TensorDesc} memory. \n + * + * If tensor or *tensor is a null pointer, this method will return error code and does not execute the release logic. \n + * + * @param tensorDesc Level-2 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 Get {@link NN_TensorDesc} instance of a tensor. + * + * Call this method to obtain the {@link NN_TensorDesc} instance of the specified {@link NN_Tensor} instance. + * You can get various tensor information such as name/format/data type/shape from the {@link NN_TensorDesc} instance. \n + * + * if tensor is a null pointer, this method will return null pointer. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @return Returns the 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 Get the data buffer of a tensor. + * + * Call this method to obtain the data buffer of the specified {@link NN_Tensor} instance. \n + * + * if tensor is a null pointer, this method will return null pointer. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @return Returns the 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 Get the data size of a tensor. + * + * Call this method to obtain the data size of the specified {@link NN_Tensor} instance. \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 Returns the 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 Get the data fd of a tensor. + * + * Call this method to obtain the data fd of the specified {@link NN_Tensor} instance. \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 Returns the 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. + * + * Call this method to obtain the data offset of the specified {@link NN_Tensor} instance. \n + * + * if tensor or offset is a null pointer, this method will return error code. \n + * + * @param tensor Pointer to the {@link NN_Tensor} instance. + * @param offset Returns the 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. 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 2.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 + * + * @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 2.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, + * 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 2.0 + */ +void OH_NNExecutor_Destroy(OH_NNExecutor **executor); + +OH_NN_ReturnCode OH_NNExecutor_GetInputNum(const OH_NNExecutor *executor, size_t *inputNum); + +OH_NN_ReturnCode OH_NNExecutor_GetOutputNum(const OH_NNExecutor *executor, size_t *outputNum); + +NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor, size_t index); + +NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index; + +// todo +NN_TensorDesc* OH_NNExecutor_GetInputDimRanges(const OH_NNExecutor *executor, size_t **minInputDims, size_t **maxInputDims); + +OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); + +OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor, NN_OnServiceDied onServiceDied); + +OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, + NN_Tensor *inputTensor[], + size_t inputNum, + NN_Tensor *outputTensor[], + size_t outputNum); + +OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, + NN_Tensor *inputTensor[], + size_t inputNum, + NN_Tensor *outputTensor[], + size_t outputNum, + int32_t timeout, + void* userData); + + +/** + * @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 2.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 2.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 2.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.h b/interfaces/kits/c/neural_network_runtime.h index b7740e1..f7a7614 100644 --- a/interfaces/kits/c/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime.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 @@ -21,30 +21,42 @@ * * @Syscap SystemCapability.Ai.NeuralNetworkRuntime * @since 9 - * @version 1.0 + * @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 and compile models and perform inference and computing on acceleration hardware. + * to coonstruct models. * Note: Currently, the APIs of Neural Network Runtime do not support multi-thread calling. \n * * @library libneural_network_runtime.so * @since 9 - * @version 1.0 + * @version 2.0 */ #ifndef NEURAL_NETWORK_RUNTIME_H #define NEURAL_NETWORK_RUNTIME_H #include "neural_network_runtime_type.h" +#include "neural_network_core.h" #ifdef __cplusplus extern "C" { #endif +NN_QuantParam *OH_NNQuantParam_Create(); + +OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam *quantParams, const double *scales, size_t quantNum); + +OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam *quantParams, const int32_t *zeroPoints, size_t quantNum); + +OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam *quantParams, const uint32_t *numBits, size_t quantNum); + +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. * @@ -57,30 +69,11 @@ extern "C" { * * @return Returns the pointer to a {@link OH_NNModel} instance. * @since 9 - * @version 1.0 + * @version 2.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. - * 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. - * 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. - * @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_AddTensor(OH_NNModel *model, const OH_NN_Tensor *tensor); +OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel *model, const NN_TensorDesc *tensorDesc); /** * @brief Sets the tensor value. @@ -96,10 +89,14 @@ OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *ten * @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 + * @version 2.0 */ OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, const void *dataBuffer, size_t length); +OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel *model, uint32_t index, NN_QuantParam *quantParam); + +OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_NN_TensorType *tensorType); + /** * @brief Adds an operator to a model instance. * @@ -125,7 +122,7 @@ OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, con * @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 + * @version 2.0 */ OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, OH_NN_OperationType op, @@ -150,7 +147,7 @@ OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, * @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 + * @version 2.0 */ OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, const OH_NN_UInt32Array *inputIndices, @@ -171,7 +168,7 @@ OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, * @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 + * @version 2.0 */ OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); @@ -184,7 +181,7 @@ OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); * * @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 + * @version 2.0 */ void OH_NNModel_Destroy(OH_NNModel **model); @@ -208,481 +205,13 @@ void OH_NNModel_Destroy(OH_NNModel **model); * @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 + * @version 2.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, - * 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. - * - * - 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]. - * 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. - * 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, - * 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_SetInput(OH_NNExecutor *executor, - uint32_t inputIndex, - const OH_NN_Tensor *tensor, - const void *dataBuffer, - size_t length); - -/** - * @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. - * 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 - * 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. - * - 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} - * 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, - * 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_SetOutput(OH_NNExecutor *executor, - uint32_t outputIndex, - 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, - * 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_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 - * 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. - * 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. - * @since 9 - * @version 1.0 - */ -OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, size_t length); - -/** - * @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 - * 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. - * 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. - * @since 9 - * @version 1.0 - */ -OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, size_t length); - -/** - * @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. - * 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. - * 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. - * @since 9 - * @version 1.0 - */ -void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, OH_NN_Memory **memory); - -/** - * @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. - * 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. - * 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. - * @since 9 - * @version 1.0 - */ -void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, OH_NN_Memory **memory); - -/** - * @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. - * 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. - * 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}. - * @since 9 - * @version 1.0 - */ -OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, - uint32_t inputIndex, - const OH_NN_Tensor *tensor, - const OH_NN_Memory *memory); - -/** - * @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. - * 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. - * 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, - * 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_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 diff --git a/interfaces/kits/c/neural_network_runtime_compat.h b/interfaces/kits/c/neural_network_runtime_compat.h new file mode 100644 index 0000000..efdf0ef --- /dev/null +++ b/interfaces/kits/c/neural_network_runtime_compat.h @@ -0,0 +1,276 @@ +/* + * 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 1.0 + */ + +/** + * @file neural_network_runtime_compat.h + * + * @brief The APIs defined in this document are all compatible interfaces of the previous version, which will be deprecated after five versions, + * and 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 + * @version 1.0 + */ + +#ifndef NEURAL_NETWORK_RUNTIME_COMPAT_H +#define NEURAL_NETWORK_RUNTIME_COMPAT_H + +#include "neural_network_runtime_type.h" +#include "neural_network_core.h" +#include "neural_network_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// todo 增加废弃标志,在使用这些接口时进行告警提示(注释,log等) + +/** + * @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. + * 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. + * 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. + * @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_AddTensor(OH_NNModel *model, const OH_NN_Tensor *tensor); + +/** + * @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, + * 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. + * + * - 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]. + * 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. + * 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, + * 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_SetInput(OH_NNExecutor *executor, + uint32_t inputIndex, + const OH_NN_Tensor *tensor, + const void *dataBuffer, + size_t length); + +/** + * @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. + * 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 + * 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. + * - 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} + * 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, + * 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_SetOutput(OH_NNExecutor *executor, + uint32_t outputIndex, + void *dataBuffer, + size_t length); + +/** + * @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, + * 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_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 + * 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. + * 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. + * @since 9 + * @version 1.0 + */ +OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, size_t length); + +/** + * @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 + * 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. + * 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. + * @since 9 + * @version 1.0 + */ +OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, size_t length); + +/** + * @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. + * 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. + * 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. + * @since 9 + * @version 1.0 + */ +void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputIndex, OH_NN_Memory **memory); + +/** + * @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. + * 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. + * 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. + * @since 9 + * @version 1.0 + */ +void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputIndex, OH_NN_Memory **memory); + +/** + * @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. + * 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. + * 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}. + * @since 9 + * @version 1.0 + */ +OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, + uint32_t inputIndex, + const OH_NN_Tensor *tensor, + const OH_NN_Memory *memory); + +/** + * @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. + * 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. + * 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, + * 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_SetOutputWithMemory(OH_NNExecutor *executor, + uint32_t outputIndex, + const OH_NN_Memory *memory); + +#ifdef __cplusplus +} +#endif // __cplusplus + +/** @} */ +#endif // NEURAL_NETWORK_RUNTIME_COMPAT_H diff --git a/interfaces/kits/c/neural_network_runtime_type.h b/interfaces/kits/c/neural_network_runtime_type.h index 00aefb6..7aadb48 100644 --- a/interfaces/kits/c/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime_type.h @@ -68,6 +68,12 @@ typedef struct OH_NNCompilation OH_NNCompilation; */ typedef struct OH_NNExecutor OH_NNExecutor; +typedef struct NN_QuantParam NN_QuantParam; + +typedef struct NN_TensorDesc NN_TensorDesc; + +typedef struct NN_Tensor NN_Tensor; + /** * @brief Defines the hardware performance mode. * @@ -131,6 +137,10 @@ typedef enum { OH_NN_INVALID_PATH = 8 } OH_NN_ReturnCode; +typedef void (*NN_OnRunDone)(void*, OH_NN_ReturnCode, void* [], int32_t); + +typedef void (*NN_OnServiceDied)(void*); + /** * @brief Defines activation function types in the fusion operator for Neural Network Runtime. * -- Gitee From 4e998c0b1493611e61619fee2bc06fe85348a191 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 4 Dec 2023 15:21:52 +0800 Subject: [PATCH 02/51] v2-1204 --- interfaces/kits/c/neural_network_core.h | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/interfaces/kits/c/neural_network_core.h b/interfaces/kits/c/neural_network_core.h index ec8bc18..a9312f6 100644 --- a/interfaces/kits/c/neural_network_core.h +++ b/interfaces/kits/c/neural_network_core.h @@ -84,11 +84,10 @@ OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compil const void *buffer, size_t modelSize); -OH_NN_ReturnCode OH_NNCompilation_SetExtensionConfigs(OH_NNCompilation *compilation, - const char **configNames, - const void **configValues, - const size_t *configValueSizes, - size_t configNum); +OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, + const char *configNames, + const void *configValues, + const size_t configValueSizes); /** * @brief Specifies the device for model compilation and computing. @@ -446,7 +445,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc* tensorDesc, si * @since 11 * @version 1.0 */ -NN_Tensor* OH_NNTensor_Create(const char* deviceName, NN_TensorDesc* desc); +NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc* desc); /** * @brief Creates an instance of the {@link NN_Tensor} type. @@ -464,7 +463,7 @@ NN_Tensor* OH_NNTensor_Create(const char* deviceName, NN_TensorDesc* desc); * @since 11 * @version 1.0 */ -NN_Tensor* OH_NNTensor_CreateWithSize(const char* deviceName, NN_TensorDesc* desc, size_t size); +NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc* desc, size_t size); /** * @brief Creates an instance of the {@link NN_Tensor} type. @@ -488,7 +487,7 @@ NN_Tensor* OH_NNTensor_CreateWithSize(const char* deviceName, NN_TensorDesc* des * @since 11 * @version 1.0 */ -NN_Tensor* OH_NNTensor_CreateWithFd(const char* deviceName, +NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, NN_TensorDesc* desc, int fd, size_t size, @@ -584,7 +583,7 @@ OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor* tensor, int* fd); * @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 + * @version 1.0@ */ OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor* tensor, size_t* offset); @@ -649,10 +648,13 @@ OH_NN_ReturnCode OH_NNExecutor_GetOutputNum(const OH_NNExecutor *executor, size_ NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor, size_t index); -NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index; +NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index); -// todo -NN_TensorDesc* OH_NNExecutor_GetInputDimRanges(const OH_NNExecutor *executor, size_t **minInputDims, size_t **maxInputDims); +NN_TensorDesc* OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, + size_t index, + size_t *minInputDims, + size_t *maxInputDims, + size_t *shapeNum); OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); -- Gitee From 36ee1a4deae184b44b2951f02fd261bd42e693e0 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 4 Dec 2023 16:00:44 +0800 Subject: [PATCH 03/51] v2-1204 --- interfaces/kits/c/neural_network_runtime.h | 2 +- testdemo/CMakeLists.txt | 17 ++ testdemo/demo.cpp | 326 +++++++++++++++++++++ 3 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 testdemo/CMakeLists.txt create mode 100644 testdemo/demo.cpp diff --git a/interfaces/kits/c/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime.h index f7a7614..ee0de32 100644 --- a/interfaces/kits/c/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime.h @@ -95,7 +95,7 @@ OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, con OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel *model, uint32_t index, NN_QuantParam *quantParam); -OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_NN_TensorType *tensorType); +OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_NN_TensorType tensorType); /** * @brief Adds an operator to a model instance. diff --git a/testdemo/CMakeLists.txt b/testdemo/CMakeLists.txt new file mode 100644 index 0000000..87d8fbb --- /dev/null +++ b/testdemo/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.0.0) +project(testdemo) + +list(APPEND OHOS_C_COMPILER_FLAGS -march=armv7a) + +add_executable(testdemo demo.cpp) +target_include_directories(testdemo PUBLIC + ../interfaces/kits/c) + +target_link_directories(testdemo PUBLIC /home/wcx/wcx/ohos1104/out/rk3568/ai/neural_network_runtime/) +target_link_libraries(testdemo PUBLIC + hilog_ndk.z.so + libneural_network_core.so + libneural_network_runtime.so) + +set(CMAKE_EXE_LINKER_FLAGS "${cmake_exe_linker_flags} -Wl,--allow-shlib-undefined") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7a") \ No newline at end of file diff --git a/testdemo/demo.cpp b/testdemo/demo.cpp new file mode 100644 index 0000000..1d72e87 --- /dev/null +++ b/testdemo/demo.cpp @@ -0,0 +1,326 @@ +#include "../interfaces/kits/c/neural_network_runtime.h" +#include + +#include +#include "hilog/log.h" + +#define LOG_DOMAIN 0xD002101 +#define LOG_TAG "NNRt" +#define LOGD(...) OH_LOG_DEBUG(LOG_APP, __VA_ARGS__) +#define LOGI(...) OH_LOG_INFO(LOG_APP, __VA_ARGS__) +#define LOGW(...) OH_LOG_WARN(LOG_APP, __VA_ARGS__) +#define LOGE(...) OH_LOG_ERROR(LOG_APP, __VA_ARGS__) +#define LOGF(...) OH_LOG_FATAL(LOG_APP, __VA_ARGS__) + +#define CHECKNEQ(realRet, expectRet, retValue, ...) \ + do { \ + if ((realRet) != (expectRet)) { \ + printf(__VA_ARGS__); \ + return (retValue); \ + } \ + } while (0) + +#define CHECKEQ(realRet, expectRet, retValue, ...) \ + do { \ + if ((realRet) == (expectRet)) { \ + printf(__VA_ARGS__); \ + return (retValue); \ + } \ + } while (0) + +OH_NN_ReturnCode SetInputData(NN_Tensor* inputTensor[], size_t inputSize) +{ + OH_NN_DataType dataType(OH_NN_FLOAT32); + OH_NN_ReturnCode ret{OH_NN_FAILED}; + size_t elementNum = 0; + for (size_t i = 0; i < inputSize; ++i) { + auto data = OH_NNTensor_GetDataBuffer(inputTensor[i]); + CHECKEQ(data, nullptr, OH_NN_FAILED, "Failed to get data buffer"); + auto desc = OH_NNTensor_GetTensorDesc(inputTensor[i]); + CHECKEQ(desc, nullptr, OH_NN_FAILED, "Failed to get desc"); + ret = OH_NNTensorDesc_GetDataType(desc, &dataType); + CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get data type"); + ret = OH_NNTensorDesc_GetElementNum(desc, &elementNum); + CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get element num"); + switch(dataType) { + case OH_NN_FLOAT32: { + float* floatValue = reinterpret_cast(data); + for (size_t j = 0; j < elementNum; ++j) { + floatValue[j] = static_cast(j); + } + break; + } + case OH_NN_INT32: { + int* intValue = reinterpret_cast(data); + for (size_t j = 0; j < elementNum; ++j) { + intValue[j] = static_cast(j); + } + break; + } + default: + return OH_NN_FAILED; + } + } + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode Print(NN_Tensor* outputTensor[], size_t outputSize) +{ + OH_NN_DataType dataType(OH_NN_FLOAT32); + OH_NN_ReturnCode ret{OH_NN_FAILED}; + size_t elementNum = 0; + for (size_t i = 0; i < outputSize; ++i) { + auto data = OH_NNTensor_GetDataBuffer(outputTensor[i]); + CHECKEQ(data, nullptr, OH_NN_FAILED, "Failed to get data buffer"); + auto desc = OH_NNTensor_GetTensorDesc(outputTensor[i]); + CHECKEQ(desc, nullptr, OH_NN_FAILED, "Failed to get desc"); + ret = OH_NNTensorDesc_GetDataType(desc, &dataType); + CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get data type"); + ret = OH_NNTensorDesc_GetElementNum(desc, &elementNum); + CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get element num"); + printf("elementnum:%zu: ", elementNum); + switch(dataType) { + case OH_NN_FLOAT32: { + float* floatValue = reinterpret_cast(data); + for (size_t j = 0; j < std::min((size_t)10, elementNum); ++j) { + printf("%f ", floatValue[j]); + } + break; + } + case OH_NN_INT32: { + int* intValue = reinterpret_cast(data); + for (size_t j = 0; j < std::min((size_t)10, elementNum); ++j) { + printf("%d ", intValue[j]); + } + break; + } + default: + return OH_NN_FAILED; + } + printf("\n"); + } + printf("\n"); + + return OH_NN_SUCCESS; +} + +int main(int argc, char** argv) { + // 查询当前已经对接的设备列表 + // 1. 先查询deviceID列表 + const size_t *allDevicesID = nullptr; + uint32_t deviceCount = 0; + OH_NN_ReturnCode returnCode = OH_NNDevice_GetAllDevicesID(&allDevicesID, &deviceCount); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNDevice_GetAllDevicesID failed."); + // 2. 遍历deviceID + const char *name = nullptr; + size_t deviceID = 0; + for(size_t i = 0; i < deviceCount; ++i) { + returnCode = OH_NNDevice_GetName(allDevicesID[i], &name); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNDevice_GetName failed."); + deviceID = allDevicesID[i]; + } + printf("backendName:%s\n", name); + + // 创建模型实例,进行模型构造 + OH_NNModel* model = OH_NNModel_Construct(); + CHECKEQ(model, nullptr, -1, "Create model failed."); + + // 添加Add算子的第一个输入Tensor,类型为float32,张量形状为[1, 2, 2, 3] + NN_TensorDesc* tensorDesc = OH_NNTensorDesc_Create(); + CHECKEQ(tensorDesc, nullptr, -1, "Create TensorDesc failed."); + + int32_t inputDims[4] = {1, 2, 2, 3}; + returnCode = OH_NNTensorDesc_SetShape(tensorDesc, inputDims, 4); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc shape failed."); + + returnCode = OH_NNTensorDesc_SetDataType(tensorDesc, OH_NN_FLOAT32); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc data type failed."); + + returnCode = OH_NNTensorDesc_SetFormat(tensorDesc, OH_NN_FORMAT_NONE); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc format failed."); + + returnCode = OH_NNModel_AddTensorToModel(model, tensorDesc); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Add first TensorDesc to model failed."); + + returnCode = OH_NNModel_SetTensorType(model, 0, OH_NN_TENSOR); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set model tensor type failed."); + + // 添加Add算子的第二个输入Tensor,类型为float32,张量形状为[1, 2, 2, 3] + tensorDesc = OH_NNTensorDesc_Create(); + CHECKEQ(tensorDesc, nullptr, -1, "Create TensorDesc failed."); + + returnCode = OH_NNTensorDesc_SetShape(tensorDesc, inputDims, 4); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc shape failed."); + + returnCode = OH_NNTensorDesc_SetDataType(tensorDesc, OH_NN_FLOAT32); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc data type failed."); + + returnCode = OH_NNTensorDesc_SetFormat(tensorDesc, OH_NN_FORMAT_NONE); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc format failed."); + + returnCode = OH_NNModel_AddTensorToModel(model, tensorDesc); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Add second TensorDesc to model failed."); + + returnCode = OH_NNModel_SetTensorType(model, 1, OH_NN_TENSOR); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set model tensor type failed."); + + // 添加Add算子的参数Tensor,该参数Tensor用于指定激活函数的类型,Tensor的数据类型为int8。 + tensorDesc = OH_NNTensorDesc_Create(); + CHECKEQ(tensorDesc, nullptr, -1, "Create TensorDesc failed."); + + int32_t activationDims = 1; + returnCode = OH_NNTensorDesc_SetShape(tensorDesc, &activationDims, 1); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc shape failed."); + + returnCode = OH_NNTensorDesc_SetDataType(tensorDesc, OH_NN_INT8); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc data type failed."); + + returnCode = OH_NNTensorDesc_SetFormat(tensorDesc, OH_NN_FORMAT_NONE); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc format failed."); + + returnCode = OH_NNModel_AddTensorToModel(model, tensorDesc); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Add second TensorDesc to model failed."); + + returnCode = OH_NNModel_SetTensorType(model, 2, OH_NN_ADD_ACTIVATIONTYPE); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set model tensor type failed."); + + // 将激活函数类型设置为OH_NNBACKEND_FUSED_NONE,表示该算子不添加激活函数。 + int8_t activationValue = OH_NN_FUSED_NONE; + returnCode = OH_NNModel_SetTensorData(model, 2, &activationValue, sizeof(int8_t)); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set model tensor data failed."); + + // 设置Add算子的输出,类型为float32,张量形状为[1, 2, 2, 3] + tensorDesc = OH_NNTensorDesc_Create(); + CHECKEQ(tensorDesc, nullptr, -1, "Create TensorDesc failed."); + + returnCode = OH_NNTensorDesc_SetShape(tensorDesc, inputDims, 4); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc shape failed."); + + returnCode = OH_NNTensorDesc_SetDataType(tensorDesc, OH_NN_FLOAT32); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc data type failed."); + + returnCode = OH_NNTensorDesc_SetFormat(tensorDesc, OH_NN_FORMAT_NONE); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set TensorDesc format failed."); + + returnCode = OH_NNModel_AddTensorToModel(model, tensorDesc); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Add forth TensorDesc to model failed."); + + returnCode = OH_NNModel_SetTensorType(model, 3, OH_NN_TENSOR); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Set model tensor type failed."); + + // 指定Add算子的输入、参数和输出索引 + uint32_t inputIndicesValues[2] = {0, 1}; + uint32_t paramIndicesValues = 2; + uint32_t outputIndicesValues = 3; + OH_NN_UInt32Array paramIndices = {¶mIndicesValues, 1 * 4}; + OH_NN_UInt32Array inputIndices = {inputIndicesValues, 2 * 4}; + OH_NN_UInt32Array outputIndices = {&outputIndicesValues, 1 * 4}; + + // 向模型实例添加Add算子 + returnCode = OH_NNModel_AddOperation(model, OH_NN_OPS_ADD, ¶mIndices, &inputIndices, &outputIndices); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Add operation to model failed."); + + // 设置模型实例的输入、输出索引 + returnCode = OH_NNModel_SpecifyInputsAndOutputs(model, &inputIndices, &outputIndices); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Specify model inputs and outputs failed."); + + // 完成模型实例的构建 + returnCode = OH_NNModel_Finish(model); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "Build model failed."); + + // 创建compilation,将构图的model或MSLite传下来的model传入 + OH_NNCompilation* compilation = OH_NNCompilation_Construct(model); + CHECKEQ(compilation, nullptr, -1, "OH_NNCore_ConstructCompilationWithNNModel failed."); + + returnCode = OH_NNCompilation_SetDevice(compilation, deviceID); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetDevice failed."); + + returnCode = OH_NNCompilation_SetCache(compilation, argv[2], 1); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetCache failed."); + + returnCode = OH_NNCompilation_SetPerformanceMode(compilation, OH_NN_PERFORMANCE_EXTREME); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetPerformanceMode failed."); + + returnCode = OH_NNCompilation_SetPriority(compilation, OH_NN_PRIORITY_HIGH); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetPriority failed."); + + returnCode = OH_NNCompilation_EnableFloat16(compilation, false); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_EnableFloat16 failed."); + + // 执行编译 + returnCode = OH_NNCompilation_Build(compilation); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_Build failed."); + + // 销毁model + OH_NNModel_Destroy(&model); + + // 用compilation创建executor + OH_NNExecutor *executor = OH_NNExecutor_Construct(compilation); + CHECKEQ(executor, nullptr, -1, "OH_NNExecutor_Construct failed."); + + // 销毁compilation + OH_NNCompilation_Destroy(&compilation); + + // 从executor获取输入输出信息 + size_t inputCount = 0; + returnCode = OH_NNExecutor_GetInputNum(executor, &inputCount); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNExecutor_GetInputNum failed."); + std::vector inputTensorDescs; + NN_TensorDesc* tensorDescTmp = nullptr; + for (size_t i = 0; i < inputCount; ++i) { + tensorDescTmp = OH_NNExecutor_CreateInputTensorDesc(executor, i); + CHECKEQ(tensorDescTmp, nullptr, -1, "OH_NNExecutor_CreateInputTensorDesc failed."); + inputTensorDescs.emplace_back(tensorDescTmp); + } + size_t outputCount = 0; + returnCode = OH_NNExecutor_GetOutputNum(executor, &outputCount); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNExecutor_GetOutputNum failed."); + std::vector outputTensorDescs; + for (size_t i = 0; i < outputCount; ++i) { + tensorDescTmp = OH_NNExecutor_CreateOutputTensorDesc(executor, i); + CHECKEQ(tensorDescTmp, nullptr, -1, "OH_NNExecutor_CreateOutputTensorDesc failed."); + outputTensorDescs.emplace_back(tensorDescTmp); + } + + // 创建输入输出Tensor + NN_Tensor* inputTensors[inputCount]; + NN_Tensor* tensor = nullptr; + for (size_t i = 0; i < inputCount; ++i) { + tensor = nullptr; + tensor = OH_NNTensor_Create(deviceID, inputTensorDescs[i]); + CHECKEQ(tensor, nullptr, -1, "OH_NNTensor_Create failed."); + inputTensors[i] = tensor; + } + NN_Tensor* outputTensors[outputCount]; + for (size_t i = 0; i < outputCount; ++i) { + tensor = nullptr; + tensor = OH_NNTensor_Create(deviceID, outputTensorDescs[i]); + CHECKEQ(tensor, nullptr, -1, "OH_NNTensor_Create failed."); + outputTensors[i] = tensor; + } + // 设置输入元素值 + returnCode = SetInputData(inputTensors, inputCount); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "SetInputData failed."); + // 执行run + returnCode = OH_NNExecutor_RunSync(executor, inputTensors, inputCount, outputTensors, outputCount); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNExecutor_RunSync failed."); + // 打印输出 + printf("inputs:\n"); + Print(inputTensors, inputCount); + printf("\n"); + printf("outputs:\n"); + Print(outputTensors, outputCount); + // 清理输入输出Tensor + for (size_t i = 0; i < inputCount; ++i) { + returnCode = OH_NNTensor_Destroy(&inputTensors[i]); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNTensor_Destroy failed."); + } + for (size_t i = 0; i < outputCount; ++i) { + returnCode = OH_NNTensor_Destroy(&outputTensors[i]); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNTensor_Destroy failed."); + } + // 销毁Executor + OH_NNExecutor_Destroy(&executor); + + return 0; +} \ No newline at end of file -- Gitee From 6235435a4bb8ab6fe1d685691266e62966be2468 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Tue, 5 Dec 2023 09:47:29 +0800 Subject: [PATCH 04/51] v2-1205 --- BUILD.gn | 5 +- frameworks/BUILD.gn | 70 +- frameworks/native/compilation.cpp | 845 ------------------ frameworks/native/compilation.h | 92 -- frameworks/native/device.h | 4 +- frameworks/native/execution_plan.cpp | 94 -- frameworks/native/executor.cpp | 621 ------------- frameworks/native/executor.h | 86 +- frameworks/native/hdi_device_v1_0.cpp | 2 +- frameworks/native/hdi_device_v1_0.h | 2 +- frameworks/native/hdi_device_v2_0.cpp | 2 +- frameworks/native/hdi_device_v2_0.h | 2 +- frameworks/native/memory_manager.cpp | 102 --- frameworks/native/neural_network_core.cpp | 689 ++++++++++++++ frameworks/native/neural_network_runtime.cpp | 733 --------------- frameworks/native/nn_tensor.h | 2 +- frameworks/native/nnexecutor.cpp | 250 ++++++ frameworks/native/nnexecutor.h | 73 ++ frameworks/native/nntensor.cpp | 313 +++++++ 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 + .../ops_validation.cpp} | 51 +- frameworks/native/ops/ops_validation.h | 29 + frameworks/native/ops/pooling_builder.cpp | 1 + frameworks/native/tensor.h | 43 + frameworks/native/tensor_desc.cpp | 200 +++++ .../{execution_plan.h => tensor_desc.h} | 53 +- frameworks/native/transform.cpp | 1 - frameworks/native/validation.cpp | 10 - frameworks/native/validation.h | 3 +- interfaces/kits/c/neural_network_core.h | 70 +- interfaces/kits/c/neural_network_runtime.h | 2 +- 34 files changed, 1842 insertions(+), 2672 deletions(-) delete mode 100644 frameworks/native/compilation.cpp delete mode 100644 frameworks/native/compilation.h delete mode 100644 frameworks/native/execution_plan.cpp delete mode 100644 frameworks/native/executor.cpp delete mode 100644 frameworks/native/memory_manager.cpp create mode 100644 frameworks/native/neural_network_core.cpp delete mode 100644 frameworks/native/neural_network_runtime.cpp create mode 100644 frameworks/native/nnexecutor.cpp create mode 100644 frameworks/native/nnexecutor.h create mode 100644 frameworks/native/nntensor.cpp create mode 100644 frameworks/native/nntensor.h rename frameworks/native/{memory_manager.h => ops/ops_validation.cpp} (41%) create mode 100644 frameworks/native/ops/ops_validation.h create mode 100644 frameworks/native/tensor.h create mode 100644 frameworks/native/tensor_desc.cpp rename frameworks/native/{execution_plan.h => tensor_desc.h} (38%) 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..598f052 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.cpp", + #"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.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/validation.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,44 @@ 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", +] + +ohos_shared_library("libneural_network_core") { + sources = nnrt_core_sources + output_extension = "so" + include_dirs = [ + ".." + ] + + 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/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 deleted file mode 100644 index 171badc..0000000 --- a/frameworks/native/compilation.h +++ /dev/null @@ -1,92 +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. - */ -#ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H -#define NEURAL_NETWORK_RUNTIME_COMPILATION_H - -#include "inner_model.h" -#include "execution_plan.h" - -#include "device.h" -#include "cpp_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); -}; -} // namespace NeuralNetworkRuntime -} // namespace OHOS - -#endif // NEURAL_NETWORK_RUNTIME_COMPILATION_H \ No newline at end of file diff --git a/frameworks/native/device.h b/frameworks/native/device.h index f8f3ecc..9d74e59 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.h @@ -22,7 +22,7 @@ #include "interfaces/kits/c/neural_network_runtime_type.h" #include "cpp_type.h" -#include "nn_tensor.h" +#include "tensor_desc.h" #include "prepared_model.h" #include "mindir.h" @@ -62,7 +62,7 @@ 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; }; } // namespace NeuralNetworkRuntime 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.cpp b/frameworks/native/executor.cpp deleted file mode 100644 index fda1fff..0000000 --- a/frameworks/native/executor.cpp +++ /dev/null @@ -1,621 +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 "executor.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()) {} - -OH_NN_ReturnCode Executor::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()) { - LOGE("BuildInputTensor failed, input index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - // Build a tensor from nnTensor. - auto ret = inputTensor->BuildFromOHNNTensor(nnTensor); - if (ret != OH_NN_SUCCESS) { - LOGE("BuildInputTensor failed, please check input nnTensor."); - return ret; - } - - if (inputTensor->IsDynamicShape()) { - LOGE("BuildInputTensor failed, input nnTensor should has certain dimensions which cannot contain -1."); - return OH_NN_INVALID_PARAMETER; - } - - inputTensor->SetFormat(m_modelInputs[index]->GetFormat()); - if (!m_modelInputs[index]->CompareAttribute(*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()); - 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) -{ - void* curBuffer = m_inputTensors[index].tensor->GetBuffer(); - errno_t status = memcpy_s(curBuffer, dataLength, buffer, dataLength); - // Current buffer inside m_inputTensors is managed by executor, no need to release if memcpy failed. - if (status != EOK) { - LOGE("SetInputTensorWithCurrentBuffe failed, copy data from user buffer to device buffer failed. " - "Error code: %d.", status); - return OH_NN_MEMORY_ERROR; - } - - // Set the new tensor with the buffer of current tensor - inputTensor->SetBuffer(curBuffer, curBufferLength); - - // The memory is reused here. Thus, current tensor's buffer must set to nullptr, in case the memory is released - // twice. - m_inputTensors[index].tensor->SetBuffer(nullptr, 0); - - // Set to the new tensor, and release current one. - m_inputTensors[index].tensor = inputTensor; - return OH_NN_SUCCESS; -} - - -void Executor::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); - } - // Set current tensor's buffer to nullptr in case the NNTensor release the driver memory in destruction. - m_inputTensors[index].tensor->SetBuffer(nullptr, 0); - } - - // Set new input tensor data buffer - inputTensor->SetBuffer(inputBuffer, length); - - // Create or update the input tensor - ExeTensor exeTensor{inputTensor, nullptr, 0, isInnerMem}; - m_inputTensors[index] = exeTensor; -} - - -OH_NN_ReturnCode Executor::CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const -{ - std::vector> minInputDims; - std::vector> maxInputDims; - auto ret = m_executionPlan->GetInputDimRanges(minInputDims, maxInputDims); - if (ret != OH_NN_SUCCESS) { - LOGE("Get the dimension ranges of input %u failed. ErrorCode=%d", index, ret); - return ret; - } - - if (index >= minInputDims.size()) { - LOGE("index is %u, which exceeds the size of minInputDims:%zu.", index, minInputDims.size()); - return OH_NN_INVALID_PARAMETER; - } - - if (index >= maxInputDims.size()) { - LOGE("index is %u, which exceeds the size of maxInputDims:%zu.", index, maxInputDims.size()); - return OH_NN_INVALID_PARAMETER; - } - - const std::vector& minSingleInputDims = minInputDims[index]; - const std::vector& maxSingleInputDims = maxInputDims[index]; - - std::vector tensorShape = ConstructVectorFromArray(nnTensor.dimensions, nnTensor.dimensionCount); - size_t tensorShapeSize = tensorShape.size(); - if (minSingleInputDims.size() != tensorShapeSize || maxSingleInputDims.size() != tensorShapeSize) { - LOGE("Size of minSingleInputDims, maxSingleInputDims and tensorShape of input %u are not equal.", index); - return OH_NN_INVALID_PARAMETER; - } - - for (size_t j = 0; j < tensorShapeSize; ++j) { - // Dimensions cannot be negative - if (tensorShape[j] < 0) { - LOGE("Dimension %zu of input %u is %d.", j, index, tensorShape[j]); - return OH_NN_INVALID_PARAMETER; - } - uint32_t dim = static_cast(tensorShape[j]); - if (dim < minSingleInputDims[j] || dim > maxSingleInputDims[j]) { - LOGE("Dimension %zu of input %u is %u, which is out of range [%u, %u]", - j, index, dim, minSingleInputDims[j], maxSingleInputDims[j]); - return OH_NN_INVALID_PARAMETER; - } - } - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::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) { - LOGI("Skip input dimension bounds check."); - } else if (nnRet != OH_NN_SUCCESS) { - LOGE("SetInput failed, Check the range of the %uth input dimension ranges failed.", index); - return nnRet; - } - - std::shared_ptr inputTensor = CreateSharedPtr(); - if (inputTensor == nullptr) { - LOGE("SetInput failed, error happened when creating NNTensor."); - return OH_NN_MEMORY_ERROR; - } - - auto ret = BuildInputTensor(index, nnTensor, inputTensor); - if (ret != OH_NN_SUCCESS) { - LOGE("SetInput failed, please check input index or nnTensor."); - return ret; - } - - // dataLength will be larger than 0 after BuildInputTensor() - size_t dataLength = inputTensor->GetDataLength(); - if (length == 0 || length < dataLength) { - LOGE("SetInput failed, the given buffer length is too small to store the input nnTensor data."); - return OH_NN_INVALID_PARAMETER; - } - - // Get length of current buffer if it is allocate by SetInput() before. - size_t curBufferLength = 0; - if ((m_inputTensors.find(index) != m_inputTensors.end()) && (m_inputTensors[index].isInnerMem)) { - curBufferLength = m_inputTensors[index].tensor->GetBufferLength(); - } - - // (dataLength <= curBufferLength) returns true if and only if current buffer is allocated by SetInput() before - // and is larger than user buffer. - if (dataLength <= curBufferLength) { - ret = SetInputTensorWithCurrentBuffer(index, inputTensor, buffer, dataLength, curBufferLength); - if (ret != OH_NN_SUCCESS) { - LOGE("SetInput failed, error happened when setting input with current buffer."); - return ret; - } - m_isRun = false; - return OH_NN_SUCCESS; - } - - /** - * Buffer needs to allocated or reallocated if: - * - * - Current buffer is not enough. - * - 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); - if (inputBuffer == nullptr) { - LOGE("SetInput failed, error happened when allocating input device buffer."); - return OH_NN_MEMORY_ERROR; - } - - 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); - return OH_NN_MEMORY_ERROR; - } - - SetInputTensorWithNewBuffer(index, inputTensor, inputBuffer, length, true); - m_isRun = false; - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::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) { - LOGI("Skip input dimension bounds check."); - } else if (nnRet != OH_NN_SUCCESS) { - LOGE("SetInputFromMemory failed, Check the range of the %uth input dimension ranges failed.", index); - return nnRet; - } - - // Build a input tensor - std::shared_ptr inputTensor = CreateSharedPtr(); - if (inputTensor == nullptr) { - LOGE("SetInputFromMemory failed, error happened when creating NNTensor."); - return OH_NN_MEMORY_ERROR; - } - - auto ret = BuildInputTensor(index, nnTensor, inputTensor); - if (ret != OH_NN_SUCCESS) { - LOGE("SetInputFromMemory failed, please check input index or nnTensor"); - return ret; - } - - // check data length - size_t dataLength = inputTensor->GetDataLength(); - if (memory.length == 0 || memory.length < dataLength) { - LOGE("SetInputFromMemory failed," - " the length in the given memory is too small to store the input nnTensor data."); - return OH_NN_INVALID_PARAMETER; - } - - SetInputTensorWithNewBuffer(index, inputTensor, const_cast(memory.data), memory.length, false); - m_isRun = false; - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length) -{ - if (index >= m_modelOutputs.size()) { - LOGE("SetOutput failed, output index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - size_t dataLength = m_modelOutputs[index]->GetDataLength(); - 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; - } - - // 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(); - if (length <= curBufferLength) { - // If current device buffer size is enough, only update the user buffer. - m_outputTensors[index].userBuffer = buffer; - m_outputTensors[index].userBufferLength = length; - m_isRun = false; - return OH_NN_SUCCESS; - } else { - // 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); - } - } - } 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]; - } - - void* deviceOutputBuffer = outputDevice->AllocateTensorBuffer(length, m_outputTensors[index].tensor); - if (deviceOutputBuffer == nullptr) { - LOGE("SetOutput failed, allocating output device buffer failed."); - return OH_NN_MEMORY_ERROR; - } - - m_outputTensors[index].tensor->SetBuffer(deviceOutputBuffer, length); - m_outputTensors[index].userBuffer = buffer; - m_outputTensors[index].userBufferLength = length; - m_outputTensors[index].isInnerMem = true; - m_isRun = false; - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory) -{ - if (index >= m_modelOutputs.size()) { - LOGE("SetOutputFromMemory failed, output index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - size_t dataLength = m_modelOutputs[index]->GetDataLength(); - 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; - } - - if (m_outputTensors.find(index) != m_outputTensors.end()) { - 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); - } - } 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]; - } - - // Set the output tensor with memory - m_outputTensors[index].tensor->SetBuffer(const_cast(memory.data), memory.length); - m_outputTensors[index].userBuffer = nullptr; - m_outputTensors[index].userBufferLength = 0; - m_outputTensors[index].isInnerMem = false; - m_isRun = false; - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::GetOutputShape(uint32_t index, int32_t** dimensions, uint32_t& dimensionCount) -{ - 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); - 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."); - return OH_NN_INVALID_PARAMETER; - } - - // Allocate device buffer - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - void* deviceInputBuffer = inputDevice->AllocateTensorBuffer(length, m_modelInputs[index]); - if (deviceInputBuffer == nullptr) { - LOGE("CreateInputMemory failed, allocating intput device buffer failed."); - return OH_NN_MEMORY_ERROR; - } - - *memory = new(std::nothrow) OH_NN_Memory{deviceInputBuffer, length}; - if (*memory == nullptr) { - LOGE("CreateInputMemory failed, constructing OH_NN_Memory failed."); - inputDevice->ReleaseBuffer(deviceInputBuffer); - return OH_NN_MEMORY_ERROR; - } - - // Save the buffer address for check when destroying it. - m_inputCreatedMem[index].emplace_back(deviceInputBuffer); - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::DestroyInputMemory(uint32_t index, OH_NN_Memory** memory) -{ - if (index >= m_modelInputs.size()) { - LOGE("DestroyInputMemory failed, input index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - if (m_inputCreatedMem.find(index) == m_inputCreatedMem.end()) { - LOGE("DestroyInputMemory failed, the memory has not been created with the index."); - return OH_NN_INVALID_PARAMETER; - } - - std::vector& inputCreatedMem = m_inputCreatedMem[index]; - auto pos = std::find(inputCreatedMem.begin(), inputCreatedMem.end(), (*memory)->data); - if (pos == inputCreatedMem.end()) { - LOGE("DestroyInputMemory failed, the index does not match the memory."); - return OH_NN_INVALID_PARAMETER; - } - - std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - auto ret = inputDevice->ReleaseBuffer((*memory)->data); - if (ret != OH_NN_SUCCESS) { - LOGE("Release input buffer failed."); - return ret; - } - - inputCreatedMem.erase(pos); - delete *memory; - *memory = nullptr; - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) -{ - if (index >= m_modelOutputs.size()) { - LOGE("CreateOutputMemory failed, output index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - // Allocate device buffer - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - void* deviceOutputBuffer = outputDevice->AllocateTensorBuffer(length, m_modelOutputs[index]); - if (deviceOutputBuffer == nullptr) { - LOGE("CreateOutputMemory failed, allocating output device buffer failed."); - return OH_NN_MEMORY_ERROR; - } - - *memory = new(std::nothrow) OH_NN_Memory{deviceOutputBuffer, length}; - if (*memory == nullptr) { - LOGE("CreateOutputMemory failed, constructing OH_NN_Memory failed."); - outputDevice->ReleaseBuffer(deviceOutputBuffer); - return OH_NN_MEMORY_ERROR; - } - - // Save the buffer address for check when destroying it. - m_outputCreatedMem[index].emplace_back(deviceOutputBuffer); - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory) -{ - if (index >= m_modelOutputs.size()) { - LOGE("DestroyOutputMemory failed, output index is out of range."); - return OH_NN_INVALID_PARAMETER; - } - - if (m_outputCreatedMem.find(index) == m_outputCreatedMem.end()) { - LOGE("DestroyOutputMemory failed, the memory has not been created with the index."); - return OH_NN_INVALID_PARAMETER; - } - - std::vector& outputCreatedMem = m_outputCreatedMem[index]; - auto pos = std::find(outputCreatedMem.begin(), outputCreatedMem.end(), (*memory)->data); - if (pos == outputCreatedMem.end()) { - LOGE("DestroyOutputMemory failed, the index does not match the memory."); - return OH_NN_INVALID_PARAMETER; - } - - std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - auto ret = outputDevice->ReleaseBuffer((*memory)->data); - if (ret != OH_NN_SUCCESS) { - LOGE("Release output buffer failed."); - return ret; - } - - outputCreatedMem.erase(pos); - delete *memory; - *memory = nullptr; - - return OH_NN_SUCCESS; -} - - -OH_NN_ReturnCode Executor::Run() -{ - NNRT_TRACE_NAME("Execution"); - if (m_modelInputs.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()) { - LOGE("Run failed, some output tensors have not been set."); - return OH_NN_INVALID_PARAMETER; - } - - // Build the NNTensor pointer vector: inputTensors and outputTensors - std::vector> inputTensors; - std::vector> outputTensors; - size_t inputSize = m_inputTensors.size(); - size_t outputSize = m_outputTensors.size(); - for (size_t i = 0; i < inputSize; ++i) { - inputTensors.emplace_back(m_inputTensors[i].tensor); - } - for (size_t i = 0; i < outputSize; ++i) { - outputTensors.emplace_back(m_outputTensors[i].tensor); - } - - // Predict - auto ret = m_executionPlan->Run(inputTensors, outputTensors); - if (ret != OH_NN_SUCCESS) { - LOGE("Run failed, error happened when executing the inference."); - return ret; - } - - errno_t status{EOK}; - // Copy inner device buffer to user buffer if using SetOutput() - for (size_t i = 0; i < outputSize; ++i) { - if (m_outputTensors[i].isInnerMem) { - auto size = outputTensors[i]->GetDataLength(); - if (size > m_outputTensors[i].userBufferLength) { - LOGE("Output buffer size is not enough. Your size=%zu, but actual output size=%zu.", - m_outputTensors[i].userBufferLength, size); - return OH_NN_INVALID_PARAMETER; - } - - void* deviceBuffer = outputTensors[i]->GetBuffer(); - if (deviceBuffer == nullptr) { - LOGE("Output buffer is nullptr."); - return OH_NN_FAILED; - } - - status = memcpy_s(m_outputTensors[i].userBuffer, m_outputTensors[i].userBufferLength, deviceBuffer, size); - if (status != EOK) { - LOGE("Run failed, memory copy from device buffer to user buffer failed. Error code: %d.", status); - return OH_NN_MEMORY_ERROR; - } - } - } - - m_isRun = true; - return OH_NN_SUCCESS; -} - -Executor::~Executor() -{ - std::shared_ptr inputDevice; - for (auto& it : m_inputTensors) { - inputDevice = m_executionPlan->GetInputDevice(); - if ((it.second).isInnerMem) { - inputDevice->ReleaseBuffer((it.second).tensor->GetBuffer()); - } - (it.second).tensor->SetBuffer(nullptr, 0); - (it.second).tensor.reset(); - (it.second).userBuffer = nullptr; - } - 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()); - } - (it.second).tensor->SetBuffer(nullptr, 0); - (it.second).tensor.reset(); - (it.second).userBuffer = nullptr; - } - m_outputTensors.clear(); - - for (auto& it : m_inputCreatedMem) { - it.second.clear(); - } - m_inputCreatedMem.clear(); - - for (auto& it : m_outputCreatedMem) { - it.second.clear(); - } - m_outputCreatedMem.clear(); - - m_outputDimensions.clear(); - m_modelInputs.clear(); - m_modelOutputs.clear(); -} -} // namespace NeuralNetworkRuntime -} // namespace OHOS diff --git a/frameworks/native/executor.h b/frameworks/native/executor.h index c7b2061..fdd68fe 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,44 @@ #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 "tensor_desc.h" +#include "interfaces/kits/c/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; + virtual ~Executor() = default; + + virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, + size_t* minInputDims, + size_t* maxInputDims, + size_t* shapeNum) = 0; + virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) = 0; + + virtual size_t GetInputNum() = 0; + virtual size_t GetOutputNum() = 0; + virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) = 0; + virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) = 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 GetDeviceID() = 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..3c6602c 100644 --- a/frameworks/native/hdi_device_v1_0.cpp +++ b/frameworks/native/hdi_device_v1_0.cpp @@ -357,7 +357,7 @@ void* HDIDeviceV1_0::AllocateBuffer(size_t length) return addr; } -void* HDIDeviceV1_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +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..1c35d91 100644 --- a/frameworks/native/hdi_device_v1_0.h +++ b/frameworks/native/hdi_device_v1_0.h @@ -59,7 +59,7 @@ 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; private: diff --git a/frameworks/native/hdi_device_v2_0.cpp b/frameworks/native/hdi_device_v2_0.cpp index e55d6a6..db43e00 100644 --- a/frameworks/native/hdi_device_v2_0.cpp +++ b/frameworks/native/hdi_device_v2_0.cpp @@ -392,7 +392,7 @@ void* HDIDeviceV2_0::AllocateBuffer(size_t length) return addr; } -void* HDIDeviceV2_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +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..09d1595 100644 --- a/frameworks/native/hdi_device_v2_0.h +++ b/frameworks/native/hdi_device_v2_0.h @@ -59,7 +59,7 @@ 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; private: diff --git a/frameworks/native/memory_manager.cpp b/frameworks/native/memory_manager.cpp deleted file mode 100644 index 1c6cc87..0000000 --- a/frameworks/native/memory_manager.cpp +++ /dev/null @@ -1,102 +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 "memory_manager.h" - -#include -#include - -#include "cpp_type.h" -#include "common/log.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -void* MemoryManager::MapMemory(int fd, size_t length) -{ - if (fd < 0) { - LOGE("Invalid fd, fd must greater than 0."); - return nullptr; - } - - if (length <= 0 || length > ALLOCATE_BUFFER_LIMIT) { - LOGE("Invalid buffer size, it must greater than 0 and less than 1Gb. length=%zu", length); - return nullptr; - } - - void* addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - LOGE("Map fd to address failed."); - return nullptr; - } - - std::lock_guard lock(m_mtx); - Memory memory {fd, addr, length}; - m_memorys.emplace(addr, memory); - return addr; -} - -OH_NN_ReturnCode MemoryManager::UnMapMemory(const void* buffer) -{ - if (buffer == nullptr) { - LOGE("Buffer is nullptr, no need to release."); - return OH_NN_INVALID_PARAMETER; - } - - auto iter = m_memorys.find(buffer); - if (iter == m_memorys.end()) { - LOGE("This buffer is not found, cannot release."); - return OH_NN_INVALID_PARAMETER; - } - - auto& memory = m_memorys[buffer]; - auto unmapResult = munmap(const_cast(memory.data), memory.length); - if (unmapResult != 0) { - LOGE("Unmap memory failed. Please try again."); - return OH_NN_MEMORY_ERROR; - } - memory.data = nullptr; - - if (close(memory.fd) != 0) { - LOGE("Close memory fd failed. fd=%d", memory.fd); - return OH_NN_MEMORY_ERROR; - } - - std::lock_guard lock(m_mtx); - m_memorys.erase(iter); - return OH_NN_SUCCESS; -} - -OH_NN_ReturnCode MemoryManager::GetMemory(const void* buffer, Memory& memory) const -{ - if (buffer == nullptr) { - LOGE("Memory is nullptr."); - return OH_NN_NULL_PTR; - } - - auto iter = m_memorys.find(buffer); - if (iter == m_memorys.end()) { - LOGE("Memory is not found."); - return OH_NN_INVALID_PARAMETER; - } - - memory.fd = iter->second.fd; - memory.data = iter->second.data; - memory.length = iter->second.length; - - return OH_NN_SUCCESS; -} -} // NeuralNetworkRuntime -} // OHOS \ No newline at end of file diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp new file mode 100644 index 0000000..b727d07 --- /dev/null +++ b/frameworks/native/neural_network_core.cpp @@ -0,0 +1,689 @@ +/* + * 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 "interfaces/kits/c/neural_network_core.h" +#include "common/log.h" +#include "tensor.h" + +#include + +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 shapeNum) +{ + 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 (shapeNum == 0) { + LOGE("OH_NNTensorDesc_SetShape failed, shapeNum is 0."); + return OH_NN_INVALID_PARAMETER; + } + TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->SetShape(shape, shapeNum); +} + +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeNum) +{ + 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 (shapeNum == nullptr) { + LOGE("OH_NNTensorDesc_GetShape failed, shapeNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetShape(shape, shapeNum); +} + +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_GetElementNum(const NN_TensorDesc *tensorDesc, size_t *elementNum) +{ + if (tensorDesc == nullptr) { + LOGE("OH_NNTensorDesc_GetElementNum failed, tensorDesc is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (elementNum == nullptr) { + LOGE("OH_NNTensorDesc_GetElementNum failed, elementNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const TensorDesc *tensorDescImpl = reinterpret_cast(tensorDesc); + return tensorDescImpl->GetElementNum(elementNum); +} + +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; + } + + // todo + /*BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendName); + if (backend == nullptr) { + LOGE("OH_NNTensor_Create failed, passed invalid backend name %{public}s.", backendName); + return nullptr; + } + + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + Tensor* tensorImpl = backend->CreateTensor(deviceID, 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;*/ + return nullptr; +} + +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; + } + + // todo + /*BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendName); + if (backend == nullptr) { + LOGE("OH_NNTensor_CreateWithSize failed, passed invalid backend name %{public}s.", backendName); + return nullptr; + } + + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + Tensor* tensorImpl = backend->CreateTensor(backendName, 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;*/ + return nullptr; +} + +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; + } + + // todo + /*BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendName); + if (backend == nullptr) { + LOGE("OH_NNTensor_CreateWithFd failed, passed invalid backend name %{public}s.", backendName); + return nullptr; + } + + TensorDesc* descImpl = reinterpret_cast(tensorDesc); + Tensor* tensorImpl = backend->CreateTensor(backendName, descImpl); + if (tensorImpl == nullptr) { + LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); + return nullptr; + } + + OH_NN_ReturnCode 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;*/ + return nullptr; +} + +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; + } + + // todo + /*Tensor* tensorImpl = reinterpret_cast(*tensor); + std::string backendName; + auto ret = tensorImpl->GetBackendName(backendName); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNTensor_Destroy failed, failed to get backend name."); + return ret; + } + + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendName); + if (backend == nullptr) { + LOGE("OH_NNTensor_Destroy failed, passed invalid backend name %{public}s.", backendName.c_str()); + return NNCORE_NULL_PTR; + } + + 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 NNCore_Executor* OH_NNCore_ConstructExecutor(const NNCore_Compiled* compiled) +// { +// if (compiled == nullptr) { +// LOGE("OH_NNCore_ConstructExecutor failed, compiled is nullptr."); +// return nullptr; +// } + +// const Compiled* compiledImpl = reinterpret_cast(compiled); +// NNCore_Executor* executor = nullptr; +// OH_NN_ReturnCode returnCode = compiledImpl->CreateExecutor(&executor); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_ConstructExecutor failed, failed to create executor."); +// return nullptr; +// } +// return executor; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_DestroyExecutor(NNCore_Executor** executor) +// { +// if (executor == nullptr) { +// LOGE("OH_NNCore_DestroyExecutor failed, executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (*executor == nullptr) { +// LOGE("OH_NNCore_DestroyExecutor failed, *executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Executor* executorImpl = reinterpret_cast(*executor); +// std::string backendName; +// OH_NN_ReturnCode returnCode = executorImpl->GetBackendName(backendName); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_DestroyExecutor failed, failed to get backend name from tensorDesc."); +// return returnCode; +// } + +// BackendManager& backendManager = BackendManager::GetInstance(); +// std::shared_ptr backend = backendManager.GetBackend(backendName); +// if (backend == nullptr) { +// LOGE("OH_NNCore_DestroyExecutor failed, failed to get backend of %{public}s.", backendName.c_str()); +// return NNCORE_NULL_PTR; +// } +// returnCode = backend->DestroyExecutor(executorImpl); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_DestroyExecutor failed, failed to destroy executor."); +// return returnCode; +// } +// *executor = nullptr; +// return OH_NN_SUCCESS; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_SetExecutorOnRunDone(NNCore_Executor* executor, NNCore_OnRunDone onRunDone) +// { +// if (executor == nullptr) { +// LOGE("OH_NNCore_SetExecutorOnRunDone failed, executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (onRunDone == nullptr) { +// LOGE("OH_NNCore_SetExecutorOnRunDone failed, onRunDone is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Executor* executorImpl = reinterpret_cast(executor); +// return executorImpl->SetOnRunDone(onRunDone); +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_SetExecutorOnServiceDied( +// NNCore_Executor* executor, NNCore_OnServiceDied onServiceDied) +// { +// if (executor == nullptr) { +// LOGE("OH_NNCore_SetExecutorOnServiceDied failed, executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (onServiceDied == nullptr) { +// LOGE("OH_NNCore_SetExecutorOnServiceDied failed, onServiceDied is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Executor* executorImpl = reinterpret_cast(executor); +// return executorImpl->SetOnServiceDied(onServiceDied); +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_ExecutorRunSync(NNCore_Executor* executor, NN_Tensor* inputTensor[], +// size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum) +// { +// if (executor == nullptr) { +// LOGE("NNCore_ExecutorRunSync failed, executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (inputTensor == nullptr) { +// LOGE("NNCore_ExecutorRunSync failed, inputTensor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (inputNum == 0) { +// LOGE("NNCore_ExecutorRunSync failed, inputNum is 0."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (outputTensor == nullptr) { +// LOGE("NNCore_ExecutorRunSync failed, outputTensor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (outputNum == 0) { +// LOGE("NNCore_ExecutorRunSync failed, outputNum is 0."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Executor* executorImpl = reinterpret_cast(executor); +// return executorImpl->RunSync(inputTensor, inputNum, outputTensor, outputNum); +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_ExecutorRunAsync(NNCore_Executor* executor, NN_Tensor* inputTensor[], +// size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum, int32_t timeout, void* userData) +// { +// if (executor == nullptr) { +// LOGE("NNCore_ExecutorRunAsync failed, executor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (inputTensor == nullptr) { +// LOGE("NNCore_ExecutorRunAsync failed, inputTensor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (inputNum == 0) { +// LOGE("NNCore_ExecutorRunAsync failed, inputNum is 0."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (outputTensor == nullptr) { +// LOGE("NNCore_ExecutorRunAsync failed, outputTensor is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (outputNum == 0) { +// LOGE("NNCore_ExecutorRunAsync failed, outputNum is 0."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (userData == 0) { +// LOGE("NNCore_ExecutorRunAsync failed, userData is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Executor* executorImpl = reinterpret_cast(executor); +// return executorImpl->RunAsync(inputTensor, inputNum, outputTensor, outputNum, timeout, userData); +// } + +// NNRT_API NNCore_Options* OH_NNCore_CreateOptions(const char* backendName) +// { +// if (backendName == nullptr) { +// LOGE("OH_NNCore_CreateOptions failed, backendName is nullptr."); +// return nullptr; +// } + +// BackendManager& manager = BackendManager::GetInstance(); +// std::shared_ptr backend = manager.GetBackend(backendName); +// if (backend == nullptr) { +// LOGE("OH_NNCore_CreateOptions failed, fail to get backend."); +// return nullptr; +// } + +// Options* innerOptions = backend->CreateOptions(); +// if (innerOptions == nullptr) { +// LOGE("OH_NNCore_CreateOptions failed, fail to create options."); +// return nullptr; +// } + +// NNCore_Options* options = reinterpret_cast(innerOptions); +// return options; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_DestroyOptions(NNCore_Options** options) +// { +// if (options == nullptr) { +// LOGE("OH_NNCore_DestroyOptions failed, options is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } +// if (*options == nullptr) { +// LOGE("OH_NNCore_DestroyOptions failed, *options is nullptr."); +// return OH_NN_INVALID_PARAMETER; +// } + +// Options* optionsImpl = reinterpret_cast(*options); + +// std::string backendName; +// OH_NN_ReturnCode returnCode = optionsImpl->GetBackendName(backendName); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_DestroyOptions failed, failed to get backend name from options."); +// return returnCode; +// } + +// BackendManager& backendManager = BackendManager::GetInstance(); +// std::shared_ptr backend = backendManager.GetBackend(backendName); +// if (backend == nullptr) { +// LOGE("OH_NNCore_DestroyOptions failed, failed to get backend of %s.", backendName.c_str()); +// return NNCORE_NULL_PTR; +// } + +// returnCode = backend->DestroyOptions(optionsImpl); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_DestroyOptions failed, failed to destroy options."); +// return returnCode; +// } + +// *options = nullptr; +// return OH_NN_SUCCESS; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_SetPriority(NNCore_Options* options, NNCore_Priority priority) +// { +// if (options == nullptr) { +// LOGE("OH_NNCore_SetPriority failed, input options is nullptr;"); +// return OH_NN_INVALID_PARAMETER; +// } + +// Options* optionsImpl = reinterpret_cast(options); +// OH_NN_ReturnCode returnCode = optionsImpl->SetPriority(priority); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_SetPriority failed, failed to set priority."); +// return returnCode; +// } + +// return OH_NN_SUCCESS; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_SetPerformanceMode(NNCore_Options* options, NNCore_PerformanceMode performanceMode) +// { +// if (options == nullptr) { +// LOGE("OH_NNCore_SetPerformanceMode failed, input options is nullptr;"); +// return OH_NN_INVALID_PARAMETER; +// } + +// Options* optionsImpl = reinterpret_cast(options); +// OH_NN_ReturnCode returnCode = optionsImpl->SetPerformanceMode(performanceMode); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_SetPerformanceMode failed, failed to set performance mode."); +// return returnCode; +// } + +// return OH_NN_SUCCESS; +// } + +// NNRT_API OH_NN_ReturnCode OH_NNCore_SetEnableFloat16(NNCore_Options* options, bool enableFloat16) +// { +// if (options == nullptr) { +// LOGE("OH_NNCore_SetEnableFloat16 failed, input options is nullptr;"); +// return OH_NN_INVALID_PARAMETER; +// } + +// Options* optionsImpl = reinterpret_cast(options); +// OH_NN_ReturnCode returnCode = optionsImpl->SetEnableFp16(enableFloat16); +// if (returnCode != OH_NN_SUCCESS) { +// LOGE("OH_NNCore_SetEnableFloat16 failed, failed to set fp16 enabled."); +// return returnCode; +// } + +// return OH_NN_SUCCESS; +// } diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp deleted file mode 100644 index f492754..0000000 --- a/frameworks/native/neural_network_runtime.cpp +++ /dev/null @@ -1,733 +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 "interfaces/innerkits/c/neural_network_runtime_inner.h" -#include "interfaces/kits/c/neural_network_runtime.h" - -#include "compilation.h" -#include "device_manager.h" -#include "executor.h" -#include "inner_model.h" -#include "common/log.h" - - -using namespace OHOS::NeuralNetworkRuntime; - -#define NNRT_API __attribute__((visibility("default"))) - -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_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_NNModel_AddOperation(OH_NNModel *model, - OH_NN_OperationType op, - const OH_NN_UInt32Array *paramIndices, - const OH_NN_UInt32Array *inputIndices, - const OH_NN_UInt32Array *outputIndices) -{ - if (model == nullptr) { - LOGE("OH_NNModel_AddOperation failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (paramIndices == nullptr) { - LOGE("OH_NNModel_AddOperation failed, passed nullptr to paramIndices."); - return OH_NN_INVALID_PARAMETER; - } - - if (inputIndices == nullptr) { - LOGE("OH_NNModel_AddOperation failed, passed nullptr to inputIndices."); - return OH_NN_INVALID_PARAMETER; - } - - if (outputIndices == nullptr) { - LOGE("OH_NNModel_AddOperation failed, passed nullptr to outputIndices."); - return OH_NN_INVALID_PARAMETER; - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->AddOperation(op, *paramIndices, *inputIndices, *outputIndices); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, - uint32_t index, - const void *dataBuffer, - size_t length) -{ - if (model == nullptr) { - LOGE("OH_NNModel_SetTensorData failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (dataBuffer == nullptr) { - LOGE("OH_NNModel_SetTensorData failed, passed nullptr to dataBuffer, which has no effect."); - return OH_NN_INVALID_PARAMETER; - } - - if (length == 0) { - LOGE("OH_NNModel_SetTensorData failed, passed dataBuffer with length 0, which has no effect."); - return OH_NN_INVALID_PARAMETER; - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->SetTensorValue(index, dataBuffer, length); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, - const OH_NN_UInt32Array *inputIndices, - const OH_NN_UInt32Array *outputIndices) -{ - if (model == nullptr) { - LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (inputIndices == nullptr) { - LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to inputIndices."); - return OH_NN_INVALID_PARAMETER; - } - - if (outputIndices == nullptr) { - LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to outputIndices."); - return OH_NN_INVALID_PARAMETER; - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->SpecifyInputsAndOutputs(*inputIndices, *outputIndices); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model) -{ - if (model == nullptr) { - LOGE("OH_NNModel_Finish failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->Build(); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromLiteGraph(OH_NNModel *model, const void *liteGraph) -{ - if (model == nullptr) { - LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (liteGraph == nullptr) { - LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to liteGraph."); - return OH_NN_INVALID_PARAMETER; - } - - auto *pLiteGraph = static_cast(liteGraph); - InnerModel *innerModel = reinterpret_cast(model); - - // Once the innerModel built from the liteGraph successfully, the innerModel - // owns the liteGraph, in which case, the invoker should not delete - // the liteGraph actively. Otherwise, the invoker still has the ownership. - return innerModel->BuildFromLiteGraph(pLiteGraph); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromMetaGraph(OH_NNModel *model, const void *metaGraph, - const OH_NN_Extension *extensions, size_t extensionSize) -{ - if (model == nullptr) { - LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (metaGraph == nullptr) { - LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to metaGraph."); - return OH_NN_INVALID_PARAMETER; - } - - Buffer buffer; - std::string modelName; - for (size_t i = 0; i < extensionSize; ++i) { - std::string name = extensions[i].name; - if (name == "QuantBuffer") { - buffer.data = extensions[i].value; - buffer.length = extensions[i].valueSize; - } else if (name == "ModelName") { - modelName.assign(extensions[i].value, extensions[i].value + extensions[i].valueSize); - } - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->BuildFromMetaGraph(metaGraph, buffer, modelName); -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_SetInputsAndOutputsInfo(OH_NNModel *model, const OH_NN_TensorInfo *inputsInfo, - size_t inputSize, const OH_NN_TensorInfo *outputsInfo, size_t outputSize) -{ - if (model == nullptr) { - LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if ((inputsInfo == nullptr) || (inputSize == 0)) { - LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, inputsInfo is empty."); - return OH_NN_INVALID_PARAMETER; - } - - if ((outputsInfo == nullptr) || (outputSize == 0)) { - LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, outputsInfo is empty."); - return OH_NN_INVALID_PARAMETER; - } - - InnerModel *innerModel = reinterpret_cast(model); - return innerModel->SetInputsAndOutputsInfo(inputsInfo, inputSize, outputsInfo, outputSize); -} - -NNRT_API void OH_NNModel_Destroy(OH_NNModel **model) -{ - if (model == nullptr) { - LOGW("OH_NNModel_Destroy has no effect, passed nullptr to model."); - return; - } - - if (*model == nullptr) { - LOGW("OH_NNModel_Destroy has no effect, passed nullptr to *model."); - return; - } - - InnerModel *innerModel = reinterpret_cast(*model); - delete innerModel; - *model = nullptr; -} - -NNRT_API OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, - size_t deviceID, - const bool **isAvailable, - uint32_t *opCount) -{ - if (model == nullptr) { - LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to model."); - return OH_NN_INVALID_PARAMETER; - } - - if (isAvailable == nullptr) { - LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to isAvailable."); - return OH_NN_INVALID_PARAMETER; - } - - if (*isAvailable != nullptr) { - LOGE("OH_NNModel_GetAvailableOperations failed, *isAvailable is not nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (opCount == nullptr) { - LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to opCount."); - return OH_NN_INVALID_PARAMETER; - } - - 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/nn_tensor.h b/frameworks/native/nn_tensor.h index fc7db02..dc47d02 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -20,7 +20,7 @@ #include #include "cpp_type.h" -#include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime_type.h" #include "interfaces/innerkits/c/neural_network_runtime_inner.h" namespace OHOS { diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp new file mode 100644 index 0000000..75e3bf2 --- /dev/null +++ b/frameworks/native/nnexecutor.cpp @@ -0,0 +1,250 @@ +/* + * 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 "nnexecutor.h" +#include "nntensor.h" +// #include "nnbackend.h" +// #include "backend_manager.h" +#include "common/log.h" +#include "cpp_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +NNExecutor::NNExecutor(size_t deviceID, std::shared_ptr device, std::shared_ptr preparedModel, + std::vector> inputTensorDescs, + std::vector> outputTensorDescs) +{ + m_deviceID = deviceID; + 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) +{ + if (shapeNum == nullptr) { + LOGE("NNExecutor::GetInputDimRange failed, shapeNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(m_minInputDims, m_maxInputDims); + if (oldRet != OH_NN_SUCCESS) { + LOGW("NNExecutor::GetInputDimRange failed, current version don't support get input dim ranges."); + return OH_NN_OPERATION_FORBIDDEN; + } + + std::vector minInputDimVec = m_minInputDims[inputIndex]; + std::vector maxInputDimVec = m_maxInputDims[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 = static_cast(minInputDimVec.data()); + maxInputDims = static_cast(maxInputDimVec.data()); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) +{ + if (outputIndex >= m_outputTensorDescs.size()) { + LOGE("NNExecutor::GetOutputShape failed, outputIndex must be smaller than m_outputTensorDescs.size."); + return OH_NN_INVALID_PARAMETER; + } + + auto tensorDesc = m_outputTensorDescs[outputIndex]; + auto ret = tensorDesc->GetShape(shape, shapeNum); + if (ret != OH_NN_SUCCESS) { + LOGE("NNExecutor::GetOutputShape failed, failed to get shape from tensor desc."); + return ret; + } + + return OH_NN_SUCCESS; +} + +size_t NNExecutor::GetInputNum() +{ + return m_inputTensorDescs.size(); +} + +size_t NNExecutor::GetOutputNum() +{ + return m_outputTensorDescs.size(); +} + +NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) +{ + if (index >= m_inputTensorDescs.size()) { + LOGE("NNExecutor::CreateInputTensorDesc failed, index must be smaller than m_inputTensorDescs.size."); + 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].get()); + + return reinterpret_cast(tensorDescImpl); +} + +NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) +{ + if (index >= m_outputTensorDescs.size()) { + LOGE("NNExecutor::CreateOutputTensorDesc failed, index must be smaller than m_outputTensorDescs.size."); + 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].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) +{ + 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) { + inputTensorsVec.emplace_back(inputTensors[i]); + } + + std::vector outputTensorsVec; + for (size_t i = 0; i < outputSize; ++i) { + outputTensorsVec.emplace_back(outputTensors[i]); + } + + std::vector> outputsDims; + std::vector isSufficientDataBuffer; + // todo + // auto oldRet = m_preparedModel->Run(inputTensorsVec, outputTensorsVec, outputsDims, isSufficientDataBuffer); + // if (oldRet != OH_NN_SUCCESS) { + // LOGE("NNExecutor::RunSync failed, failed to run in prepared model."); + // return OH_NN_FAILED; + // } + + // 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]->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::GetDeviceID() +{ + return m_deviceID; +} + +OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize) +{ + OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(m_minInputDims, m_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 != m_minInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of m_minInputDims is not equal to inputSize."); + return OH_NN_INVALID_PARAMETER; + } + + if (inputSize != m_maxInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of m_maxInputDims is not equal to 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 = m_minInputDims[i]; + const std::vector& maxSingleInputDims = m_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; +} +} // 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..95af79e --- /dev/null +++ b/frameworks/native/nnexecutor.h @@ -0,0 +1,73 @@ +/* + * 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" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class NNExecutor : public Executor { +public: + NNExecutor(size_t deviceID, + std::shared_ptr device, + std::shared_ptr preparedModel, + std::vector> inputTensorDescs, + std::vector> outputTensorDescs); + virtual ~NNExecutor() = default; + + virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, + size_t* minInputDims, + size_t* maxInputDims, + size_t* shapeNum) override; + virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) override; + + virtual size_t GetInputNum() override; + virtual size_t GetOutputNum() override; + virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) override; + virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) 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 GetDeviceID() override; + +private: + OH_NN_ReturnCode CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize); + +private: + size_t m_deviceID {0}; + std::shared_ptr m_device {nullptr}; + std::shared_ptr m_preparedModel {nullptr}; + std::vector> m_inputTensorDescs; + std::vector> m_outputTensorDescs; + std::vector> m_minInputDims; + std::vector> m_maxInputDims; +}; +} // 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..eb33b13 --- /dev/null +++ b/frameworks/native/nntensor.cpp @@ -0,0 +1,313 @@ +/* + * 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 "nntensor.h" +#include "common/log.h" +#include +#include +#include "interfaces/kits/c/neural_network_runtime_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +const size_t ALLOCATE_BUFFER_LIMIT = 1024 * 1024 * 1024; + +NNTensor2_0::~NNTensor2_0() +{ + if (!m_isUserData) { + ReleaseMemory(); + } + + if (m_tensorDesc != nullptr) { + 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::CreateData() +{ + if (m_data != nullptr) { + LOGE("NNTensor2_0::CreateData failed, m_data has been created before."); + return OH_NN_FAILED; + } + + 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 (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; + } + + auto 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; + } + + 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 - 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."); + 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) +{ + // todo + /* + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(m_backendName); + if (backend == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, failed to get backend of %{public}s.", m_backendName.c_str()); + return NNCORE_NULL_PTR; + } + + auto* nnBackend = reinterpret_cast(backend.get()); + if (nnBackend == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, failed to convert backend to nnbackend."); + return NNCORE_NULL_PTR; + } + auto device = nnBackend->GetDevice(); + if (device == nullptr) { + LOGE("NNTensor2_0::AllocateMemory failed, device of nnbackend is nullptr."); + return NNCORE_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."); + 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; + } + + // todo + /* + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(m_backendName); + if (backend == nullptr) { + LOGE("NNTensor2_0::ReleaseMemory failed, failed to get backend of %{public}s.", m_backendName.c_str()); + return NNCORE_NULL_PTR; + } + // todo backend中拿到device 分配内存 + auto* nnrtBackend = reinterpret_cast(backend.get()); + if (nnrtBackend == nullptr) { + LOGE("NNTensor2_0::ReleaseMemory failed, failed to convert backend to nnbackend."); + return NNCORE_NULL_PTR; + } + auto device = nnrtBackend->GetDevice(); + if (device == nullptr) { + LOGE(""); + return NNCORE_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::GetDeviceID() const +{ + return m_deviceID; +} + +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..c7f464d --- /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 deviceID, TensorDesc* tensorDesc) : + m_deviceID(deviceID), m_tensorDesc(tensorDesc) {} + virtual ~NNTensor2_0(); + + 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 GetDeviceID() 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_deviceID {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/memory_manager.h b/frameworks/native/ops/ops_validation.cpp similarity index 41% rename from frameworks/native/memory_manager.h rename to frameworks/native/ops/ops_validation.cpp index 5518deb..988ffd8 100644 --- a/frameworks/native/memory_manager.h +++ b/frameworks/native/ops/ops_validation.cpp @@ -13,48 +13,21 @@ * limitations under the License. */ -#ifndef NEURAL_NETWORK_RUNTIME_MEMORY_MANAGER_H -#define NEURAL_NETWORK_RUNTIME_MEMORY_MANAGER_H +// #include "mindir_types.h" // todo -#include -#include - -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "ops_validation.h" +#include "mindir_types.h" namespace OHOS { namespace NeuralNetworkRuntime { -const int INVALID_FD = -1; - -struct Memory { - int fd; - const void* data; - size_t length; -}; - -class MemoryManager { -public: - ~MemoryManager() = default; - - void* MapMemory(int fd, size_t length); - OH_NN_ReturnCode UnMapMemory(const void* buffer); - OH_NN_ReturnCode GetMemory(const void* buffer, Memory& memory) const; - - static MemoryManager* GetInstance() - { - static MemoryManager instance; - return &instance; +namespace Validation { +bool ValidatePadMode(int8_t padMode) +{ + if ((padMode >= mindspore::lite::PAD_MODE_PAD) && (padMode <= mindspore::lite::PAD_MODE_VALID)) { + return true; } - -private: - MemoryManager() {}; - MemoryManager(const MemoryManager&) = delete; - MemoryManager& operator=(const MemoryManager&) = delete; - -private: - // key: OH_NN_Memory, value: fd - std::unordered_map m_memorys; - std::mutex m_mtx; -}; + return false; +} +} // namespace Validation } // namespace NeuralNetworkRuntime -} // OHOS -#endif // NEURAL_NETWORK_RUNTIME_MEMORY_MANAGER_H \ No newline at end of file +} // 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/tensor.h b/frameworks/native/tensor.h new file mode 100644 index 0000000..9e2776f --- /dev/null +++ b/frameworks/native/tensor.h @@ -0,0 +1,43 @@ +/* + * 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(const std::string& backendName, TensorDesc* tensorDesc); + virtual ~Tensor() = default; + + 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 GetDeviceID() 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..32d6704 --- /dev/null +++ b/frameworks/native/tensor_desc.cpp @@ -0,0 +1,200 @@ +/* + * 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) { + LOGE("GetElementNum failed, shape[%{public}zu] should larger than zero, now is %{public}d.", i, m_shape[i]); + *elementNum = 0; + return OH_NN_INVALID_PARAMETER; + } + (*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; + } + size_t elementNum = 0; + auto ret = GetElementNum(&elementNum); + 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/execution_plan.h b/frameworks/native/tensor_desc.h similarity index 38% rename from frameworks/native/execution_plan.h rename to frameworks/native/tensor_desc.h index 54f4648..08cfc39 100644 --- a/frameworks/native/execution_plan.h +++ b/frameworks/native/tensor_desc.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,36 +13,43 @@ * limitations under the License. */ -#ifndef NEURAL_NETWORK_RUNTIME_EXECUTION_PLAN_H -#define NEURAL_NETWORK_RUNTIME_EXECUTION_PLAN_H +#ifndef NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H +#define NEURAL_NETWORK_RUNTIME_TENSOR_DESC_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 namespace OHOS { namespace NeuralNetworkRuntime { -class ExecutionPlan { +class TensorDesc{ 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); + 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 Run(const std::vector>& inputTensors, - std::vector>& outputTensors); + 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; - std::shared_ptr GetInputDevice() const; - std::shared_ptr GetOutputDevice() const; private: - std::shared_ptr m_preparedModel {nullptr}; - std::shared_ptr m_device {nullptr}; + 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 \ No newline at end of file +} // 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/validation.cpp b/frameworks/native/validation.cpp index d451601..6f87bcf 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 { @@ -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..1f13751 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_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/kits/c/neural_network_core.h b/interfaces/kits/c/neural_network_core.h index a9312f6..f6da013 100644 --- a/interfaces/kits/c/neural_network_core.h +++ b/interfaces/kits/c/neural_network_core.h @@ -276,7 +276,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc* tensorDesc, const char* name); +OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char *name); /** * @brief Get name of a tensorDesc. @@ -293,7 +293,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc* tensorDesc, const char* * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc* tensorDesc, const char** name); +OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const char **name); /** * @brief Set data type of a tensorDesc. @@ -309,7 +309,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc* tensorDesc, const * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc* tensorDesc, OH_NN_DataType dataType); +OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_DataType dataType); /** * @brief Get data type of a tensorDesc. @@ -325,7 +325,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc* tensorDesc, OH_NN_Da * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc* tensorDesc, OH_NN_DataType* dataType); +OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH_NN_DataType *dataType); /** * @brief Set shape of a tensorDesc. @@ -342,9 +342,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc* tensorDesc, OH * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc* tensorDesc, - const int32_t* shape, - size_t shapeNum); +OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeNum); /** * @brief Get shape of a tensorDesc. @@ -362,7 +360,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc* tensorDesc, * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc* tensorDesc, int32_t** shape, size_t* shapeNum); +OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeNum); /** * @brief Set format of a tensorDesc. @@ -378,7 +376,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc* tensorDesc, int32 * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc* tensorDesc, OH_NN_Format format); +OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format); /** * @brief Get format of a tensorDesc. @@ -394,7 +392,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc* tensorDesc, OH_NN_Form * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc* tensorDesc, OH_NN_Format* format); +OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_NN_Format *format); /** * @brief Get element number of a tensorDesc. @@ -411,7 +409,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc* tensorDesc, OH_N * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetElementNum(const NN_TensorDesc* tensorDesc, size_t* elementNum); +OH_NN_ReturnCode OH_NNTensorDesc_GetElementNum(const NN_TensorDesc *tensorDesc, size_t *elementNum); /** * @brief Get byte size of a tensorDesc. @@ -428,42 +426,42 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetElementNum(const NN_TensorDesc* tensorDesc, * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc* tensorDesc, size_t* byteSize); +OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, size_t *byteSize); /** * @brief Creates an instance of the {@link NN_Tensor} type. * * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is calculated by {@link OH_NNTensorDesc_GetByteSize} is allocated. * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * desc must be provided, if it is a null pointer, the method returns an error code. \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 created by this method. desc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance created by this method. tensorDesc will also be released. \n * * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. - * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @return Returns the pointer to a {@link NN_Tensor} instance. * @since 11 * @version 1.0 */ -NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc* desc); +NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); /** * @brief Creates an instance of the {@link NN_Tensor} type. * * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is specified by size is allocated. * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * desc must be provided, if it is a null pointer, the method returns an error code. \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 created by this method. desc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance created by this method. tensorDesc will also be released. \n * * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. - * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param size Size of tensor data that need to be allocated. * @return Returns the pointer to a {@link NN_Tensor} instance. * @since 11 * @version 1.0 */ -NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc* desc, size_t size); +NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc, size_t size); /** * @brief Creates an instance of the {@link NN_Tensor} type. @@ -472,14 +470,14 @@ NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc* desc, size * When you call the {@link OH_NNTensor_DestroyTensor} method to release the tensor created by this method, the data memory is not released. \n * * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * desc must be provided, if it is a null pointer, the method returns an error code. + * tensorDesc must be provided, if it is a null pointer, the method returns an error code. * fd, size and offset come from another {@link NN_Tensor} instance. (size - offset) must be greater than or - * equal to the byte size obtained by the {@link OH_NNTensorDesc_GetByteSize} in desc. \n + * equal to the byte size obtained by the {@link OH_NNTensorDesc_GetByteSize} in tensorDesc. \n * - * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance created by this method. desc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance created by this method. tensorDesc will also be released. \n * * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. - * @param desc Pointer to the {@link NN_TensorDesc} instance. + * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param fd Fd comes from another {@link NN_Tensor} instance. * @param size Size comes from another {@link NN_Tensor} instance. * @param offset Offset comes from another {@link NN_Tensor} instance. @@ -488,7 +486,7 @@ NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc* desc, size * @version 1.0 */ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, - NN_TensorDesc* desc, + NN_TensorDesc *tensorDesc, int fd, size_t size, size_t offset); @@ -508,7 +506,7 @@ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor** tensor); +OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor); /** * @brief Get {@link NN_TensorDesc} instance of a tensor. @@ -523,7 +521,7 @@ OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor** tensor); * @since 11 * @version 1.0 */ -NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor* tensor); +NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor); /** * @brief Get the data buffer of a tensor. @@ -537,7 +535,7 @@ NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor* tensor); * @since 11 * @version 1.0 */ -void* OH_NNTensor_GetDataBuffer(const NN_Tensor* tensor); +void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); /** * @brief Get the data size of a tensor. @@ -553,7 +551,7 @@ void* OH_NNTensor_GetDataBuffer(const NN_Tensor* tensor); * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor* tensor, size_t* size); +OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); /** * @brief Get the data fd of a tensor. @@ -569,7 +567,7 @@ OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor* tensor, size_t* size); * @since 11 * @version 1.0 */ -OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor* tensor, int* fd); +OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); /** * @brief Get the data offset of a tensor. @@ -585,7 +583,7 @@ OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor* tensor, int* fd); * @since 11 * @version 1.0@ */ -OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor* tensor, size_t* offset); +OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t *offset); /** * @brief Creates an executor instance of the {@link OH_NNExecutor} type. @@ -650,11 +648,11 @@ NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index); -NN_TensorDesc* OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, - size_t index, - size_t *minInputDims, - size_t *maxInputDims, - size_t *shapeNum); +OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, + size_t index, + size_t *minInputDims, + size_t *maxInputDims, + size_t *shapeNum); OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); diff --git a/interfaces/kits/c/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime.h index ee0de32..3076f36 100644 --- a/interfaces/kits/c/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime.h @@ -28,7 +28,7 @@ * @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 coonstruct models. + * to construct models. * Note: Currently, the APIs of Neural Network Runtime do not support multi-thread calling. \n * * @library libneural_network_runtime.so -- Gitee From 7f8482a52c5f15a7be52f7273331165943b4ede6 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Tue, 5 Dec 2023 14:21:45 +0800 Subject: [PATCH 05/51] v2-1205 --- frameworks/native/executor.h | 16 +- frameworks/native/neural_network_core.cpp | 489 +++++++++++----------- frameworks/native/nnexecutor.cpp | 53 ++- frameworks/native/nnexecutor.h | 16 +- interfaces/kits/c/neural_network_core.h | 10 +- 5 files changed, 292 insertions(+), 292 deletions(-) diff --git a/frameworks/native/executor.h b/frameworks/native/executor.h index fdd68fe..4c9eb84 100644 --- a/frameworks/native/executor.h +++ b/frameworks/native/executor.h @@ -30,15 +30,15 @@ public: virtual ~Executor() = default; virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, - size_t* minInputDims, - size_t* maxInputDims, - size_t* shapeNum) = 0; - virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) = 0; + 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() = 0; - virtual size_t GetOutputNum() = 0; - virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) = 0; - virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) = 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; diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index b727d07..d98fb63 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.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 @@ -15,6 +15,7 @@ #include "interfaces/kits/c/neural_network_core.h" #include "common/log.h" +#include "executor.h" #include "tensor.h" #include @@ -339,7 +340,7 @@ NNRT_API OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor) std::shared_ptr backend = backendManager.GetBackend(backendName); if (backend == nullptr) { LOGE("OH_NNTensor_Destroy failed, passed invalid backend name %{public}s.", backendName.c_str()); - return NNCORE_NULL_PTR; + return OH_NN_NULL_PTR; } ret = backend->DestroyTensor(tensorImpl); @@ -434,256 +435,234 @@ NNRT_API OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t return OH_NN_SUCCESS; } -// NNRT_API NNCore_Executor* OH_NNCore_ConstructExecutor(const NNCore_Compiled* compiled) -// { -// if (compiled == nullptr) { -// LOGE("OH_NNCore_ConstructExecutor failed, compiled is nullptr."); -// return nullptr; -// } - -// const Compiled* compiledImpl = reinterpret_cast(compiled); -// NNCore_Executor* executor = nullptr; -// OH_NN_ReturnCode returnCode = compiledImpl->CreateExecutor(&executor); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_ConstructExecutor failed, failed to create executor."); -// return nullptr; -// } -// return executor; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_DestroyExecutor(NNCore_Executor** executor) -// { -// if (executor == nullptr) { -// LOGE("OH_NNCore_DestroyExecutor failed, executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (*executor == nullptr) { -// LOGE("OH_NNCore_DestroyExecutor failed, *executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Executor* executorImpl = reinterpret_cast(*executor); -// std::string backendName; -// OH_NN_ReturnCode returnCode = executorImpl->GetBackendName(backendName); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_DestroyExecutor failed, failed to get backend name from tensorDesc."); -// return returnCode; -// } - -// BackendManager& backendManager = BackendManager::GetInstance(); -// std::shared_ptr backend = backendManager.GetBackend(backendName); -// if (backend == nullptr) { -// LOGE("OH_NNCore_DestroyExecutor failed, failed to get backend of %{public}s.", backendName.c_str()); -// return NNCORE_NULL_PTR; -// } -// returnCode = backend->DestroyExecutor(executorImpl); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_DestroyExecutor failed, failed to destroy executor."); -// return returnCode; -// } -// *executor = nullptr; -// return OH_NN_SUCCESS; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_SetExecutorOnRunDone(NNCore_Executor* executor, NNCore_OnRunDone onRunDone) -// { -// if (executor == nullptr) { -// LOGE("OH_NNCore_SetExecutorOnRunDone failed, executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (onRunDone == nullptr) { -// LOGE("OH_NNCore_SetExecutorOnRunDone failed, onRunDone is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Executor* executorImpl = reinterpret_cast(executor); -// return executorImpl->SetOnRunDone(onRunDone); -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_SetExecutorOnServiceDied( -// NNCore_Executor* executor, NNCore_OnServiceDied onServiceDied) -// { -// if (executor == nullptr) { -// LOGE("OH_NNCore_SetExecutorOnServiceDied failed, executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (onServiceDied == nullptr) { -// LOGE("OH_NNCore_SetExecutorOnServiceDied failed, onServiceDied is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Executor* executorImpl = reinterpret_cast(executor); -// return executorImpl->SetOnServiceDied(onServiceDied); -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_ExecutorRunSync(NNCore_Executor* executor, NN_Tensor* inputTensor[], -// size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum) -// { -// if (executor == nullptr) { -// LOGE("NNCore_ExecutorRunSync failed, executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (inputTensor == nullptr) { -// LOGE("NNCore_ExecutorRunSync failed, inputTensor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (inputNum == 0) { -// LOGE("NNCore_ExecutorRunSync failed, inputNum is 0."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (outputTensor == nullptr) { -// LOGE("NNCore_ExecutorRunSync failed, outputTensor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (outputNum == 0) { -// LOGE("NNCore_ExecutorRunSync failed, outputNum is 0."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Executor* executorImpl = reinterpret_cast(executor); -// return executorImpl->RunSync(inputTensor, inputNum, outputTensor, outputNum); -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_ExecutorRunAsync(NNCore_Executor* executor, NN_Tensor* inputTensor[], -// size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum, int32_t timeout, void* userData) -// { -// if (executor == nullptr) { -// LOGE("NNCore_ExecutorRunAsync failed, executor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (inputTensor == nullptr) { -// LOGE("NNCore_ExecutorRunAsync failed, inputTensor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (inputNum == 0) { -// LOGE("NNCore_ExecutorRunAsync failed, inputNum is 0."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (outputTensor == nullptr) { -// LOGE("NNCore_ExecutorRunAsync failed, outputTensor is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (outputNum == 0) { -// LOGE("NNCore_ExecutorRunAsync failed, outputNum is 0."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (userData == 0) { -// LOGE("NNCore_ExecutorRunAsync failed, userData is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Executor* executorImpl = reinterpret_cast(executor); -// return executorImpl->RunAsync(inputTensor, inputNum, outputTensor, outputNum, timeout, userData); -// } - -// NNRT_API NNCore_Options* OH_NNCore_CreateOptions(const char* backendName) -// { -// if (backendName == nullptr) { -// LOGE("OH_NNCore_CreateOptions failed, backendName is nullptr."); -// return nullptr; -// } - -// BackendManager& manager = BackendManager::GetInstance(); -// std::shared_ptr backend = manager.GetBackend(backendName); -// if (backend == nullptr) { -// LOGE("OH_NNCore_CreateOptions failed, fail to get backend."); -// return nullptr; -// } - -// Options* innerOptions = backend->CreateOptions(); -// if (innerOptions == nullptr) { -// LOGE("OH_NNCore_CreateOptions failed, fail to create options."); -// return nullptr; -// } - -// NNCore_Options* options = reinterpret_cast(innerOptions); -// return options; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_DestroyOptions(NNCore_Options** options) -// { -// if (options == nullptr) { -// LOGE("OH_NNCore_DestroyOptions failed, options is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } -// if (*options == nullptr) { -// LOGE("OH_NNCore_DestroyOptions failed, *options is nullptr."); -// return OH_NN_INVALID_PARAMETER; -// } - -// Options* optionsImpl = reinterpret_cast(*options); - -// std::string backendName; -// OH_NN_ReturnCode returnCode = optionsImpl->GetBackendName(backendName); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_DestroyOptions failed, failed to get backend name from options."); -// return returnCode; -// } - -// BackendManager& backendManager = BackendManager::GetInstance(); -// std::shared_ptr backend = backendManager.GetBackend(backendName); -// if (backend == nullptr) { -// LOGE("OH_NNCore_DestroyOptions failed, failed to get backend of %s.", backendName.c_str()); -// return NNCORE_NULL_PTR; -// } - -// returnCode = backend->DestroyOptions(optionsImpl); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_DestroyOptions failed, failed to destroy options."); -// return returnCode; -// } - -// *options = nullptr; -// return OH_NN_SUCCESS; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_SetPriority(NNCore_Options* options, NNCore_Priority priority) -// { -// if (options == nullptr) { -// LOGE("OH_NNCore_SetPriority failed, input options is nullptr;"); -// return OH_NN_INVALID_PARAMETER; -// } - -// Options* optionsImpl = reinterpret_cast(options); -// OH_NN_ReturnCode returnCode = optionsImpl->SetPriority(priority); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_SetPriority failed, failed to set priority."); -// return returnCode; -// } - -// return OH_NN_SUCCESS; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_SetPerformanceMode(NNCore_Options* options, NNCore_PerformanceMode performanceMode) -// { -// if (options == nullptr) { -// LOGE("OH_NNCore_SetPerformanceMode failed, input options is nullptr;"); -// return OH_NN_INVALID_PARAMETER; -// } - -// Options* optionsImpl = reinterpret_cast(options); -// OH_NN_ReturnCode returnCode = optionsImpl->SetPerformanceMode(performanceMode); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_SetPerformanceMode failed, failed to set performance mode."); -// return returnCode; -// } - -// return OH_NN_SUCCESS; -// } - -// NNRT_API OH_NN_ReturnCode OH_NNCore_SetEnableFloat16(NNCore_Options* options, bool enableFloat16) -// { -// if (options == nullptr) { -// LOGE("OH_NNCore_SetEnableFloat16 failed, input options is nullptr;"); -// return OH_NN_INVALID_PARAMETER; -// } - -// Options* optionsImpl = reinterpret_cast(options); -// OH_NN_ReturnCode returnCode = optionsImpl->SetEnableFp16(enableFloat16); -// if (returnCode != OH_NN_SUCCESS) { -// LOGE("OH_NNCore_SetEnableFloat16 failed, failed to set fp16 enabled."); -// return returnCode; -// } - -// 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; + } + + // todo + return nullptr; +} + +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; + } + + // todo + /*Executor *executorImpl = reinterpret_cast(*executor); + size_t deviceID = executorImpl->GetDeviceID(); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); + if (backend == nullptr) { + LOGE("OH_NNExecutor_Destroy failed, failed to get backend of %{public}s.", backendName.c_str()); + return; + } + 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_GetInputNum(const OH_NNExecutor *executor, size_t *inputNum) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetInputNum failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (inputNum == nullptr) { + LOGE("OH_NNExecutor_GetInputNum failed, inputNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Executor *executorImpl = reinterpret_cast(executor); + *inputNum = executorImpl->GetInputNum(); + return OH_NN_SUCCESS; +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputNum(const OH_NNExecutor *executor, size_t *outputNum) +{ + if (executor == nullptr) { + LOGE("OH_NNExecutor_GetOutputNum failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputNum == nullptr) { + LOGE("OH_NNExecutor_GetOutputNum failed, outputNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + const Executor *executorImpl = reinterpret_cast(executor); + *outputNum = 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 *shapeNum) +{ + 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 (shapeNum == nullptr) { + LOGE("OH_NNExecutor_GetInputDimRange failed, shapeNum is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + + const Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->GetInputDimRange(index, minInputDims, maxInputDims, shapeNum); +} + +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 inputNum, NN_Tensor *outputTensor[], size_t outputNum) +{ + 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 (inputNum == 0) { + LOGE("OH_NNExecutor_RunSync failed, inputNum is 0."); + return OH_NN_INVALID_PARAMETER; + } + if (outputTensor == nullptr) { + LOGE("OH_NNExecutor_RunSync failed, outputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputNum == 0) { + LOGE("OH_NNExecutor_RunSync failed, outputNum is 0."); + return OH_NN_INVALID_PARAMETER; + } + + Executor *executorImpl = reinterpret_cast(executor); + return executorImpl->RunSync(inputTensor, inputNum, outputTensor, outputNum); +} + +NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Tensor* inputTensor[], + size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum, 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 (inputNum == 0) { + LOGE("OH_NNExecutor_RunAsync failed, inputNum is 0."); + return OH_NN_INVALID_PARAMETER; + } + if (outputTensor == nullptr) { + LOGE("OH_NNExecutor_RunAsync failed, outputTensor is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + if (outputNum == 0) { + LOGE("OH_NNExecutor_RunAsync failed, outputNum 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, inputNum, outputTensor, outputNum, timeout, userData); +} \ No newline at end of file diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 75e3bf2..3b8d7ec 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -35,33 +35,52 @@ NNExecutor::NNExecutor(size_t deviceID, std::shared_ptr device, std::sha } OH_NN_ReturnCode NNExecutor::GetInputDimRange( - size_t inputIndex, size_t* minInputDims, size_t* maxInputDims, size_t* shapeNum) + 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; } - OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(m_minInputDims, m_maxInputDims); + 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; } - std::vector minInputDimVec = m_minInputDims[inputIndex]; - std::vector maxInputDimVec = m_maxInputDims[inputIndex]; + 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; + } + + 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 = static_cast(minInputDimVec.data()); - maxInputDims = static_cast(maxInputDimVec.data()); + *minInputDims = static_cast(minInputDimVec.data()); + *maxInputDims = static_cast(maxInputDimVec.data()); return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) +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."); @@ -78,17 +97,17 @@ OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shap return OH_NN_SUCCESS; } -size_t NNExecutor::GetInputNum() +size_t NNExecutor::GetInputNum() const { return m_inputTensorDescs.size(); } -size_t NNExecutor::GetOutputNum() +size_t NNExecutor::GetOutputNum() const { return m_outputTensorDescs.size(); } -NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) +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."); @@ -107,7 +126,7 @@ NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) return reinterpret_cast(tensorDescImpl); } -NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) +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."); @@ -211,19 +230,21 @@ size_t NNExecutor::GetDeviceID() OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize) { - OH_NN_ReturnCode oldRet = m_preparedModel->GetInputDimRanges(m_minInputDims, m_maxInputDims); + 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 != m_minInputDims.size()) { - LOGE("NNExecutor::CheckInputDimRanges failed, size of m_minInputDims is not equal to inputSize."); + if (inputSize != minInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of minInputDims is not equal to inputSize."); return OH_NN_INVALID_PARAMETER; } - if (inputSize != m_maxInputDims.size()) { - LOGE("NNExecutor::CheckInputDimRanges failed, size of m_maxInputDims is not equal to inputSize."); + if (inputSize != maxInputDims.size()) { + LOGE("NNExecutor::CheckInputDimRanges failed, size of maxInputDims is not equal to inputSize."); return OH_NN_INVALID_PARAMETER; } diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index 95af79e..f54bb26 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -32,15 +32,15 @@ public: virtual ~NNExecutor() = default; virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, - size_t* minInputDims, - size_t* maxInputDims, - size_t* shapeNum) override; - virtual OH_NN_ReturnCode GetOutputShape(uint32_t outputIndex, int32_t** shape, uint32_t* shapeNum) override; + 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() override; - virtual size_t GetOutputNum() override; - virtual NN_TensorDesc* CreateInputTensorDesc(size_t index) override; - virtual NN_TensorDesc* CreateOutputTensorDesc(size_t index) 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; diff --git a/interfaces/kits/c/neural_network_core.h b/interfaces/kits/c/neural_network_core.h index f6da013..d67f86e 100644 --- a/interfaces/kits/c/neural_network_core.h +++ b/interfaces/kits/c/neural_network_core.h @@ -85,9 +85,9 @@ OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compil size_t modelSize); OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, - const char *configNames, - const void *configValues, - const size_t configValueSizes); + const char *configName, + const void *configValue, + const size_t configValueSize); /** * @brief Specifies the device for model compilation and computing. @@ -650,8 +650,8 @@ NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executo OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, size_t index, - size_t *minInputDims, - size_t *maxInputDims, + size_t **minInputDims, + size_t **maxInputDims, size_t *shapeNum); OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); -- Gitee From 1d3b210bdd3614d2ae595c69046e1d451a3255d9 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 14:27:23 +0800 Subject: [PATCH 06/51] update base class head file --- frameworks/native/backend.h | 50 +++++++++++++++++ frameworks/native/compilation.h | 54 +++++++++++++++++++ .../kits/c/neural_network_runtime_type.h | 2 +- 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 frameworks/native/backend.h create mode 100644 frameworks/native/compilation.h diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h new file mode 100644 index 0000000..097bae1 --- /dev/null +++ b/frameworks/native/backend.h @@ -0,0 +1,50 @@ +/* + * 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_H +#define NEURAL_NETWORK_CORE_BACKEND_H + +#include +#include + +#include "compiler.h" +#include "compiled.h" +#include "executor.h" +#include "options.h" +#include "tensor.h" +#include "v2_0/neural_network_core_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class Backend { +public: + Backend() = default; + virtual ~Backend() = default; + + virtual size_t GetBackendID() const = 0; + virtual OH_NN_ReturnCode GetBackendName(std::string& name); + virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType); + virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) = 0; + + virtual Executor* CreateExecutor() = 0; + virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; + + virtual Tensor* CreateTensor( + const std::string& backendName, OHOS::NeuralNetworkRuntime::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/compilation.h b/frameworks/native/compilation.h new file mode 100644 index 0000000..d6c45b3 --- /dev/null +++ b/frameworks/native/compilation.h @@ -0,0 +1,54 @@ +/* + * 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_RUNTIME_COMPILATION_H +#define NEURAL_NETWORK_RUNTIME_COMPILATION_H + +#include "inner_model.h" +#include "execution_plan.h" + +#include "device.h" +#include "cpp_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class Compilation { +public: + Compilation() = default; + Compilation(const void* model); + Compilation(const std::string& filePath); + Compilation(const void* modelData, size_t modelSize); + virtual ~Compilation() = default; + + 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 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 GetExtensionConfig(const char** configNames, + const void** configValues, + const size_t* configValueSizes, + const size_t configNum) = 0; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS + +#endif // NEURAL_NETWORK_RUNTIME_COMPILATION_H \ No newline at end of file diff --git a/interfaces/kits/c/neural_network_runtime_type.h b/interfaces/kits/c/neural_network_runtime_type.h index 7aadb48..874da01 100644 --- a/interfaces/kits/c/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime_type.h @@ -132,7 +132,7 @@ typedef enum { /** Invalid file. */ OH_NN_INVALID_FILE = 6, /** A hardware error occurs, for example, HDL service crash. */ - OH_NN_UNAVALIDABLE_DEVICE = 7, + OH_NN_UNAVAILABLE_DEVICE = 7, /** Invalid path. */ OH_NN_INVALID_PATH = 8 } OH_NN_ReturnCode; -- Gitee From c2b4cad1de7c8d9410526e47b91a30ce501406af Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 14:29:51 +0800 Subject: [PATCH 07/51] update bakend.h --- frameworks/native/backend.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index 097bae1..188d1fa 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -34,9 +34,9 @@ public: virtual ~Backend() = default; virtual size_t GetBackendID() const = 0; - virtual OH_NN_ReturnCode GetBackendName(std::string& name); - virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType); - virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) = 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; virtual Executor* CreateExecutor() = 0; virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; -- Gitee From 98e14acc509ad86c43d8397101de08e6a16d90dc Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 16:26:43 +0800 Subject: [PATCH 08/51] update compilation head file --- frameworks/native/compilation.h | 38 +++++------------------- frameworks/native/compiler.h | 52 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 frameworks/native/compiler.h diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index d6c45b3..8aab354 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -15,40 +15,18 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H #define NEURAL_NETWORK_RUNTIME_COMPILATION_H -#include "inner_model.h" -#include "execution_plan.h" - -#include "device.h" -#include "cpp_type.h" +#include +#include "neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { -class Compilation { -public: - Compilation() = default; - Compilation(const void* model); - Compilation(const std::string& filePath); - Compilation(const void* modelData, size_t modelSize); - virtual ~Compilation() = default; - - 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 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 GetExtensionConfig(const char** configNames, - const void** configValues, - const size_t* configValueSizes, - const size_t configNum) = 0; +struct OH_NNCompilation { + size_t backendId; + void* nnModel; + char* offlineModelPath; + std::pair offlineModelBuffer; }; } // namespace NeuralNetworkRuntime -} // namespace OHOS +} #endif // NEURAL_NETWORK_RUNTIME_COMPILATION_H \ No newline at end of file diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h new file mode 100644 index 0000000..1ece4ef --- /dev/null +++ b/frameworks/native/compiler.h @@ -0,0 +1,52 @@ +/* + * 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_RUNTIME_COMPILER_H +#define NEURAL_NETWORK_RUNTIME_COMPILER_H + +#include "neural_network_runtime.h" +#include "cpp_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class Compiler { +public: + Compiler() = default; + Compiler(const void* model); + Compiler(const std::string& filePath); + Compiler(const void* modelData, size_t modelSize); + 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 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 AddExtensionConfig(const char* configName, + const void* configValue, + const size_t configValueSizes) = 0; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS + +#endif // NEURAL_NETWORK_RUNTIME_COMPILER_H \ No newline at end of file -- Gitee From 54969ecc314d7ea62d94d571bfe13ffd3e9e22e2 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 16:40:33 +0800 Subject: [PATCH 09/51] update backend/compilation --- frameworks/native/backend.h | 3 +++ frameworks/native/compilation.h | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index 188d1fa..03e6a8e 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -38,6 +38,9 @@ public: virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; + virtual Compiler* CreateCompiler() = 0; + virtual OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) = 0; + virtual Executor* CreateExecutor() = 0; virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 8aab354..d39b51b 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -15,16 +15,21 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H #define NEURAL_NETWORK_RUNTIME_COMPILATION_H -#include +#include "compiler.h" #include "neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { struct OH_NNCompilation { - size_t backendId; + size_t deviceId; void* nnModel; char* offlineModelPath; std::pair offlineModelBuffer; + char* cachePath; + uint32_t cacheVersion; + OH_NN_Priority priority; + OH_NN_PerformanceMode performance; + Compiler* compiler; }; } // namespace NeuralNetworkRuntime } -- Gitee From 05be32747c6caab7944cd0216c10f34adfa39c9d Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 18:41:27 +0800 Subject: [PATCH 10/51] update backend.h --- frameworks/native/backend.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index 03e6a8e..c6c207b 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -33,8 +33,9 @@ public: 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 GetVendorName(std::string& name) = 0; + virtual OH_NN_ReturnCode GetVersion(std::string& version) = 0; virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; -- Gitee From ac98c519ef8200ceb16f84c873f5c198e6166f29 Mon Sep 17 00:00:00 2001 From: maoyong Date: Tue, 5 Dec 2023 22:03:11 +0800 Subject: [PATCH 11/51] update backend/compilation --- frameworks/native/backend.h | 6 +----- frameworks/native/compilation.h | 14 +++++++++++++- interfaces/kits/c/neural_network_runtime_type.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index c6c207b..62562b7 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -20,11 +20,9 @@ #include #include "compiler.h" -#include "compiled.h" #include "executor.h" -#include "options.h" #include "tensor.h" -#include "v2_0/neural_network_core_type.h" +#include "neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -34,8 +32,6 @@ public: virtual ~Backend() = default; virtual OH_NN_ReturnCode GetBackendName(std::string& name) const = 0; - virtual OH_NN_ReturnCode GetVendorName(std::string& name) = 0; - virtual OH_NN_ReturnCode GetVersion(std::string& version) = 0; virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index d39b51b..1d9d3a7 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -15,13 +15,24 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H #define NEURAL_NETWORK_RUNTIME_COMPILATION_H +#include +#include + #include "compiler.h" #include "neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { +struct ExtensionConfig +{ + char *configName; + void *configValue; + size_t configValueSize; +}; + + struct OH_NNCompilation { - size_t deviceId; + size_t backendId; void* nnModel; char* offlineModelPath; std::pair offlineModelBuffer; @@ -30,6 +41,7 @@ struct OH_NNCompilation { OH_NN_Priority priority; OH_NN_PerformanceMode performance; Compiler* compiler; + std::vector configs; }; } // namespace NeuralNetworkRuntime } diff --git a/interfaces/kits/c/neural_network_runtime_type.h b/interfaces/kits/c/neural_network_runtime_type.h index 874da01..7aadb48 100644 --- a/interfaces/kits/c/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime_type.h @@ -132,7 +132,7 @@ typedef enum { /** Invalid file. */ OH_NN_INVALID_FILE = 6, /** A hardware error occurs, for example, HDL service crash. */ - OH_NN_UNAVAILABLE_DEVICE = 7, + OH_NN_UNAVALIDABLE_DEVICE = 7, /** Invalid path. */ OH_NN_INVALID_PATH = 8 } OH_NN_ReturnCode; -- Gitee From d6fa123d54ee8369030bebf255019ebb66fbe87e Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 6 Dec 2023 10:21:32 +0800 Subject: [PATCH 12/51] v2-1206 --- frameworks/native/backend.h | 6 +- frameworks/native/compilation.h | 14 +-- frameworks/native/cpp_type.h | 2 +- frameworks/native/device.h | 2 +- frameworks/native/device_manager.h | 2 +- frameworks/native/executor.h | 4 +- frameworks/native/hdi_prepared_model_v1_0.cpp | 108 +++++++++++++++++ frameworks/native/hdi_prepared_model_v1_0.h | 5 + frameworks/native/hdi_prepared_model_v2_0.cpp | 110 ++++++++++++++++++ frameworks/native/hdi_prepared_model_v2_0.h | 5 + frameworks/native/inner_model.h | 2 +- frameworks/native/neural_network_core.cpp | 80 ++++++------- frameworks/native/nn_tensor.h | 2 +- frameworks/native/nnexecutor.cpp | 26 ++--- frameworks/native/nnexecutor.h | 8 +- frameworks/native/nntensor.cpp | 4 +- frameworks/native/nntensor.h | 6 +- .../native/ops/strided_slice_builder.cpp | 2 +- frameworks/native/ops_builder.h | 2 +- frameworks/native/ops_registry.h | 2 +- frameworks/native/prepared_model.h | 7 +- frameworks/native/tensor.h | 2 +- frameworks/native/tensor_desc.h | 2 +- frameworks/native/transform.h | 2 +- frameworks/native/validation.h | 2 +- .../c/neural_network_runtime_inner.h | 2 +- interfaces/kits/c/BUILD.gn | 14 ++- .../libneural_network_runtime.ndk.json | 0 .../neural_network_core.h | 32 ++--- .../neural_network_runtime.h | 7 +- .../neural_network_runtime_compat.h | 0 .../neural_network_runtime_type.h | 2 +- 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 +- .../neural_network_runtime_test.h | 2 +- .../neural_network_runtime_test.h | 2 +- testdemo/demo.cpp | 2 +- 39 files changed, 352 insertions(+), 126 deletions(-) rename interfaces/kits/c/{ => neural_network_runtime}/libneural_network_runtime.ndk.json (100%) rename interfaces/kits/c/{ => neural_network_runtime}/neural_network_core.h (96%) rename interfaces/kits/c/{ => neural_network_runtime}/neural_network_runtime.h (98%) rename interfaces/kits/c/{ => neural_network_runtime}/neural_network_runtime_compat.h (100%) rename interfaces/kits/c/{ => neural_network_runtime}/neural_network_runtime_type.h (99%) diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index 62562b7..c6c207b 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -20,9 +20,11 @@ #include #include "compiler.h" +#include "compiled.h" #include "executor.h" +#include "options.h" #include "tensor.h" -#include "neural_network_runtime_type.h" +#include "v2_0/neural_network_core_type.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -32,6 +34,8 @@ public: virtual ~Backend() = default; virtual OH_NN_ReturnCode GetBackendName(std::string& name) const = 0; + virtual OH_NN_ReturnCode GetVendorName(std::string& name) = 0; + virtual OH_NN_ReturnCode GetVersion(std::string& version) = 0; virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 1d9d3a7..d39b51b 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -15,24 +15,13 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILATION_H #define NEURAL_NETWORK_RUNTIME_COMPILATION_H -#include -#include - #include "compiler.h" #include "neural_network_runtime.h" namespace OHOS { namespace NeuralNetworkRuntime { -struct ExtensionConfig -{ - char *configName; - void *configValue; - size_t configValueSize; -}; - - struct OH_NNCompilation { - size_t backendId; + size_t deviceId; void* nnModel; char* offlineModelPath; std::pair offlineModelBuffer; @@ -41,7 +30,6 @@ struct OH_NNCompilation { OH_NN_Priority priority; OH_NN_PerformanceMode performance; Compiler* compiler; - std::vector configs; }; } // namespace NeuralNetworkRuntime } 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 9d74e59..efe380c 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.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" #include "cpp_type.h" #include "tensor_desc.h" #include "prepared_model.h" diff --git a/frameworks/native/device_manager.h b/frameworks/native/device_manager.h index 4d8b9fb..0dcef19 100644 --- a/frameworks/native/device_manager.h +++ b/frameworks/native/device_manager.h @@ -24,7 +24,7 @@ #include #include "device.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/executor.h b/frameworks/native/executor.h index 4c9eb84..9671ca9 100644 --- a/frameworks/native/executor.h +++ b/frameworks/native/executor.h @@ -20,7 +20,7 @@ #include #include "tensor_desc.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 { @@ -52,7 +52,7 @@ public: size_t outputSize, int32_t timeout, void* userData) = 0; - virtual size_t GetDeviceID() = 0; + virtual size_t GetBackendID() = 0; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/hdi_prepared_model_v1_0.cpp b/frameworks/native/hdi_prepared_model_v1_0.cpp index d697ea3..e239107 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) @@ -160,5 +226,47 @@ OH_NN_ReturnCode HDIPreparedModelV1_0::Run(const std::vector& inputs, 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_UNAVALIDABLE_DEVICE; + } + + return OH_NN_SUCCESS; +} } // namespace NeuralNetworkRuntime } // OHOS \ No newline at end of file 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..249af8b 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.cpp +++ b/frameworks/native/hdi_prepared_model_v2_0.cpp @@ -92,6 +92,71 @@ V2_0::IOTensor TransIOTensor(const IOTensor& tensor) return iTensor; } + +OH_NN_ReturnCode TransIOTensor(const NNCore_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 NNTensor* 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) @@ -164,6 +229,51 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, 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_UNAVALIDABLE_DEVICE, "Run model failed"); + } + if (outputsDims.empty()) { + LOGE("Run failed, outputsDims is empty."); + return OH_NN_UNAVALIDABLE_DEVICE; + } + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode HDIPreparedModelV2_0::GetInputDimRanges(std::vector>& minInputDims, std::vector>& maxInputDims) { 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/inner_model.h b/frameworks/native/inner_model.h index 7deec70..62aab0b 100644 --- a/frameworks/native/inner_model.h +++ b/frameworks/native/inner_model.h @@ -22,7 +22,7 @@ #include "mindir.h" #include "ops_builder.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 { diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index d98fb63..9dca185 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "interfaces/kits/c/neural_network_core.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_core.h" #include "common/log.h" #include "executor.h" #include "tensor.h" @@ -112,7 +112,7 @@ NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tenso return tensorDescImpl->GetDataType(dataType); } -NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeNum) +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."); @@ -122,15 +122,15 @@ NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, co LOGE("OH_NNTensorDesc_SetShape failed, shape is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (shapeNum == 0) { - LOGE("OH_NNTensorDesc_SetShape failed, shapeNum is 0."); + 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, shapeNum); + return tensorDescImpl->SetShape(shape, shapeLength); } -NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeNum) +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."); @@ -144,13 +144,13 @@ NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDe LOGE("OH_NNTensorDesc_GetShape failed, *shape is not nullptr."); return OH_NN_INVALID_PARAMETER; } - if (shapeNum == nullptr) { - LOGE("OH_NNTensorDesc_GetShape failed, shapeNum is nullptr."); + 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, shapeNum); + return tensorDescImpl->GetShape(shape, shapeLength); } NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format) @@ -179,19 +179,19 @@ NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorD return tensorDescImpl->GetFormat(format); } -NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetElementNum(const NN_TensorDesc *tensorDesc, size_t *elementNum) +NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount) { if (tensorDesc == nullptr) { - LOGE("OH_NNTensorDesc_GetElementNum failed, tensorDesc is nullptr."); + LOGE("OH_NNTensorDesc_GetElementCount failed, tensorDesc is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (elementNum == nullptr) { - LOGE("OH_NNTensorDesc_GetElementNum failed, elementNum is nullptr."); + 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(elementNum); + return tensorDescImpl->GetElementNum(elementCount); } NNRT_API OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, size_t *byteSize) @@ -498,35 +498,35 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape( return executorImpl->GetOutputShape(outputIndex, shape, shapeLength); } -NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputNum(const OH_NNExecutor *executor, size_t *inputNum) +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputCount(const OH_NNExecutor *executor, size_t *inputCount) { if (executor == nullptr) { - LOGE("OH_NNExecutor_GetInputNum failed, executor is nullptr."); + LOGE("OH_NNExecutor_GetInputCount failed, executor is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (inputNum == nullptr) { - LOGE("OH_NNExecutor_GetInputNum failed, inputNum is nullptr."); + if (inputCount == nullptr) { + LOGE("OH_NNExecutor_GetInputCount failed, inputCount is nullptr."); return OH_NN_INVALID_PARAMETER; } const Executor *executorImpl = reinterpret_cast(executor); - *inputNum = executorImpl->GetInputNum(); + *inputCount = executorImpl->GetInputNum(); return OH_NN_SUCCESS; } -NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputNum(const OH_NNExecutor *executor, size_t *outputNum) +NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputCount(const OH_NNExecutor *executor, size_t *outputCount) { if (executor == nullptr) { - LOGE("OH_NNExecutor_GetOutputNum failed, executor is nullptr."); + LOGE("OH_NNExecutor_GetOutputCount failed, executor is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (outputNum == nullptr) { - LOGE("OH_NNExecutor_GetOutputNum failed, outputNum is nullptr."); + if (outputCount == nullptr) { + LOGE("OH_NNExecutor_GetOutputCount failed, outputCount is nullptr."); return OH_NN_INVALID_PARAMETER; } const Executor *executorImpl = reinterpret_cast(executor); - *outputNum = executorImpl->GetOutputNum(); + *outputCount = executorImpl->GetOutputNum(); return OH_NN_SUCCESS; } @@ -553,7 +553,7 @@ 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 *shapeNum) + size_t index, size_t **minInputDims, size_t **maxInputDims, size_t *shapeLength) { if (executor == nullptr) { LOGE("OH_NNExecutor_GetInputDimRange failed, executor is nullptr."); @@ -567,14 +567,14 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *ex LOGE("OH_NNExecutor_GetInputDimRange failed, maxInputDims is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (shapeNum == nullptr) { - LOGE("OH_NNExecutor_GetInputDimRange failed, shapeNum is nullptr."); + 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, shapeNum); + return executorImpl->GetInputDimRange(index, minInputDims, maxInputDims, shapeLength); } NNRT_API OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone) @@ -608,7 +608,7 @@ 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 inputNum, NN_Tensor *outputTensor[], size_t outputNum) + NN_Tensor *inputTensor[], size_t inputCount, NN_Tensor *outputTensor[], size_t outputCount) { if (executor == nullptr) { LOGE("OH_NNExecutor_RunSync failed, executor is nullptr."); @@ -618,25 +618,25 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, LOGE("OH_NNExecutor_RunSync failed, inputTensor is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (inputNum == 0) { - LOGE("OH_NNExecutor_RunSync failed, inputNum is 0."); + 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 (outputNum == 0) { - LOGE("OH_NNExecutor_RunSync failed, outputNum is 0."); + 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, inputNum, outputTensor, outputNum); + return executorImpl->RunSync(inputTensor, inputCount, outputTensor, outputCount); } NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Tensor* inputTensor[], - size_t inputNum, NN_Tensor* outputTensor[], size_t outputNum, int32_t timeout, void* userData) + 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."); @@ -646,16 +646,16 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Ten LOGE("OH_NNExecutor_RunAsync failed, inputTensor is nullptr."); return OH_NN_INVALID_PARAMETER; } - if (inputNum == 0) { - LOGE("OH_NNExecutor_RunAsync failed, inputNum is 0."); + 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 (outputNum == 0) { - LOGE("OH_NNExecutor_RunAsync failed, outputNum is 0."); + if (outputCount == 0) { + LOGE("OH_NNExecutor_RunAsync failed, outputCount is 0."); return OH_NN_INVALID_PARAMETER; } if (userData == 0) { @@ -664,5 +664,5 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Ten } Executor *executorImpl = reinterpret_cast(executor); - return executorImpl->RunAsync(inputTensor, inputNum, outputTensor, outputNum, timeout, userData); + return executorImpl->RunAsync(inputTensor, inputCount, outputTensor, outputCount, timeout, userData); } \ No newline at end of file diff --git a/frameworks/native/nn_tensor.h b/frameworks/native/nn_tensor.h index dc47d02..e5ea8dd 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -20,7 +20,7 @@ #include #include "cpp_type.h" -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include "interfaces/innerkits/c/neural_network_runtime_inner.h" namespace OHOS { diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 3b8d7ec..079713f 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -16,18 +16,16 @@ #include "nnexecutor.h" #include "nntensor.h" -// #include "nnbackend.h" -// #include "backend_manager.h" #include "common/log.h" #include "cpp_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -NNExecutor::NNExecutor(size_t deviceID, std::shared_ptr device, std::shared_ptr preparedModel, +NNExecutor::NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, std::vector> inputTensorDescs, std::vector> outputTensorDescs) { - m_deviceID = deviceID; + m_backendID = backendID; m_device = device; m_preparedModel = preparedModel; m_inputTensorDescs = inputTensorDescs; @@ -180,12 +178,12 @@ OH_NN_ReturnCode NNExecutor::RunSync(NN_Tensor* inputTensors[], size_t inputSize std::vector> outputsDims; std::vector isSufficientDataBuffer; - // todo - // auto oldRet = m_preparedModel->Run(inputTensorsVec, outputTensorsVec, outputsDims, isSufficientDataBuffer); - // if (oldRet != OH_NN_SUCCESS) { - // LOGE("NNExecutor::RunSync failed, failed to run in prepared model."); - // return OH_NN_FAILED; - // } + + 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. @@ -223,9 +221,9 @@ OH_NN_ReturnCode NNExecutor::RunAsync(NN_Tensor* inputTensors[], size_t inputSiz return OH_NN_OPERATION_FORBIDDEN; } -size_t NNExecutor::GetDeviceID() +size_t NNExecutor::GetBackendID() { - return m_deviceID; + return m_backendID; } OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize) @@ -251,8 +249,8 @@ OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size const NNTensor2_0* nnTensor = nullptr; OH_NN_ReturnCode ret {OH_NN_FAILED}; for (size_t i = 0; i < inputSize; ++i) { - const std::vector& minSingleInputDims = m_minInputDims[i]; - const std::vector& maxSingleInputDims = m_maxInputDims[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); diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index f54bb26..08c196f 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -24,7 +24,7 @@ namespace OHOS { namespace NeuralNetworkRuntime { class NNExecutor : public Executor { public: - NNExecutor(size_t deviceID, + NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, std::vector> inputTensorDescs, @@ -54,19 +54,17 @@ public: size_t outputSize, int32_t timeout, void* userData) override; - virtual size_t GetDeviceID() override; + virtual size_t GetBackendID() override; private: OH_NN_ReturnCode CheckInputDimRanges(NN_Tensor* inputTensors[], size_t inputSize); private: - size_t m_deviceID {0}; + size_t m_backendID {0}; std::shared_ptr m_device {nullptr}; std::shared_ptr m_preparedModel {nullptr}; std::vector> m_inputTensorDescs; std::vector> m_outputTensorDescs; - std::vector> m_minInputDims; - std::vector> m_maxInputDims; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index eb33b13..4b2a77e 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -17,7 +17,7 @@ #include "common/log.h" #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 { @@ -245,7 +245,7 @@ OH_NN_ReturnCode NNTensor2_0::ReleaseMemory() size_t NNTensor2_0::GetDeviceID() const { - return m_deviceID; + return m_backendID; } bool NNTensor2_0::CheckTensorData() const diff --git a/frameworks/native/nntensor.h b/frameworks/native/nntensor.h index c7f464d..c04cbc5 100644 --- a/frameworks/native/nntensor.h +++ b/frameworks/native/nntensor.h @@ -23,8 +23,8 @@ namespace OHOS { namespace NeuralNetworkRuntime { class NNTensor2_0 : public Tensor { public: - NNTensor2_0(size_t deviceID, TensorDesc* tensorDesc) : - m_deviceID(deviceID), m_tensorDesc(tensorDesc) {} + NNTensor2_0(size_t backendID, TensorDesc* tensorDesc) : + m_backendID(backendID), m_tensorDesc(tensorDesc) {} virtual ~NNTensor2_0(); OH_NN_ReturnCode CreateData() override; @@ -48,7 +48,7 @@ private: OH_NN_ReturnCode ReleaseMemory(); private: - size_t m_deviceID {0}; + size_t m_backendID {0}; TensorDesc* m_tensorDesc {nullptr}; void* m_data {nullptr}; int m_fd {0}; 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.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/tensor.h b/frameworks/native/tensor.h index 9e2776f..8cb2f47 100644 --- a/frameworks/native/tensor.h +++ b/frameworks/native/tensor.h @@ -24,7 +24,7 @@ namespace NeuralNetworkRuntime { class Tensor { public: Tensor() = default; - Tensor(const std::string& backendName, TensorDesc* tensorDesc); + Tensor(size_t backendID, TensorDesc* tensorDesc); virtual ~Tensor() = default; virtual OH_NN_ReturnCode CreateData() = 0; diff --git a/frameworks/native/tensor_desc.h b/frameworks/native/tensor_desc.h index 08cfc39..b16e379 100644 --- a/frameworks/native/tensor_desc.h +++ b/frameworks/native/tensor_desc.h @@ -16,7 +16,7 @@ #ifndef NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H #define NEURAL_NETWORK_RUNTIME_TENSOR_DESC_H -#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" #include #include 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.h b/frameworks/native/validation.h index 1f13751..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_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { 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 index 856097a..8b93655 100644 --- a/interfaces/kits/c/BUILD.gn +++ b/interfaces/kits/c/BUILD.gn @@ -16,19 +16,23 @@ 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" + ndk_description_file = "neural_network_runtime/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", + "neural_network_runtime/neural_network_core.h", + "neural_network_runtime/neural_network_runtime.h", + "neural_network_runtime/neural_network_runtime_compat.h", + "neural_network_runtime/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", + "neural_network_runtime/neural_network_core.h", + "neural_network_runtime/neural_network_runtime.h", + "neural_network_runtime/neural_network_runtime_compat.h", + "neural_network_runtime/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_core.h b/interfaces/kits/c/neural_network_runtime/neural_network_core.h similarity index 96% rename from interfaces/kits/c/neural_network_core.h rename to interfaces/kits/c/neural_network_runtime/neural_network_core.h index d67f86e..3842cc0 100644 --- a/interfaces/kits/c/neural_network_core.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -332,35 +332,35 @@ 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. - * @param shapeNum The size of the shape list that needs to be set. + * @param shapeLength The size 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 shapeNum); +OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeLength); /** * @brief Get shape of a 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. + * 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. \n * * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param shape Return the shape list of the tensor. - * @param shapeNum Return the size of the shape list. + * @param shapeLength Return the size 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 *shapeNum); +OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength); /** * @brief Set format of a tensorDesc. @@ -400,16 +400,16 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_N * Call this method to obtain the element number of the specified {@link NN_TensorDesc} instance. * If you need to obtain byte size of the tensor data, you can call the {@link OH_NNTensorDesc_GetByteSize} method to obtain it. \n * - * if tensorDesc or elementNum is a null pointer, this method will return error code. \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 elementNum Return the element number of the tensor. + * @param elementCount Return the element number 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_GetElementNum(const NN_TensorDesc *tensorDesc, size_t *elementNum); +OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount); /** * @brief Get byte size of a tensorDesc. @@ -640,9 +640,9 @@ OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, */ void OH_NNExecutor_Destroy(OH_NNExecutor **executor); -OH_NN_ReturnCode OH_NNExecutor_GetInputNum(const OH_NNExecutor *executor, size_t *inputNum); +OH_NN_ReturnCode OH_NNExecutor_GetInputCount(const OH_NNExecutor *executor, size_t *inputCount); -OH_NN_ReturnCode OH_NNExecutor_GetOutputNum(const OH_NNExecutor *executor, size_t *outputNum); +OH_NN_ReturnCode OH_NNExecutor_GetOutputCount(const OH_NNExecutor *executor, size_t *outputCount); NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor, size_t index); @@ -652,7 +652,7 @@ OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *executor, size_t index, size_t **minInputDims, size_t **maxInputDims, - size_t *shapeNum); + size_t *shapeLength); OH_NN_ReturnCode OH_NNExecutor_SetOnRunDone(OH_NNExecutor *executor, NN_OnRunDone onRunDone); @@ -660,15 +660,15 @@ OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor, NN_OnSe OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, NN_Tensor *inputTensor[], - size_t inputNum, + size_t inputCount, NN_Tensor *outputTensor[], - size_t outputNum); + size_t outputCount); OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, NN_Tensor *inputTensor[], - size_t inputNum, + size_t inputCount, NN_Tensor *outputTensor[], - size_t outputNum, + size_t outputCount, int32_t timeout, void* userData); diff --git a/interfaces/kits/c/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h similarity index 98% rename from interfaces/kits/c/neural_network_runtime.h rename to interfaces/kits/c/neural_network_runtime/neural_network_runtime.h index 3076f36..572e400 100644 --- a/interfaces/kits/c/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h @@ -41,6 +41,7 @@ #include "neural_network_runtime_type.h" #include "neural_network_core.h" +#include "neural_network_runtime_compat.h" #ifdef __cplusplus extern "C" { @@ -48,11 +49,11 @@ extern "C" { NN_QuantParam *OH_NNQuantParam_Create(); -OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam *quantParams, const double *scales, size_t quantNum); +OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam *quantParams, const double *scales, size_t quantCount); -OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam *quantParams, const int32_t *zeroPoints, size_t quantNum); +OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam *quantParams, const int32_t *zeroPoints, size_t quantCount); -OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam *quantParams, const uint32_t *numBits, size_t quantNum); +OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam *quantParams, const uint32_t *numBits, size_t quantCount); OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam **quantParams); diff --git a/interfaces/kits/c/neural_network_runtime_compat.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h similarity index 100% rename from interfaces/kits/c/neural_network_runtime_compat.h rename to interfaces/kits/c/neural_network_runtime/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 99% rename from interfaces/kits/c/neural_network_runtime_type.h rename to interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h index 7aadb48..874da01 100644 --- a/interfaces/kits/c/neural_network_runtime_type.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h @@ -132,7 +132,7 @@ typedef enum { /** Invalid file. */ OH_NN_INVALID_FILE = 6, /** A hardware error occurs, for example, HDL service crash. */ - OH_NN_UNAVALIDABLE_DEVICE = 7, + OH_NN_UNAVAILABLE_DEVICE = 7, /** Invalid path. */ OH_NN_INVALID_PATH = 8 } OH_NN_ReturnCode; 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/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/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" diff --git a/testdemo/demo.cpp b/testdemo/demo.cpp index 1d72e87..21a974b 100644 --- a/testdemo/demo.cpp +++ b/testdemo/demo.cpp @@ -1,4 +1,4 @@ -#include "../interfaces/kits/c/neural_network_runtime.h" +#include "../interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include #include -- Gitee From 2512e2c4b0fe1ef1df4de1140a9f401370bec6c9 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 6 Dec 2023 10:33:58 +0800 Subject: [PATCH 13/51] v2-type --- .../neural_network_runtime_type.h | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) 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 874da01..1b1cedd 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 @@ -134,7 +134,19 @@ typedef enum { /** A hardware error occurs, for example, HDL service crash. */ OH_NN_UNAVAILABLE_DEVICE = 7, /** Invalid path. */ - OH_NN_INVALID_PATH = 8 + OH_NN_INVALID_PATH = 8, + /** Timeout. + * @since 11 + */ + OH_NN_TIMEOUT = 9, + /** Unsupported. + * @since 11 + */ + OH_NN_UNSUPPORTED = 10, + /** Connect Exception. + * @since 11 + */ + OH_NN_CONNECT_EXCEPTION = 11 } OH_NN_ReturnCode; typedef void (*NN_OnRunDone)(void*, OH_NN_ReturnCode, void* [], int32_t); @@ -168,7 +180,11 @@ 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; /** @@ -1730,6 +1746,8 @@ typedef struct OH_NN_UInt32Array { \end{cases} \f] * + * @deprecated since 11 + * @useinstead {@link NN_QuantParam} * @since 9 * @version 1.0 */ @@ -1754,6 +1772,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_Tensor} * @since 9 * @version 1.0 */ @@ -1776,6 +1796,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 ea2813a06a7406966a168df73c1757e1e246d1e5 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 6 Dec 2023 14:42:09 +0800 Subject: [PATCH 14/51] consturct model --- frameworks/BUILD.gn | 26 +- frameworks/native/compilation.h | 2 +- frameworks/native/compiler.h | 4 +- frameworks/native/hdi_prepared_model_v2_0.cpp | 9 +- frameworks/native/hdi_returncode_utils.h | 5 +- frameworks/native/inner_model.cpp | 69 +++ frameworks/native/inner_model.h | 3 + frameworks/native/memory_manager.cpp | 102 +++++ frameworks/native/memory_manager.h | 60 +++ frameworks/native/neural_network_runtime.cpp | 418 ++++++++++++++++++ .../native/neural_network_runtime_compat.cpp | 44 ++ frameworks/native/nn_tensor.cpp | 148 +++++-- frameworks/native/nn_tensor.h | 12 +- frameworks/native/quant_param.cpp | 71 +++ frameworks/native/quant_param.h | 48 ++ .../neural_network_runtime_type.h | 2 +- 16 files changed, 959 insertions(+), 64 deletions(-) create mode 100644 frameworks/native/memory_manager.cpp create mode 100644 frameworks/native/memory_manager.h create mode 100644 frameworks/native/neural_network_runtime.cpp create mode 100644 frameworks/native/neural_network_runtime_compat.cpp create mode 100644 frameworks/native/quant_param.cpp create mode 100644 frameworks/native/quant_param.h diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 598f052..a8b1cd3 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -23,26 +23,28 @@ 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/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.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/validation.cpp", + "native/quant_param.cpp" ] ops_sources = [ diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index d39b51b..837b682 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -16,7 +16,7 @@ #define NEURAL_NETWORK_RUNTIME_COMPILATION_H #include "compiler.h" -#include "neural_network_runtime.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h index 1ece4ef..be6fb35 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -15,8 +15,8 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILER_H #define NEURAL_NETWORK_RUNTIME_COMPILER_H -#include "neural_network_runtime.h" -#include "cpp_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" +#include namespace OHOS { namespace NeuralNetworkRuntime { diff --git a/frameworks/native/hdi_prepared_model_v2_0.cpp b/frameworks/native/hdi_prepared_model_v2_0.cpp index 249af8b..f3bdc4b 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 { @@ -93,14 +94,14 @@ V2_0::IOTensor TransIOTensor(const IOTensor& tensor) return iTensor; } -OH_NN_ReturnCode TransIOTensor(const NNCore_Tensor* tensor, V2_0::IOTensor& ioTensor) +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 NNTensor* nnTensor = reinterpret_cast(tensor); + const NNTensor2_0* nnTensor = reinterpret_cast(tensor); TensorDesc* nnTensorDesc = nnTensor->GetTensorDesc(); if (nnTensorDesc == nullptr) { LOGE("TransIOTensor failed, failed to get desc from tensor."); @@ -229,8 +230,8 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, return OH_NN_SUCCESS; } -OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, - const std::vector& outputs, std::vector>& outputsDims, +OH_NN_ReturnCode HDIPreparedModelV2_0::Run(const std::vector& inputs, + const std::vector& outputs, std::vector>& outputsDims, std::vector& isOutputBufferEnough) { V2_0::IOTensor iTensor; 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..e098816 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -198,6 +198,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) { diff --git a/frameworks/native/inner_model.h b/frameworks/native/inner_model.h index 62aab0b..a5baf9a 100644 --- a/frameworks/native/inner_model.h +++ b/frameworks/native/inner_model.h @@ -35,6 +35,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, diff --git a/frameworks/native/memory_manager.cpp b/frameworks/native/memory_manager.cpp new file mode 100644 index 0000000..1c6cc87 --- /dev/null +++ b/frameworks/native/memory_manager.cpp @@ -0,0 +1,102 @@ +/* + * 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 "memory_manager.h" + +#include +#include + +#include "cpp_type.h" +#include "common/log.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +void* MemoryManager::MapMemory(int fd, size_t length) +{ + if (fd < 0) { + LOGE("Invalid fd, fd must greater than 0."); + return nullptr; + } + + if (length <= 0 || length > ALLOCATE_BUFFER_LIMIT) { + LOGE("Invalid buffer size, it must greater than 0 and less than 1Gb. length=%zu", length); + return nullptr; + } + + void* addr = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + LOGE("Map fd to address failed."); + return nullptr; + } + + std::lock_guard lock(m_mtx); + Memory memory {fd, addr, length}; + m_memorys.emplace(addr, memory); + return addr; +} + +OH_NN_ReturnCode MemoryManager::UnMapMemory(const void* buffer) +{ + if (buffer == nullptr) { + LOGE("Buffer is nullptr, no need to release."); + return OH_NN_INVALID_PARAMETER; + } + + auto iter = m_memorys.find(buffer); + if (iter == m_memorys.end()) { + LOGE("This buffer is not found, cannot release."); + return OH_NN_INVALID_PARAMETER; + } + + auto& memory = m_memorys[buffer]; + auto unmapResult = munmap(const_cast(memory.data), memory.length); + if (unmapResult != 0) { + LOGE("Unmap memory failed. Please try again."); + return OH_NN_MEMORY_ERROR; + } + memory.data = nullptr; + + if (close(memory.fd) != 0) { + LOGE("Close memory fd failed. fd=%d", memory.fd); + return OH_NN_MEMORY_ERROR; + } + + std::lock_guard lock(m_mtx); + m_memorys.erase(iter); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode MemoryManager::GetMemory(const void* buffer, Memory& memory) const +{ + if (buffer == nullptr) { + LOGE("Memory is nullptr."); + return OH_NN_NULL_PTR; + } + + auto iter = m_memorys.find(buffer); + if (iter == m_memorys.end()) { + LOGE("Memory is not found."); + return OH_NN_INVALID_PARAMETER; + } + + memory.fd = iter->second.fd; + memory.data = iter->second.data; + memory.length = iter->second.length; + + return OH_NN_SUCCESS; +} +} // NeuralNetworkRuntime +} // OHOS \ No newline at end of file diff --git a/frameworks/native/memory_manager.h b/frameworks/native/memory_manager.h new file mode 100644 index 0000000..ae56bec --- /dev/null +++ b/frameworks/native/memory_manager.h @@ -0,0 +1,60 @@ +/* + * 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_RUNTIME_MEMORY_MANAGER_H +#define NEURAL_NETWORK_RUNTIME_MEMORY_MANAGER_H + +#include +#include + +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +const int INVALID_FD = -1; + +struct Memory { + int fd; + const void* data; + size_t length; +}; + +class MemoryManager { +public: + ~MemoryManager() = default; + + void* MapMemory(int fd, size_t length); + OH_NN_ReturnCode UnMapMemory(const void* buffer); + OH_NN_ReturnCode GetMemory(const void* buffer, Memory& memory) const; + + static MemoryManager* GetInstance() + { + static MemoryManager instance; + return &instance; + } + +private: + MemoryManager() {}; + MemoryManager(const MemoryManager&) = delete; + MemoryManager& operator=(const MemoryManager&) = delete; + +private: + // key: OH_NN_Memory, value: fd + std::unordered_map m_memorys; + std::mutex m_mtx; +}; +} // namespace NeuralNetworkRuntime +} // OHOS +#endif // NEURAL_NETWORK_RUNTIME_MEMORY_MANAGER_H \ No newline at end of file diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp new file mode 100644 index 0000000..49de519 --- /dev/null +++ b/frameworks/native/neural_network_runtime.cpp @@ -0,0 +1,418 @@ +/* + * 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 "device_manager.h" +#include "executor.h" +#include "inner_model.h" +#include "common/log.h" +#include "quant_param.h" +#include "validation.h" + + +using namespace OHOS::NeuralNetworkRuntime; + +#define NNRT_API __attribute__((visibility("default"))) + +NNRT_API NN_QuantParam *OH_NNQuantParam_Create() +{ + auto* quantParamImpl = new (std::nothrow) QuantParams(); + if (quantParamImpl == nullptr) { + LOGE("OH_NNQuantParam_Create failed, please check whether it has enough memory."); + return nullptr; + } + + return (NN_QuantParam*)(quantParamImpl); +} + +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_AddTensorToModel failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (tensorDesc == nullptr) { + LOGE("OH_NNModel_AddTensorToModel failed, passed nullptr to tensorDesc."); + return OH_NN_INVALID_PARAMETER; + } + + 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, + OH_NN_OperationType op, + const OH_NN_UInt32Array *paramIndices, + const OH_NN_UInt32Array *inputIndices, + const OH_NN_UInt32Array *outputIndices) +{ + if (model == nullptr) { + LOGE("OH_NNModel_AddOperation failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (paramIndices == nullptr) { + LOGE("OH_NNModel_AddOperation failed, passed nullptr to paramIndices."); + return OH_NN_INVALID_PARAMETER; + } + + if (inputIndices == nullptr) { + LOGE("OH_NNModel_AddOperation failed, passed nullptr to inputIndices."); + return OH_NN_INVALID_PARAMETER; + } + + if (outputIndices == nullptr) { + LOGE("OH_NNModel_AddOperation failed, passed nullptr to outputIndices."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->AddOperation(op, *paramIndices, *inputIndices, *outputIndices); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, + uint32_t index, + const void *dataBuffer, + size_t length) +{ + if (model == nullptr) { + LOGE("OH_NNModel_SetTensorData failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (dataBuffer == nullptr) { + LOGE("OH_NNModel_SetTensorData failed, passed nullptr to dataBuffer, which has no effect."); + return OH_NN_INVALID_PARAMETER; + } + + if (length == 0) { + LOGE("OH_NNModel_SetTensorData failed, passed dataBuffer with length 0, which has no effect."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->SetTensorValue(index, dataBuffer, length); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, + const OH_NN_UInt32Array *inputIndices, + const OH_NN_UInt32Array *outputIndices) +{ + if (model == nullptr) { + LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (inputIndices == nullptr) { + LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to inputIndices."); + return OH_NN_INVALID_PARAMETER; + } + + if (outputIndices == nullptr) { + LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to outputIndices."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->SpecifyInputsAndOutputs(*inputIndices, *outputIndices); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model) +{ + if (model == nullptr) { + LOGE("OH_NNModel_Finish failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->Build(); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromLiteGraph(OH_NNModel *model, const void *liteGraph) +{ + if (model == nullptr) { + LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (liteGraph == nullptr) { + LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to liteGraph."); + return OH_NN_INVALID_PARAMETER; + } + + auto *pLiteGraph = static_cast(liteGraph); + InnerModel *innerModel = reinterpret_cast(model); + + // Once the innerModel built from the liteGraph successfully, the innerModel + // owns the liteGraph, in which case, the invoker should not delete + // the liteGraph actively. Otherwise, the invoker still has the ownership. + return innerModel->BuildFromLiteGraph(pLiteGraph); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromMetaGraph(OH_NNModel *model, const void *metaGraph, + const OH_NN_Extension *extensions, size_t extensionSize) +{ + if (model == nullptr) { + LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (metaGraph == nullptr) { + LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to metaGraph."); + return OH_NN_INVALID_PARAMETER; + } + + Buffer buffer; + std::string modelName; + for (size_t i = 0; i < extensionSize; ++i) { + std::string name = extensions[i].name; + if (name == "QuantBuffer") { + buffer.data = extensions[i].value; + buffer.length = extensions[i].valueSize; + } else if (name == "ModelName") { + modelName.assign(extensions[i].value, extensions[i].value + extensions[i].valueSize); + } + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->BuildFromMetaGraph(metaGraph, buffer, modelName); +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_SetInputsAndOutputsInfo(OH_NNModel *model, const OH_NN_TensorInfo *inputsInfo, + size_t inputSize, const OH_NN_TensorInfo *outputsInfo, size_t outputSize) +{ + if (model == nullptr) { + LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if ((inputsInfo == nullptr) || (inputSize == 0)) { + LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, inputsInfo is empty."); + return OH_NN_INVALID_PARAMETER; + } + + if ((outputsInfo == nullptr) || (outputSize == 0)) { + LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, outputsInfo is empty."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->SetInputsAndOutputsInfo(inputsInfo, inputSize, outputsInfo, outputSize); +} + +NNRT_API void OH_NNModel_Destroy(OH_NNModel **model) +{ + if (model == nullptr) { + LOGW("OH_NNModel_Destroy has no effect, passed nullptr to model."); + return; + } + + if (*model == nullptr) { + LOGW("OH_NNModel_Destroy has no effect, passed nullptr to *model."); + return; + } + + InnerModel *innerModel = reinterpret_cast(*model); + delete innerModel; + *model = nullptr; +} + +NNRT_API OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, + size_t deviceID, + const bool **isAvailable, + uint32_t *opCount) +{ + if (model == nullptr) { + LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to model."); + return OH_NN_INVALID_PARAMETER; + } + + if (isAvailable == nullptr) { + LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to isAvailable."); + return OH_NN_INVALID_PARAMETER; + } + + if (*isAvailable != nullptr) { + LOGE("OH_NNModel_GetAvailableOperations failed, *isAvailable is not nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + if (opCount == nullptr) { + LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to opCount."); + return OH_NN_INVALID_PARAMETER; + } + + InnerModel *innerModel = reinterpret_cast(model); + return innerModel->GetSupportedOperations(deviceID, isAvailable, *opCount); +} \ 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..4e93aae --- /dev/null +++ b/frameworks/native/neural_network_runtime_compat.cpp @@ -0,0 +1,44 @@ +/* + * 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 "device_manager.h" +#include "executor.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); +} \ No newline at end of file diff --git a/frameworks/native/nn_tensor.cpp b/frameworks/native/nn_tensor.cpp index 71755a1..18290f8 100644 --- a/frameworks/native/nn_tensor.cpp +++ b/frameworks/native/nn_tensor.cpp @@ -23,6 +23,8 @@ #include "common/log.h" #include "mindir.h" #include "mindir_types.h" +#include "tensor_desc.h" +#include "quant_param.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -74,7 +76,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 +87,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 +119,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 +149,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::ParseDimensions(const std::vector& dimensions) +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::ValidateDimensions(const std::vector& dimensions) { // Temporary variable to check overflow. uint64_t absoluteDim {0}; @@ -187,24 +261,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 +305,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 +361,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; diff --git a/frameworks/native/nn_tensor.h b/frameworks/native/nn_tensor.h index e5ea8dd..ef4a2b7 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -41,9 +41,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 +53,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; @@ -74,12 +78,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/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/quant_param.h b/frameworks/native/quant_param.h new file mode 100644 index 0000000..59bc5e9 --- /dev/null +++ b/frameworks/native/quant_param.h @@ -0,0 +1,48 @@ +/* + * 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_RUNTIME_QUANT_PARAMS_H +#define NEURAL_NETWORK_RUNTIME_QUANT_PARAMS_H + +#include + +#include "cpp_type.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class QuantParams { +public: + QuantParams() = default; + ~QuantParams() = default; + + void SetScales(std::vector scales); + void SetZeroPoints(std::vector zeroPoints); + void SetNumBits(std::vector numBits); + + std::vector GetScales() const; + std::vector GetZeroPoints() const; + std::vector GetNumBits() const; + + OH_NN_ReturnCode CopyToCompat(std::vector& compatQuantParams) const; + +private: + std::vector m_scales; + std::vector m_zeroPoints; + std::vector m_numBits; +}; +} // namespace NeuralNetworkRuntime +} // namespace OHOS +#endif // NEURAL_NETWORK_RUNTIME_QUANT_PARAMS_H \ No newline at end of file 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 1b1cedd..2bcdda5 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 @@ -132,7 +132,7 @@ typedef enum { /** Invalid file. */ OH_NN_INVALID_FILE = 6, /** A hardware error occurs, for example, HDL service crash. */ - OH_NN_UNAVAILABLE_DEVICE = 7, + OH_NN_UNAVALIDABLE_DEVICE = 7, /** Invalid path. */ OH_NN_INVALID_PATH = 8, /** Timeout. -- Gitee From 2297c4e56740473404b927141affd96a46174490 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 6 Dec 2023 15:15:12 +0800 Subject: [PATCH 15/51] compat executor --- frameworks/native/device.h | 2 + frameworks/native/hdi_device_v1_0.cpp | 5 + frameworks/native/hdi_device_v1_0.h | 1 + frameworks/native/hdi_device_v2_0.cpp | 5 + frameworks/native/hdi_device_v2_0.h | 1 + frameworks/native/nnexecutor.cpp | 619 ++++++++++++++++++++++++++ frameworks/native/nnexecutor.h | 44 +- 7 files changed, 676 insertions(+), 1 deletion(-) diff --git a/frameworks/native/device.h b/frameworks/native/device.h index efe380c..66f7275 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.h @@ -25,6 +25,7 @@ #include "tensor_desc.h" #include "prepared_model.h" #include "mindir.h" +#include "nn_tensor.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -63,6 +64,7 @@ public: 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; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/hdi_device_v1_0.cpp b/frameworks/native/hdi_device_v1_0.cpp index 3c6602c..e19949f 100644 --- a/frameworks/native/hdi_device_v1_0.cpp +++ b/frameworks/native/hdi_device_v1_0.cpp @@ -362,6 +362,11 @@ void* HDIDeviceV1_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +{ + return AllocateBuffer(length); +} + OH_NN_ReturnCode HDIDeviceV1_0::ReleaseBuffer(const void* buffer) { if (buffer == nullptr) { diff --git a/frameworks/native/hdi_device_v1_0.h b/frameworks/native/hdi_device_v1_0.h index 1c35d91..281b895 100644 --- a/frameworks/native/hdi_device_v1_0.h +++ b/frameworks/native/hdi_device_v1_0.h @@ -60,6 +60,7 @@ public: 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; private: diff --git a/frameworks/native/hdi_device_v2_0.cpp b/frameworks/native/hdi_device_v2_0.cpp index db43e00..8979042 100644 --- a/frameworks/native/hdi_device_v2_0.cpp +++ b/frameworks/native/hdi_device_v2_0.cpp @@ -397,6 +397,11 @@ void* HDIDeviceV2_0::AllocateTensorBuffer(size_t length, std::shared_ptr tensor) +{ + return AllocateBuffer(length); +} + OH_NN_ReturnCode HDIDeviceV2_0::ReleaseBuffer(const void* buffer) { if (buffer == nullptr) { diff --git a/frameworks/native/hdi_device_v2_0.h b/frameworks/native/hdi_device_v2_0.h index 09d1595..f19f4cf 100644 --- a/frameworks/native/hdi_device_v2_0.h +++ b/frameworks/native/hdi_device_v2_0.h @@ -60,6 +60,7 @@ public: 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; private: diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 079713f..558fb41 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -19,6 +19,11 @@ #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 { NNExecutor::NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, @@ -265,5 +270,619 @@ OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size return OH_NN_SUCCESS; } + +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()) { + LOGE("BuildInputTensor failed, input index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + // Build a tensor from nnTensor. + auto ret = inputTensor->BuildFromOHNNTensor(nnTensor); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildInputTensor failed, please check input nnTensor."); + return ret; + } + + if (inputTensor->IsDynamicShape()) { + LOGE("BuildInputTensor failed, input nnTensor should has certain dimensions which cannot contain -1."); + return OH_NN_INVALID_PARAMETER; + } + + inputTensor->SetFormat(m_modelInputs[index]->GetFormat()); + if (!m_modelInputs[index]->CompareAttribute(*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()); + return OH_NN_SUCCESS; +} + + +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); + // Current buffer inside m_inputTensors is managed by executor, no need to release if memcpy failed. + if (status != EOK) { + LOGE("SetInputTensorWithCurrentBuffe failed, copy data from user buffer to device buffer failed. " + "Error code: %d.", status); + return OH_NN_MEMORY_ERROR; + } + + // Set the new tensor with the buffer of current tensor + inputTensor->SetBuffer(curBuffer, curBufferLength); + + // The memory is reused here. Thus, current tensor's buffer must set to nullptr, in case the memory is released + // twice. + m_inputTensors[index].tensor->SetBuffer(nullptr, 0); + + // Set to the new tensor, and release current one. + m_inputTensors[index].tensor = inputTensor; + return OH_NN_SUCCESS; +} + + +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(); + 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); + } + + // Set new input tensor data buffer + inputTensor->SetBuffer(inputBuffer, length); + + // Create or update the input tensor + ExeTensor exeTensor{inputTensor, nullptr, 0, isInnerMem}; + m_inputTensors[index] = exeTensor; +} + + +OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(uint32_t index, const OH_NN_Tensor& nnTensor) const +{ + std::vector> minInputDims; + std::vector> 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; + } + + if (index >= minInputDims.size()) { + LOGE("index is %u, which exceeds the size of minInputDims:%zu.", index, minInputDims.size()); + return OH_NN_INVALID_PARAMETER; + } + + if (index >= maxInputDims.size()) { + LOGE("index is %u, which exceeds the size of maxInputDims:%zu.", index, maxInputDims.size()); + return OH_NN_INVALID_PARAMETER; + } + + const std::vector& minSingleInputDims = minInputDims[index]; + const std::vector& maxSingleInputDims = maxInputDims[index]; + + std::vector tensorShape = ConstructVectorFromArray(nnTensor.dimensions, nnTensor.dimensionCount); + size_t tensorShapeSize = tensorShape.size(); + if (minSingleInputDims.size() != tensorShapeSize || maxSingleInputDims.size() != tensorShapeSize) { + LOGE("Size of minSingleInputDims, maxSingleInputDims and tensorShape of input %u are not equal.", index); + return OH_NN_INVALID_PARAMETER; + } + + for (size_t j = 0; j < tensorShapeSize; ++j) { + // Dimensions cannot be negative + if (tensorShape[j] < 0) { + LOGE("Dimension %zu of input %u is %d.", j, index, tensorShape[j]); + return OH_NN_INVALID_PARAMETER; + } + uint32_t dim = static_cast(tensorShape[j]); + if (dim < minSingleInputDims[j] || dim > maxSingleInputDims[j]) { + LOGE("Dimension %zu of input %u is %u, which is out of range [%u, %u]", + j, index, dim, minSingleInputDims[j], maxSingleInputDims[j]); + return OH_NN_INVALID_PARAMETER; + } + } + + return OH_NN_SUCCESS; +} + + +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) { + LOGI("Skip input dimension bounds check."); + } else if (nnRet != OH_NN_SUCCESS) { + LOGE("SetInput failed, Check the range of the %uth input dimension ranges failed.", index); + return nnRet; + } + + std::shared_ptr inputTensor = CreateSharedPtr(); + if (inputTensor == nullptr) { + LOGE("SetInput failed, error happened when creating NNTensor."); + return OH_NN_MEMORY_ERROR; + } + + auto ret = BuildInputTensor(index, nnTensor, inputTensor); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInput failed, please check input index or nnTensor."); + return ret; + } + + // dataLength will be larger than 0 after BuildInputTensor() + size_t dataLength = inputTensor->GetDataLength(); + if (length == 0 || length < dataLength) { + LOGE("SetInput failed, the given buffer length is too small to store the input nnTensor data."); + return OH_NN_INVALID_PARAMETER; + } + + // Get length of current buffer if it is allocate by SetInput() before. + size_t curBufferLength = 0; + if ((m_inputTensors.find(index) != m_inputTensors.end()) && (m_inputTensors[index].isInnerMem)) { + curBufferLength = m_inputTensors[index].tensor->GetBufferLength(); + } + + // (dataLength <= curBufferLength) returns true if and only if current buffer is allocated by SetInput() before + // and is larger than user buffer. + if (dataLength <= curBufferLength) { + ret = SetInputTensorWithCurrentBuffer(index, inputTensor, buffer, dataLength, curBufferLength); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInput failed, error happened when setting input with current buffer."); + return ret; + } + m_isRun = false; + return OH_NN_SUCCESS; + } + + /** + * Buffer needs to allocated or reallocated if: + * + * - Current buffer is not enough. + * - SetInput() has not been called for the input before. + * - The buffer held in m_inputTensors is allocated and set by CreateInputMemory() and SetInputFromMemory(). + */ + 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; + } + + 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); + m_device->ReleaseBuffer(inputBuffer); + return OH_NN_MEMORY_ERROR; + } + + SetInputTensorWithNewBuffer(index, inputTensor, inputBuffer, length, true); + m_isRun = false; + return OH_NN_SUCCESS; +} + + +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) { + LOGI("Skip input dimension bounds check."); + } else if (nnRet != OH_NN_SUCCESS) { + LOGE("SetInputFromMemory failed, Check the range of the %uth input dimension ranges failed.", index); + return nnRet; + } + + // Build a input tensor + std::shared_ptr inputTensor = CreateSharedPtr(); + if (inputTensor == nullptr) { + LOGE("SetInputFromMemory failed, error happened when creating NNTensor."); + return OH_NN_MEMORY_ERROR; + } + + auto ret = BuildInputTensor(index, nnTensor, inputTensor); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInputFromMemory failed, please check input index or nnTensor"); + return ret; + } + + // check data length + size_t dataLength = inputTensor->GetDataLength(); + if (memory.length == 0 || memory.length < dataLength) { + LOGE("SetInputFromMemory failed," + " the length in the given memory is too small to store the input nnTensor data."); + return OH_NN_INVALID_PARAMETER; + } + + SetInputTensorWithNewBuffer(index, inputTensor, const_cast(memory.data), memory.length, false); + m_isRun = false; + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t length) +{ + if (index >= m_modelOutputs.size()) { + LOGE("SetOutput failed, output index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + size_t dataLength = m_modelOutputs[index]->GetDataLength(); + 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; + } + + // 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. + if (m_outputTensors.find(index) != m_outputTensors.end()) { + if (m_outputTensors[index].isInnerMem) { + size_t curBufferLength = m_outputTensors[index].tensor->GetBufferLength(); + if (length <= curBufferLength) { + // If current device buffer size is enough, only update the user buffer. + m_outputTensors[index].userBuffer = buffer; + m_outputTensors[index].userBufferLength = length; + m_isRun = false; + return OH_NN_SUCCESS; + } else { + // 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(); + 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]; + } + + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensors[index].tensor); + if (deviceOutputBuffer == nullptr) { + LOGE("SetOutput failed, allocating output device buffer failed."); + return OH_NN_MEMORY_ERROR; + } + + m_outputTensors[index].tensor->SetBuffer(deviceOutputBuffer, length); + m_outputTensors[index].userBuffer = buffer; + m_outputTensors[index].userBufferLength = length; + m_outputTensors[index].isInnerMem = true; + m_isRun = false; + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Memory& memory) +{ + if (index >= m_modelOutputs.size()) { + LOGE("SetOutputFromMemory failed, output index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + size_t dataLength = m_modelOutputs[index]->GetDataLength(); + 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; + } + + if (m_outputTensors.find(index) != m_outputTensors.end()) { + if (m_outputTensors[index].isInnerMem) { + // If it is inner buffer, releate it + void* curBuffer = m_outputTensors[index].tensor->GetBuffer(); + 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]; + } + + // Set the output tensor with memory + m_outputTensors[index].tensor->SetBuffer(const_cast(memory.data), memory.length); + m_outputTensors[index].userBuffer = nullptr; + m_outputTensors[index].userBufferLength = 0; + m_outputTensors[index].isInnerMem = false; + m_isRun = false; + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t index, int32_t** dimensions, uint32_t& dimensionCount) +{ + 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); + 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 NNExecutor::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."); + return OH_NN_INVALID_PARAMETER; + } + + // Allocate device buffer + void* deviceInputBuffer = m_device->AllocateTensorBuffer(length, m_modelInputs[index]); + if (deviceInputBuffer == nullptr) { + LOGE("CreateInputMemory failed, allocating intput device buffer failed."); + return OH_NN_MEMORY_ERROR; + } + + *memory = new(std::nothrow) OH_NN_Memory{deviceInputBuffer, length}; + if (*memory == nullptr) { + LOGE("CreateInputMemory failed, constructing OH_NN_Memory failed."); + m_device->ReleaseBuffer(deviceInputBuffer); + return OH_NN_MEMORY_ERROR; + } + + // Save the buffer address for check when destroying it. + m_inputCreatedMem[index].emplace_back(deviceInputBuffer); + + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::DestroyInputMemory(uint32_t index, OH_NN_Memory** memory) +{ + if (index >= m_modelInputs.size()) { + LOGE("DestroyInputMemory failed, input index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_inputCreatedMem.find(index) == m_inputCreatedMem.end()) { + LOGE("DestroyInputMemory failed, the memory has not been created with the index."); + return OH_NN_INVALID_PARAMETER; + } + + std::vector& inputCreatedMem = m_inputCreatedMem[index]; + auto pos = std::find(inputCreatedMem.begin(), inputCreatedMem.end(), (*memory)->data); + if (pos == inputCreatedMem.end()) { + LOGE("DestroyInputMemory failed, the index does not match the memory."); + return OH_NN_INVALID_PARAMETER; + } + + auto ret = m_device->ReleaseBuffer((*memory)->data); + if (ret != OH_NN_SUCCESS) { + LOGE("Release input buffer failed."); + return ret; + } + + inputCreatedMem.erase(pos); + delete *memory; + *memory = nullptr; + + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::CreateOutputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) +{ + if (index >= m_modelOutputs.size()) { + LOGE("CreateOutputMemory failed, output index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + // Allocate device buffer + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_modelOutputs[index]); + if (deviceOutputBuffer == nullptr) { + LOGE("CreateOutputMemory failed, allocating output device buffer failed."); + return OH_NN_MEMORY_ERROR; + } + + *memory = new(std::nothrow) OH_NN_Memory{deviceOutputBuffer, length}; + if (*memory == nullptr) { + LOGE("CreateOutputMemory failed, constructing OH_NN_Memory failed."); + m_device->ReleaseBuffer(deviceOutputBuffer); + return OH_NN_MEMORY_ERROR; + } + + // Save the buffer address for check when destroying it. + m_outputCreatedMem[index].emplace_back(deviceOutputBuffer); + + return OH_NN_SUCCESS; +} + + +OH_NN_ReturnCode NNExecutor::DestroyOutputMemory(uint32_t index, OH_NN_Memory** memory) +{ + if (index >= m_modelOutputs.size()) { + LOGE("DestroyOutputMemory failed, output index is out of range."); + return OH_NN_INVALID_PARAMETER; + } + + if (m_outputCreatedMem.find(index) == m_outputCreatedMem.end()) { + LOGE("DestroyOutputMemory failed, the memory has not been created with the index."); + return OH_NN_INVALID_PARAMETER; + } + + std::vector& outputCreatedMem = m_outputCreatedMem[index]; + auto pos = std::find(outputCreatedMem.begin(), outputCreatedMem.end(), (*memory)->data); + if (pos == outputCreatedMem.end()) { + LOGE("DestroyOutputMemory failed, the index does not match the memory."); + return OH_NN_INVALID_PARAMETER; + } + + auto ret = m_device->ReleaseBuffer((*memory)->data); + if (ret != OH_NN_SUCCESS) { + LOGE("Release output buffer failed."); + return ret; + } + + outputCreatedMem.erase(pos); + delete *memory; + *memory = nullptr; + + 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)); + } + + 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; +} + +OH_NN_ReturnCode NNExecutor::Run() +{ + NNRT_TRACE_NAME("Execution"); + if (m_modelInputs.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()) { + LOGE("Run failed, some output tensors have not been set."); + return OH_NN_INVALID_PARAMETER; + } + + // Build the NNTensor pointer vector: inputTensors and outputTensors + std::vector> inputTensors; + std::vector> outputTensors; + size_t inputSize = m_inputTensors.size(); + size_t outputSize = m_outputTensors.size(); + for (size_t i = 0; i < inputSize; ++i) { + inputTensors.emplace_back(m_inputTensors[i].tensor); + } + for (size_t i = 0; i < outputSize; ++i) { + outputTensors.emplace_back(m_outputTensors[i].tensor); + } + + // Predict + auto ret = Run(inputTensors, outputTensors); + if (ret != OH_NN_SUCCESS) { + LOGE("Run failed, error happened when executing the inference."); + return ret; + } + + errno_t status{EOK}; + // Copy inner device buffer to user buffer if using SetOutput() + for (size_t i = 0; i < outputSize; ++i) { + if (m_outputTensors[i].isInnerMem) { + auto size = outputTensors[i]->GetDataLength(); + if (size > m_outputTensors[i].userBufferLength) { + LOGE("Output buffer size is not enough. Your size=%zu, but actual output size=%zu.", + m_outputTensors[i].userBufferLength, size); + return OH_NN_INVALID_PARAMETER; + } + + void* deviceBuffer = outputTensors[i]->GetBuffer(); + if (deviceBuffer == nullptr) { + LOGE("Output buffer is nullptr."); + return OH_NN_FAILED; + } + + status = memcpy_s(m_outputTensors[i].userBuffer, m_outputTensors[i].userBufferLength, deviceBuffer, size); + if (status != EOK) { + LOGE("Run failed, memory copy from device buffer to user buffer failed. Error code: %d.", status); + return OH_NN_MEMORY_ERROR; + } + } + } + + m_isRun = true; + return OH_NN_SUCCESS; +} + +NNExecutor::~NNExecutor() +{ + for (auto& it : m_inputTensors) { + if ((it.second).isInnerMem) { + m_device->ReleaseBuffer((it.second).tensor->GetBuffer()); + } + (it.second).tensor->SetBuffer(nullptr, 0); + (it.second).tensor.reset(); + (it.second).userBuffer = nullptr; + } + m_inputTensors.clear(); + + for (auto& it : m_outputTensors) { + if ((it.second).isInnerMem) { + m_device->ReleaseBuffer((it.second).tensor->GetBuffer()); + } + (it.second).tensor->SetBuffer(nullptr, 0); + (it.second).tensor.reset(); + (it.second).userBuffer = nullptr; + } + m_outputTensors.clear(); + + for (auto& it : m_inputCreatedMem) { + it.second.clear(); + } + m_inputCreatedMem.clear(); + + for (auto& it : m_outputCreatedMem) { + it.second.clear(); + } + m_outputCreatedMem.clear(); + + m_outputDimensions.clear(); + m_modelInputs.clear(); + m_modelOutputs.clear(); +} } // namespace NeuralNetworkRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index 08c196f..ba534e0 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -19,6 +19,7 @@ #include "executor.h" #include "device.h" #include "prepared_model.h" +#include "nn_tensor.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -29,7 +30,7 @@ public: std::shared_ptr preparedModel, std::vector> inputTensorDescs, std::vector> outputTensorDescs); - virtual ~NNExecutor() = default; + virtual ~NNExecutor(); virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, size_t** minInputDims, @@ -56,15 +57,56 @@ public: 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 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 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); + 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> m_inputTensorDescs; std::vector> 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::vector> m_modelInputs; + std::vector> m_modelOutputs; + 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; }; } // namespace NeuralNetworkRuntime } // namespace OHOS -- Gitee From 2de28a41e0123c09774b44da5cb6869549f22083 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Wed, 6 Dec 2023 16:38:44 +0800 Subject: [PATCH 16/51] add neural_network_runtime_compat.cpp --- .../native/neural_network_runtime_compat.cpp | 188 +++++++++++++++++- frameworks/native/nnexecutor.cpp | 178 ++++++++++++----- frameworks/native/nnexecutor.h | 6 +- 3 files changed, 318 insertions(+), 54 deletions(-) diff --git a/frameworks/native/neural_network_runtime_compat.cpp b/frameworks/native/neural_network_runtime_compat.cpp index 4e93aae..5cfc7c1 100644 --- a/frameworks/native/neural_network_runtime_compat.cpp +++ b/frameworks/native/neural_network_runtime_compat.cpp @@ -18,7 +18,7 @@ #include "compilation.h" #include "device_manager.h" -#include "executor.h" +#include "nnexecutor.h" #include "inner_model.h" #include "common/log.h" @@ -41,4 +41,190 @@ NNRT_API OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Te 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/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 558fb41..e616740 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -271,11 +271,49 @@ OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size return OH_NN_SUCCESS; } +bool NNExecutor::CompareAttribute(std::shared_ptr tensorDesc, const NNTensor& tensor) const +{ + OH_NN_DataType dataType; + auto ret = tensorDesc->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->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; + } + } + + 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; } @@ -292,13 +330,26 @@ OH_NN_ReturnCode NNExecutor::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]->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]->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; } @@ -507,15 +558,63 @@ OH_NN_ReturnCode NNExecutor::SetInputFromMemory(uint32_t index, const OH_NN_Tens return OH_NN_SUCCESS; } +std::shared_ptr NNExecutor::BuildNNTensorFromDesc(std::shared_ptr 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.get()); + auto ret = tensor->BuildFromTensorDesc(tensorDescCast); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, please check input nnTensor."); + return nullptr; + } + + if (tensor->IsDynamicShape()) { + LOGE("BuildNNTensorFromDesc failed, input nnTensor should has certain dimensions which cannot contain -1."); + return nullptr; + } + + OH_NN_Format format; + ret = tensorDesc->GetFormat(&format); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildNNTensorFromDesc failed, failed to get tensor format from desc."); + return nullptr; + } + tensor->SetFormat(format); + + 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->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 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; } - size_t dataLength = m_modelOutputs[index]->GetDataLength(); + size_t dataLength {0}; + auto ret = m_outputTensorDescs[index]->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; @@ -544,10 +643,10 @@ OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t leng // 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]); } - void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensors[index].tensor); + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[index]); if (deviceOutputBuffer == nullptr) { LOGE("SetOutput failed, allocating output device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -564,12 +663,17 @@ OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t leng 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; } - size_t dataLength = m_modelOutputs[index]->GetDataLength(); + size_t dataLength {0}; + auto ret = m_outputTensorDescs[index]->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; @@ -585,7 +689,7 @@ OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Mem // 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]); } // Set the output tensor with memory @@ -597,41 +701,15 @@ OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Mem return OH_NN_SUCCESS; } - -OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t index, int32_t** dimensions, uint32_t& dimensionCount) -{ - 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); - 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 NNExecutor::CreateInputMemory(uint32_t index, size_t length, OH_NN_Memory** memory) { - if (index >= m_modelInputs.size()) { + if (index >= m_inputTensorDescs.size()) { LOGE("CreateInputMemory failed, input index is out of range."); return OH_NN_INVALID_PARAMETER; } // Allocate device buffer - void* deviceInputBuffer = m_device->AllocateTensorBuffer(length, m_modelInputs[index]); + void* deviceInputBuffer = m_device->AllocateTensorBuffer(length, m_inputTensorDescs[index]); if (deviceInputBuffer == nullptr) { LOGE("CreateInputMemory failed, allocating intput device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -653,7 +731,7 @@ OH_NN_ReturnCode NNExecutor::CreateInputMemory(uint32_t index, size_t length, OH 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; } @@ -686,13 +764,13 @@ OH_NN_ReturnCode NNExecutor::DestroyInputMemory(uint32_t index, OH_NN_Memory** m 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; } // Allocate device buffer - void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_modelOutputs[index]); + void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[index]); if (deviceOutputBuffer == nullptr) { LOGE("CreateOutputMemory failed, allocating output device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -714,7 +792,7 @@ OH_NN_ReturnCode NNExecutor::CreateOutputMemory(uint32_t index, size_t length, O 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; } @@ -783,6 +861,12 @@ OH_NN_ReturnCode NNExecutor::Run(const std::vector>& i LOGE("Run failed, error happened when setting output tensor's dimensions, output id: %zu.", i); return ret; } + ret = m_outputTensorDescs[i]->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; @@ -791,11 +875,11 @@ OH_NN_ReturnCode NNExecutor::Run(const std::vector>& i 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; } @@ -879,10 +963,6 @@ NNExecutor::~NNExecutor() it.second.clear(); } m_outputCreatedMem.clear(); - - m_outputDimensions.clear(); - m_modelInputs.clear(); - m_modelOutputs.clear(); } } // namespace NeuralNetworkRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index ba534e0..1a0a710 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -62,7 +62,6 @@ public: 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); @@ -77,6 +76,8 @@ private: // The following APIs are compatible with older versions OH_NN_ReturnCode Run(const std::vector>& inputTensors, std::vector>& outputTensors); + bool CompareAttribute(std::shared_ptr tensorDesc, const NNTensor& tensor) const; + std::shared_ptr BuildNNTensorFromDesc(std::shared_ptr 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, @@ -100,9 +101,6 @@ private: bool isInnerMem; }; bool m_isRun {false}; - std::vector> m_modelInputs; - std::vector> m_modelOutputs; - std::unordered_map> m_outputDimensions; std::unordered_map m_inputTensors; std::unordered_map m_outputTensors; std::unordered_map> m_inputCreatedMem; -- Gitee From 6f32fbf65cd97fe6c41c0410803b743bdb8b05f9 Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 09:18:43 +0800 Subject: [PATCH 17/51] update backend, compilate, upload backend manager --- frameworks/BUILD.gn | 7 +- frameworks/native/backend.h | 9 +- frameworks/native/backend_manager.cpp | 96 ++++ frameworks/native/backend_manager.h | 64 +++ frameworks/native/backend_registrar.cpp | 18 + frameworks/native/backend_registrar.h | 22 + frameworks/native/compilation.h | 17 +- frameworks/native/compiler.h | 11 +- frameworks/native/neural_network_core.cpp | 576 +++++++++++++++++++++- frameworks/native/nnbackend.cpp | 230 +++++++++ frameworks/native/nnbackend.h | 47 ++ frameworks/native/nncompiled_cache.cpp | 441 +++++++++++++++++ frameworks/native/nncompiled_cache.h | 86 ++++ frameworks/native/nncompiler.cpp | 310 ++++++++++++ frameworks/native/nncompiler.h | 48 ++ 15 files changed, 1965 insertions(+), 17 deletions(-) create mode 100644 frameworks/native/backend_manager.cpp create mode 100644 frameworks/native/backend_manager.h create mode 100644 frameworks/native/backend_registrar.cpp create mode 100644 frameworks/native/backend_registrar.h 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 diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index a8b1cd3..7efdff0 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -148,13 +148,18 @@ nnrt_core_sources = [ "native/neural_network_core.cpp", "native/tensor_desc.cpp", "native/validation.cpp", + "native/backend_registrar.cpp", + "native/backend_manager.cpp", + "native/inner_model.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 = [ diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index c6c207b..d448a6c 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -19,12 +19,13 @@ #include #include +#include "compilation.h" #include "compiler.h" #include "compiled.h" #include "executor.h" #include "options.h" #include "tensor.h" -#include "v2_0/neural_network_core_type.h" +#include "interfaces/kits/c/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -33,20 +34,20 @@ public: 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 GetVendorName(std::string& name) = 0; virtual OH_NN_ReturnCode GetVersion(std::string& version) = 0; virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; - virtual Compiler* CreateCompiler() = 0; + virtual Compiler* CreateCompiler(Compilation* compilation) = 0; virtual OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) = 0; virtual Executor* CreateExecutor() = 0; virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; - virtual Tensor* CreateTensor( - const std::string& backendName, OHOS::NeuralNetworkRuntime::TensorDesc* desc) = 0; + virtual Tensor* CreateTensor(const std::string& backendName, TensorDesc* desc) = 0; virtual OH_NN_ReturnCode DestroyTensor(Tensor* tensor) = 0; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp new file mode 100644 index 0000000..a3aa14a --- /dev/null +++ b/frameworks/native/backend_manager.cpp @@ -0,0 +1,96 @@ +#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(); +} + +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=%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 %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_UNAVALIDABLE_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=%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/backend_manager.h b/frameworks/native/backend_manager.h new file mode 100644 index 0000000..32d3fa5 --- /dev/null +++ b/frameworks/native/backend_manager.h @@ -0,0 +1,64 @@ +/* + * 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_MANAGER_H +#define NEURAL_NETWORK_CORE_BACKEND_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include + +#include "backend.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { +class BackendManager { +public: + const std::vector& GetAllBackendsID(); + std::shared_ptr GetBackend(size_t backendID) const; + const std::string& GetBackendName(size_t backendID); + + // Register backend by C++ API + OH_NN_ReturnCode RegisterBackend(std::function()> creator); + + static BackendManager& GetInstance() + { + static BackendManager instance; + return instance; + } + +private: + 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_backendIDs; + // key is the name of backend. + std::unordered_map> m_backends; + std::mutex m_mtx; + + std::string m_tmpBackendName; + std::vector m_tmpBackendIds; +}; +} // 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..884cf48 --- /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_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=%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..d15b4c1 --- /dev/null +++ b/frameworks/native/backend_registrar.h @@ -0,0 +1,22 @@ +#include +#include +#include + +#include "backend.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 \ No newline at end of file diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 837b682..566ba86 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -12,26 +12,35 @@ * 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 +#include +#include + #include "compiler.h" -#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" +#include "interfaces/kits/c/neural_network_runtime_type.h" namespace OHOS { namespace NeuralNetworkRuntime { -struct OH_NNCompilation { - size_t deviceId; +struct Compilation { + size_t backendID; void* nnModel; char* offlineModelPath; std::pair offlineModelBuffer; char* cachePath; uint32_t cacheVersion; + std::pair cacheBuffer; OH_NN_Priority priority; OH_NN_PerformanceMode performance; + bool enableFp16; Compiler* compiler; + std::vector options; + std::unordered_map> configs; }; } // namespace NeuralNetworkRuntime -} +} // namespace OHOS #endif // NEURAL_NETWORK_RUNTIME_COMPILATION_H \ No newline at end of file diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h index be6fb35..7717264 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -15,8 +15,10 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILER_H #define NEURAL_NETWORK_RUNTIME_COMPILER_H -#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" -#include +#include + +#include "interfaces/kits/c/neural_network_runtime_type.h" +#include "cpp_type.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -42,9 +44,8 @@ public: 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 AddExtensionConfig(const char* configName, - const void* configValue, - const size_t configValueSizes) = 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 diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 9dca185..8225841 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -13,16 +13,586 @@ * limitations under the License. */ -#include "interfaces/kits/c/neural_network_runtime/neural_network_core.h" +#include "interfaces/kits/c/neural_network_core.h" + +#include +#include + #include "common/log.h" #include "executor.h" #include "tensor.h" - -#include +#include "inner_model.h" +#include "compilation.h" +#include "backend_manager.h" using namespace OHOS::NeuralNetworkRuntime; #define NNRT_API __attribute__((visibility("default"))) +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 %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: %zu.", deviceID); + return ret; + } + return OH_NN_SUCCESS; +} + +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_NNCompilation_Build before creating compilation."); + 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); + if (nnCompilation == nullptr) { + LOGE("OH_NNCompilation_Construct failed, cast to OH_NNCompilation pointer failed."); + delete compilation; + return nullptr; + } + + return nnCompilation; +} + +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); + if (nnCompilation == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelFile failed, cast to OH_NNCompilation pointer failed."); + delete compilation; + return nullptr; + } + + return nnCompilation; +} + +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); + if (nnCompilation == nullptr) { + LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, cast to OH_NNCompilation pointer failed."); + delete compilation; + return nullptr; + } + + return nnCompilation; +} + +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); + if (nnCompilation == nullptr) { + LOGE("OH_NNCompilation_ConstructForCache failed, cast to OH_NNCompilation pointer failed."); + delete compilation; + return nullptr; + } + + return nnCompilation; +} + +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 == nullptr) { + LOGE("OH_NNCompilation_ExportCacheToBuffer failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + 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; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + if (compilationImpr->compiler == nullptr) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, should call OH_NNCompilation_Build before import cache."); + return OH_NN_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret = compilationImpr->compiler->RestoreFromCacheBuffer(buffer, modelSize); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, fail to import cache from buffer."); + } + + return ret; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_AddExtensionConfig failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + std::string configNameStr = configName; + 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 %s already exists, don't set again.", configName); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_SetDevice failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + compilationImpr->backendID = deviceID; + + return OH_NN_SUCCESS; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_SetCache failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + compilationImpr->cachePath = const_cast(cachePath); + compilationImpr->cacheVersion = version; + + return OH_NN_SUCCESS; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_SetPerformanceMode failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + compilationImpr->performance = performanceMode; + + return OH_NN_SUCCESS; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_SetPriority failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + compilationImpr->priority = priority; + + return OH_NN_SUCCESS; +} + +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); + if (compilationImpr == nullptr) { + LOGE("OH_NNCompilation_EnableFloat16 failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + compilationImpr->enableFp16 = enableFloat16; + + return OH_NN_SUCCESS; +} + +Compiler* CreateCompiler(Compilation* compilation) +{ + if (compilation == nullptr) { + LOGE("CreateCompiler failed, compilation is nullptr."); + return nullptr; + } + + BackendManager& manager = BackendManager::GetInstance(); + std::shared_ptr backend = manager.GetBackend(compilation->backendID); + if(backend == nullptr) { + LOGE("CreateCompiler failed, fail to get backend."); + return nullptr; + } + + Compiler* nnCompiler = backend->CreateCompiler(); + if (nnCompiler == nullptr) { + LOGE("CreateCompiler failed, fail to create compiler."); + return nullptr; + } + + return nnCompiler; +} + +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 = compilation->compiler->SetCacheDir(compilation->cachePath, compilation->cacheVersion); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set cache dir."); + return OH_NN_FAILED; + } + + ret = compilation->compiler->SetEnableFp16(compilation->enableFp16); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set enable fp16."); + return OH_NN_FAILED; + } + + ret = compilation->compiler->SetPerformance(compilation->performance); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set performance."); + return OH_NN_FAILED; + } + + ret = compilation->compiler->SetPriority(compilation->priority); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set priority."); + return OH_NN_FAILED; + } + + ret = compilation->compiler->SetExtensionConfig(compilation->configs); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set extenstion configs."); + return OH_NN_FAILED; + } + + ret = compilation->compiler->SetOptions(compilation->options); + if (ret != OH_NN_SUCCESS) { + LOGE("SetCompilationOptions failed, fail to set extenstion options."); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} + +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 == nullptr) { + LOGE("OH_NNCompilation_Build failed, cast to compilation instance failed."); + return OH_NN_NULL_PTR; + } + + // if ((compilationImpr->nnModel == nullptr) && (compilationImpr->offlineModelPath == nullptr) && + // ((compilationImpr->offlineModelBuffer.first == nullptr) || + // (compilationImpr->offlineModelBuffer.second == static_cast(0)))) { + // LOGE("OH_NNCompilation_Build failed, find no model to build compilation."); + // return OH_NN_INVALID_PARAMETER; + // } + + 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; + } + + Compiler* nnCompiler = CreateCompiler(compilationImpr); + if (nnCompiler == nullptr) { + LOGE("OH_NNCompilation_Build failed, faile to create compiler."); + return OH_NN_FAILED; + } + + compilationImpr->compiler = nnCompiler; + OH_NN_ReturnCode ret = SetCompilationOptions(compilationImpr); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Build failed, faile to create compiler."); + return OH_NN_FAILED; + } + + ret = compilationImpr->compiler->Build(); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Build failed, faile to build compilation."); + return OH_NN_FAILED; + } + + return OH_NN_SUCCESS; +} + +void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) +{ + if (compilation == nullptr) { + LOGE("OH_NNCompilation_Destroy failed, compilation is nullptr."); + } + + if (*compilation == nullptr) { + LOGE("OH_NNCompilation_Destroy failed, compilation is nullptr."); + } + + 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."); + } + + OH_NN_ReturnCode ret = backend->DestroyCompiler(compilationImpr->compiler); + if (ret != OH_NN_SUCCESS) { + LOGE("OH_NNCompilation_Destroy failed, fail to destroy compiler."); + } + } + + 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..a4a4866 --- /dev/null +++ b/frameworks/native/nnbackend.cpp @@ -0,0 +1,230 @@ +#include "nnbackend.h" + +#include +#include "common/log.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_backendID(backendID), + m_device(device) {} + +NNBackend::~NNBackend() +{ + if (m_device != nullptr) { + m_device = nullptr; + } + m_backendName.clear(); +} + +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; +} + +std::string NNBackend::GenUniqueName( + const std::string& deviceName, const std::string& vendorName, const std::string& version) const +{ + return deviceName + "_" + vendorName + "_" + version; +} + +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 OH_NN_FAILED; + } + + 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 OH_NN_FAILED; + } + return OH_NN_SUCCESS; +} + +Compiler* NNBackend::CreateCompiler(Compilation* compilation) +{ + if (compilation == nullptr) { + LOGE("[NNBackend] CreateCompiler failed, compilation is nullptr"); + return OH_NN_INVALID_PARAMETER; + } + + // 如果nnmodel、offlineModelPath、offlineModelBuffer都是空值,构建空的编译器,后续从cache编译模型 + // 如果nnmodel、offlineModelPath、offlineModelBuffer有一项不为空,则从对应模型构建编译器 + NNCompiler* compilerImpl = nullptr; + if ((compilation->nnModel == nullptr) && + (compilation->offlineModelPath == nullptr) && + ((compilation->offlineModelBuffer.first == nullptr) && + (compilation->offlineModelBuffer.second == static_cast(0)))) { + compilerImpl = new (std::nothrow) NNCompiler(); + } else if (compilation->nnModel != nullptr) { + compilerImpl = new (std::nothrow) NNCompiler(compilation->nnModel); + } else if (compilation->offlineModelPath != nullptr) { + compilerImpl = new (std::nothrow) NNCompiler(compilation->offlineModelPath); + } else if (compilation->offlineModelBuffer.first != nullptr && + compilation->offlineModelBuffer.second != static_cast(0)) { + compilerImpl = new (std::nothrow) NNCompiler( + compilation->offlineModelBuffer.first, compilation->offlineModelBuffer.second); + } else { + LOGE("[NNBackend] CreateCompiler failed, compilation model is not valid"); + return OH_NN_INVALID_PARAMETER; + } + + if (compilerImpl == nullptr) { + LOGE("[NNBackend] CreateCompiler failed, error happend when allocating NN Compiler."); + return nullptr; + } + + return reinterpret_cast(compilerImpl); +} + +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() +{ + if (m_preparedModel == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, m_preparedModel is nullptr."); + return nullptr; + } + + std::shared_ptr backend = backendManager.GetBackend(m_backendID); + if (backend == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, backend with backendID %zu is not exist.", m_backendID); + return nullptr; + } + + NNExecutor* nnExecutor = new (std::nothrow) NNExecutor(m_backendID, m_preparedModel, ...); + if (executor == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, error happend when allocating NN Executor."); + return nullptr; + } + + Executor* executor = reinterpret_cast(nnExecutor); + + return executor; +} + +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; + } + + NNTensor* tensorImpl = new (std::nothrow) NNTensor(m_backendID, desc); + if (tensorImpl == nullptr) { + LOGE("[NNBackend] CreateTensor failed, error happend when allocating NN Tensor."); + 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_ReturnCode; +} + +OH_NN_ReturnCode NNBackend::SetDevice(std::shared_ptr device) +{ + m_device = device; + return OH_NN_ReturnCode; +} + +std::shared_ptr NNBackend::GetDevice() const +{ + if (m_device == nullptr) { + LOGE("[NNBackend] GetDevice failed, the device in backend is not available."); + } + + return m_device; +} +} // 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..fd83779 --- /dev/null +++ b/frameworks/native/nnbackend.h @@ -0,0 +1,47 @@ +#include "backend.h" +#include "compiler.h" +#include "executor.h" +#include "tensor.h" +#include "tensor_desc.h" +#include "device.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() = 0; + OH_NN_ReturnCode DestroyExecutor(Executor* executor) override; + + // Create & Destory Tensor + Tensor* CreateTensor(TensorDesc* desc) override; + OH_NN_ReturnCode DestroyTensor(Tensor* tensor) override; + + // Set & Get Device + OH_NN_ReturnCode SetDevice(std::pair> device); + std::shared_ptr GetDevice() const; + +private: + std::string GenUniqueName( + const std::string& deviceName, const std::string& vendorName, const std::string& version) const; + +private: + std::string m_backendID; + std::shared_ptr m_device; +}; +} // NeuralNetworkRuntime +} // OHOS \ 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..260df9b --- /dev/null +++ b/frameworks/native/nncompiled_cache.cpp @@ -0,0 +1,441 @@ +/* + * 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}; + +NNCore_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 NNCORE_INVALID_PARAMETER; + } + + if (m_backendName.empty()) { + LOGE("NNCompiledCache::Save failed, m_backendName is empty."); + return NNCORE_INVALID_PARAMETER; + } + + NNCore_ReturnCode returnCode = GenerateCacheFiles(caches, cacheDir, version); + if (returnCode != NNCORE_SUCCESS) { + LOGE("NNCompiledCache::Save failed, error happened when calling GenerateCacheFiles."); + return returnCode; + } + + LOGI("NNCompiledCache::Save success. %zu caches are saved.", caches.size()); + return NNCORE_SUCCESS; +} + +NNCore_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, + uint32_t version, + std::vector& caches) +{ + if (cacheDir.empty()) { + LOGE("NNCompiledCache::Restore failed, cacheDir is empty."); + return NNCORE_INVALID_PARAMETER; + } + + if (!caches.empty()) { + LOGE("NNCompiledCache::Restore failed, caches is not empty."); + return NNCORE_INVALID_PARAMETER; + } + + if (m_backendName.empty()) { + LOGE("NNCompiledCache::Restore failed, m_backendName is empty."); + return NNCORE_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 NNCORE_INVALID_PATH; + } + + NNCompiledCacheInfo cacheInfo; + NNCore_ReturnCode returnCode = CheckCacheInfo(cacheInfo, cacheInfoPath); + if (returnCode != NNCORE_SUCCESS) { + LOGE("NNCompiledCache::Restore failed, error happened when calling CheckCacheInfo."); + return returnCode; + } + + if ((uint64_t)version != cacheInfo.version) { + LOGE("NNCompiledCache::Restore failed, version is not match. The current version is %u, but the cache files " + "version is %llu.", + version, + cacheInfo.version); + return NNCORE_INVALID_PARAMETER; + } + + 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 NNCORE_INVALID_PATH; + } + + OHOS::NeuralNetworkRuntime::Buffer modelBuffer; + returnCode = ReadCacheModelFile(cacheModelPath, modelBuffer); + if (returnCode != NNCORE_SUCCESS) { + LOGE("NNCompiledCache::Restore failed, error happened when calling ReadCacheModelFile."); + return returnCode; + } + + 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 NNCORE_INVALID_FILE; + } + + caches.emplace_back(std::move(modelBuffer)); + } + + return returnCode; +} + +NNCore_ReturnCode NNCompiledCache::SetBackendName(const std::string& backendName) +{ + if (backendName.empty()) { + LOGE("NNCompiledCache::SetBackend failed, m_backendName is empty."); + return NNCORE_INVALID_PARAMETER; + } + + OHOS::NeuralNetworkCore::BackendManager& backendManager = OHOS::NeuralNetworkCore::BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendName); + if (backend == nullptr) { + LOGE("NNCompiledCache::SetBackend failed, backend with backendName %s is not exist.", backendName.c_str()); + return NNCORE_INVALID_PARAMETER; + } + + std::shared_ptr nnBackend = + std::dynamic_pointer_cast(backend); + m_device = nnBackend->GetDevice(); + if (m_device == nullptr) { + LOGE("NNCompiledCache::SetBackend failed, device with backendName %s is not exist.", backendName.c_str()); + return NNCORE_FAILED; + } + + m_backendID = std::hash{}(backendName); + m_backendName = backendName; + return NNCORE_SUCCESS; +} + +void NNCompiledCache::SetModelName(const std::string& modelName) +{ + m_modelName = modelName; +} + +void NNCompiledCache::SetInputTensorDescs( + std::vector> inputTensorDescs) +{ + m_inputTensorDescs = inputTensorDescs; +} + +void NNCompiledCache::SetOutputTensorDescs( + std::vector> outputTensorDescs) +{ + m_outputTensorDescs = outputTensorDescs; +} + +std::vector> NNCompiledCache::GetInputTensorDescs() const +{ + return m_inputTensorDescs; +} + +std::vector> NNCompiledCache::GetOutputTensorDescs() const +{ + return m_outputTensorDescs; +} + +NNCore_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("Fail to create cacheInfo instance."); + return NNCORE_MEMORY_EXCEPTION; + } + + NNCore_ReturnCode ret = GenerateCacheModel(caches, cacheInfo, cacheDir, version); + if (ret != NNCORE_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 != NNCORE_SUCCESS) { + LOGE("NNCompiledCache::GenerateCacheFiles failed, error happened when calling WriteCacheInfo."); + return ret; + } + + return NNCORE_SUCCESS; +} + +NNCore_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("[Compilation] Model cache file is invalid."); + return NNCORE_INVALID_FILE; + } + + 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("[Compilation] Fail to write cache model."); + cacheModelStream.close(); + return NNCORE_FAILED; + }; + + cacheModelStream.close(); + } + + return NNCORE_SUCCESS; +} + +NNCore_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("[Compilation] Model cache info file is invalid."); + return NNCORE_INVALID_FILE; + } + + if (!cacheInfoStream.write(reinterpret_cast(cacheInfo.get()), cacheSize)) { + LOGE("[Compilation] Fail to write cache info."); + cacheInfoStream.close(); + return NNCORE_FAILED; + } + + cacheInfoStream.close(); + return NNCORE_SUCCESS; +} + +NNCore_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 NNCORE_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 NNCORE_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=%zu in the cache files is different from current " + "deviceId=%zu," + "please change the cache directory or current deviceId.", + deviceId, + m_backendID); + infoCacheFile.close(); + return NNCORE_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 NNCORE_INVALID_FILE; + } + + for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { + modelCacheInfo.modelCheckSum[i] = static_cast(modelCheckSum[i]); + } + + return NNCORE_SUCCESS; +} + +NNCore_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, + OHOS::NeuralNetworkRuntime::Buffer& cache) const +{ + // filePath is validate in NNCompiledCache::Restore, no need to check twice. + std::ifstream ifs(filePath.c_str(), std::ios::in | std::ios::binary); + if (!ifs) { + LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); + return NNCORE_INVALID_FILE; + } + + int fsize{-1}; + NNCore_ReturnCode returnCode = GetCacheFileLength(ifs, fsize); + if (returnCode != NNCORE_SUCCESS) { + ifs.close(); + LOGE("Get file %{public}s length fialed.", filePath.c_str()); + return returnCode; + } + + ifs.seekg(0, std::ios::beg); + if (!ifs.good()) { + LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); + ifs.close(); + return NNCORE_INVALID_FILE; + } + + char* ptr = static_cast(m_device->AllocateBuffer(fsize)); + if (ptr == nullptr) { + LOGE("NNCompiledCache::ReadCacheModelFile failed, failed to allocate memory."); + ifs.close(); + return NNCORE_MEMORY_EXCEPTION; + } + + ifs.read(ptr, fsize); + if (!ifs.good()) { + LOGE("NNCompiledCache::ReadCacheModelFile failed, failed to read file."); + ifs.close(); + m_device->ReleaseBuffer(ptr); + ptr = nullptr; + return NNCORE_INVALID_FILE; + } + + ifs.close(); + cache.data = ptr; + cache.length = static_cast(fsize); // fsize should be non-negative, safe to cast. + return NNCORE_SUCCESS; +} + +NNCore_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const +{ + std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; + if (remove(cacheInfoPath.c_str()) == -1) { + LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", + cacheInfoPath.c_str()); + return NNCORE_FAILED; + } + LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove %s.", cacheInfoPath.c_str()); + + for (uint32_t i = 0; i < fileNumber; ++i) { + std::string fileName = m_modelName + std::to_string(i) + ".nncache"; + std::string cacheModelPath = cacheDir + fileName; + if (access(cacheModelPath.c_str(), 0) != 0) { + LOGW("The file %s does not exist, no need to delete the file.", cacheModelPath.c_str()); + continue; + } + + if (remove(cacheModelPath.c_str()) == -1) { + LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", + cacheModelPath.c_str()); + return NNCORE_FAILED; + } + LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove the file %s", cacheModelPath.c_str()); + } + return NNCORE_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; +} + +NNCore_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fileSize) const +{ + ifs.seekg(0, std::ios::end); + if (!ifs.good()) { + LOGE("NNCompiledCache::GetCacheFileLength fail to set the position of the next character to be extracted from " + "the input stream."); + return NNCORE_FAILED; + } + + int handleValue = ifs.tellg(); + if (handleValue == -1) { + LOGE("Compiled::GetCacheFileLength fail to get position of the input stream."); + return NNCORE_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 NNCORE_INVALID_FILE; + } + + fileSize = handleValue; + return NNCORE_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..9209601 --- /dev/null +++ b/frameworks/native/nncompiled_cache.h @@ -0,0 +1,86 @@ +/* + * 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 "compat/device.h" +#include "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; + + NNCore_ReturnCode Save(const std::vector& caches, + const std::string& cacheDir, + uint32_t version); + NNCore_ReturnCode Restore(const std::string& cacheDir, + uint32_t version, + std::vector& caches); + + NNCore_ReturnCode SetBackendName(const std::string& backendName); + void SetModelName(const std::string& modelName); + void SetInputTensorDescs(std::vector> inputTensorDescs); + void SetOutputTensorDescs(std::vector> outputTensorDescs); + std::vector> GetInputTensorDescs() const; + std::vector> GetOutputTensorDescs() const; + +private: + NNCore_ReturnCode GenerateCacheFiles(const std::vector& caches, + const std::string& cacheDir, + uint32_t version) const; + NNCore_ReturnCode GenerateCacheModel(const std::vector& caches, + std::unique_ptr& cacheInfo, + const std::string& cacheDir, + uint32_t version) const; + NNCore_ReturnCode WriteCacheInfo(uint32_t cacheSize, + std::unique_ptr& cacheInfo, + const std::string& cacheDir) const; + NNCore_ReturnCode CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const; + NNCore_ReturnCode ReadCacheModelFile(const std::string& file, OHOS::NeuralNetworkRuntime::Buffer& cache) const; + NNCore_ReturnCode RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const; + unsigned short GetCrc16(const unsigned char* buffer, size_t length) const; + NNCore_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fileSize) const; + +private: + size_t m_backendID{0}; + std::string m_backendName; + std::string m_modelName; + std::shared_ptr m_device{nullptr}; + std::vector> m_inputTensorDescs; + std::vector> m_outputTensorDescs; +}; + +} // 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..a1ca2d6 --- /dev/null +++ b/frameworks/native/nncompiler.cpp @@ -0,0 +1,310 @@ +#include "nncompiler.h" + +#include +#include +#include + +#include "mindir.h" +#include "validation.h" +#include "nncompiled_cache.h" + +namespace OHOS { +namespace NeuralNetworkRuntime { + +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_innerModel(model), + m_device(device), + m_backendID(backendID) {} + +NNCompiler::~NNCompiler() +{ + if (m_prepareModel != nullptr) { + delete m_prepareModel; + m_prepareModel = nullptr; + } +} + +size_t NNCompiler::GetBackendID() const +{ + return m_backendID; +} + +OH_NN_ReturnCode NNCompiler::SetCacheDir(const std::string& cacheModelPath, uint32_t version) +{ + m_cacheDir = 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, 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("[NNCompiler] SetPerformance failed, fail to call device."); + return OH_NN_FAILED; + } + + if (!isSupportedPerformance) { + 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=%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, 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("[NNCompiler] SetPriority failed, fail to call device."); + return OH_NN_FAILED; + } + + if (!isSupportedPriority) { + 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=%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, 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("[NNCompiler] SetEnableFp16 failed, fail to call device."); + return OH_NN_FAILED; + } + + if (!isSupportedFp16) { + LOGE("[NNCompiler] SetEnableFp16 failed, this device is not support float16 precision setting."); + return OH_NN_OPERATION_FORBIDDEN; + } + + m_enableFp16 = isFp16; + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::Build() +{ + return OH_NN_SUCCESS; +} + +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; + 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; + + 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); + + Buffer outputTensorDescBuffer; + ret = SerializeTensorsToBuffer(m_outputTensorDescs, outputTensorDescBuffer); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing output tensor desc."); + return ret; + } + caches.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."); + return ret; + } + + 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; + + std::vector caches; + OH_NN_ReturnCode ret = compiledCache.Restore(m_cachePath, m_cacheVersion, caches); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when restoring model cache."); + 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."); + 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."); + return ret; + } + + // TODO: Add NNOption check here. + ModelConfig config; + config.enableFloat16 = m_enableFp16; + config.mode = m_performance; + config.priority = m_priority; + std::vector modelOnlyCaches(caches.begin(), caches.end()-2); + OH_NN_ReturnCode ret = m_device->PrepareModelFromModelCache(modelOnlyCaches, config, m_preparedModel); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when preparing model from cache."); + return ret; + } + + LOGI("[Compilation] Restore model cache successfully."); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SaveToCacheBuffer(const void* buffer, size_t length, size_t* modelSize) const +{ + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::RestoreFromCacheBuffer(const void* buffer, size_t length) +{ + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& configs) +{ + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector& options) +{ + LOGE("[NNCompiler] SetOptions failed, NN compiler don't support set extentsion options."); + return OH_NN_OPERATION_FORBIDDEN; +} + + + + +OH_NN_ReturnCode NNCompiler::Build(const void* model, Compiled** compiled) +{ + if (m_isBuild) { + LOGE("[NNCompiler] Cannot build again."); + return NNCORE_OPERATION_FORBIDDEN; + } + + const InnerModel* innerModel = reinterpret_cast(model); + std::shared_ptr liteGraph = innerModel->GetLiteGraphs(); + std::vector> inputTensors = innerModel->GetInputTensors(); + std::vector> outputTensors = innerModel->GetOutputTensors(); + void* metaGraph = innerModel->GetMetaGraph(); + Buffer quantBuffer = innerModel->GetQuantBuffer(); + + if ((liteGraph == nullptr) && (metaGraph == nullptr)) { + LOGE("[NNCompiler] Both liteGraph and metaGraph are nullptr."); + return NNCORE_INVALID_PARAMETER; + } + + if ((liteGraph != nullptr) && (metaGraph != nullptr)) { + LOGE("[NNCompiler] Neither liteGraph nor metaGraph are nullptr."); + return NNCORE_INVALID_PARAMETER; + } + + OH_NN_ReturnCode ret {OH_NN_FAILED}; + ModelConfig config {m_enableFp16, static_cast(m_performance), + static_cast(m_priority)}; + std::shared_ptr preparedModel = nullptr; + if (liteGraph != nullptr) { + ret = m_device->PrepareModel(liteGraph, config, preparedModel); + } + if (metaGraph != nullptr) { + ret = m_device->PrepareModel(metaGraph, quantBuffer, config, preparedModel); + } + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Preparing model failed when normally building."); + return NNCORE_FAILED; + } + + NNCompiler* NNCompiler = new (std::nothrow) NNCompiler( + m_backendName, preparedModel, inputTensors, outputTensors, m_device); + if (NNCompiler == nullptr) { + LOGE("[NNCompiler] Create nn compiled failed."); + return NNCORE_NULL_PTR; + } + NNCompiler->SetCompiledOptions(m_options); + *compiled = reinterpret_cast(NNCompiler); + + return NNCORE_SUCCESS; +} +} // 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..511e640 --- /dev/null +++ b/frameworks/native/nncompiler.h @@ -0,0 +1,48 @@ +#include "compiler.h" + +#include "device.h" +#include "inner_model.h" +#include "prepared_model.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() = default; + + 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; + + 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; + +private: + void* m_innerModel; + bool m_isBuild {false}; + bool m_enableFp16 {false}; + size_t m_backendID; + bool m_isBuild {false}; + std::string m_cachePath; + uint32_t m_cacheVersion; + std::shared_ptr m_device; + PreparedModel* m_prepareModel {nullptr}; + OH_NN_Priority m_priority {OH_NN_PRIORITY_NONE}; + OH_NN_PerformanceMode m_performance {OH_NN_PERFORMANCE_NONE}; +}; +} // NeuralNetworkRuntime +} // OHOS \ No newline at end of file -- Gitee From 263de58bc3ce59a50f1677494e787999864e7902 Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 09:31:14 +0800 Subject: [PATCH 18/51] update backend --- frameworks/native/nnbackend.cpp | 21 ++++++--------------- frameworks/native/nnbackend.h | 1 + 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index a4a4866..cea6120 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -104,24 +104,15 @@ Compiler* NNBackend::CreateCompiler(Compilation* compilation) return OH_NN_INVALID_PARAMETER; } - // 如果nnmodel、offlineModelPath、offlineModelBuffer都是空值,构建空的编译器,后续从cache编译模型 - // 如果nnmodel、offlineModelPath、offlineModelBuffer有一项不为空,则从对应模型构建编译器 + // 如果nnmodel是空值,构建空的编译器,后续从cache编译模型, + // 如果nnmodel不为空,则从对应模型构建编译器 NNCompiler* compilerImpl = nullptr; - if ((compilation->nnModel == nullptr) && - (compilation->offlineModelPath == nullptr) && - ((compilation->offlineModelBuffer.first == nullptr) && - (compilation->offlineModelBuffer.second == static_cast(0)))) { - compilerImpl = new (std::nothrow) NNCompiler(); + if (compilation->nnModel == nullptr) { + compilerImpl = new (std::nothrow) NNCompiler(m_device, m_backendID); } else if (compilation->nnModel != nullptr) { - compilerImpl = new (std::nothrow) NNCompiler(compilation->nnModel); - } else if (compilation->offlineModelPath != nullptr) { - compilerImpl = new (std::nothrow) NNCompiler(compilation->offlineModelPath); - } else if (compilation->offlineModelBuffer.first != nullptr && - compilation->offlineModelBuffer.second != static_cast(0)) { - compilerImpl = new (std::nothrow) NNCompiler( - compilation->offlineModelBuffer.first, compilation->offlineModelBuffer.second); + compilerImpl = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); } else { - LOGE("[NNBackend] CreateCompiler failed, compilation model is not valid"); + LOGE("[NNBackend] CreateCompiler failed, only support build NN model and NN model cache."); return OH_NN_INVALID_PARAMETER; } diff --git a/frameworks/native/nnbackend.h b/frameworks/native/nnbackend.h index fd83779..82475fe 100644 --- a/frameworks/native/nnbackend.h +++ b/frameworks/native/nnbackend.h @@ -42,6 +42,7 @@ private: private: std::string m_backendID; std::shared_ptr m_device; + std::shared_ptr m_preparedModel {nullptr}; }; } // NeuralNetworkRuntime } // OHOS \ No newline at end of file -- Gitee From be6a183e409aebdd2861da76023d77b6f639fd1e Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 09:41:00 +0800 Subject: [PATCH 19/51] update nncore, delete inner_model --- frameworks/BUILD.gn | 1 - frameworks/native/neural_network_core.cpp | 7 ------- 2 files changed, 8 deletions(-) diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 7efdff0..0def39f 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -150,7 +150,6 @@ nnrt_core_sources = [ "native/validation.cpp", "native/backend_registrar.cpp", "native/backend_manager.cpp", - "native/inner_model.cpp", ] ohos_shared_library("libneural_network_core") { diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 8225841..69afcc3 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -21,7 +21,6 @@ #include "common/log.h" #include "executor.h" #include "tensor.h" -#include "inner_model.h" #include "compilation.h" #include "backend_manager.h" @@ -114,12 +113,6 @@ OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) 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_NNCompilation_Build before creating compilation."); - return nullptr; - } Compilation *compilation = new (std::nothrow) Compilation(); if (compilation == nullptr) { -- Gitee From e20514a132687a19ae07242a2707f86e6265ecce Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 15:10:20 +0800 Subject: [PATCH 20/51] 1207, upload backend/compilation --- common/utils.h | 6 + frameworks/BUILD.gn | 15 +- frameworks/native/backend.h | 8 +- frameworks/native/backend_registrar.cpp | 2 +- frameworks/native/compilation.h | 2 +- frameworks/native/compiler.h | 2 +- frameworks/native/inner_model.cpp | 26 ++ frameworks/native/inner_model.h | 3 + frameworks/native/neural_network_core.cpp | 4 +- frameworks/native/nn_tensor.cpp | 9 +- frameworks/native/nn_tensor.h | 2 + frameworks/native/nnbackend.cpp | 69 ++-- frameworks/native/nnbackend.h | 21 +- frameworks/native/nncompiled_cache.cpp | 163 +++++---- frameworks/native/nncompiled_cache.h | 43 ++- frameworks/native/nncompiler.cpp | 309 +++++++++++++++--- frameworks/native/nncompiler.h | 32 +- .../native/register_hdi_device_v1_0.cpp | 60 ++++ .../native/register_hdi_device_v2_0.cpp | 77 +++++ 19 files changed, 627 insertions(+), 226 deletions(-) create mode 100644 frameworks/native/register_hdi_device_v1_0.cpp create mode 100644 frameworks/native/register_hdi_device_v2_0.cpp diff --git a/common/utils.h b/common/utils.h index 7430ad0..7db891b 100644 --- a/common/utils.h +++ b/common/utils.h @@ -35,6 +35,12 @@ std::shared_ptr CreateSharedPtr(Args&&... args) return tPtr; } +std::string GenUniqueName( + const std::string& deviceName, const std::string& vendorName, const std::string& version) +{ + return deviceName + "_" + vendorName + "_" + version; +} + } // namespace NeuralNetworkRuntime } // namespace OHOS #endif // NEURAL_NETWORK_RUNTIME_UTILS_H diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 0def39f..3f57a0b 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -23,10 +23,10 @@ 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/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", @@ -44,7 +44,12 @@ nnrt_sources = [ "native/ops_registry.cpp", "native/transform.cpp", "native/validation.cpp", - "native/quant_param.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 = [ diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index d448a6c..82bdb4d 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -21,11 +21,9 @@ #include "compilation.h" #include "compiler.h" -#include "compiled.h" #include "executor.h" -#include "options.h" #include "tensor.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 { @@ -36,8 +34,6 @@ public: virtual size_t GetBackendID() const = 0; virtual OH_NN_ReturnCode GetBackendName(std::string& name) const = 0; - virtual OH_NN_ReturnCode GetVendorName(std::string& name) = 0; - virtual OH_NN_ReturnCode GetVersion(std::string& version) = 0; virtual OH_NN_ReturnCode GetBackendType(OH_NN_DeviceType& backendType) const = 0; virtual OH_NN_ReturnCode GetBackendStatus(DeviceStatus& status) const = 0; @@ -47,7 +43,7 @@ public: virtual Executor* CreateExecutor() = 0; virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; - virtual Tensor* CreateTensor(const std::string& backendName, TensorDesc* desc) = 0; + virtual Tensor* CreateTensor(TensorDesc* desc) = 0; virtual OH_NN_ReturnCode DestroyTensor(Tensor* tensor) = 0; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/backend_registrar.cpp b/frameworks/native/backend_registrar.cpp index 884cf48..b50ed87 100644 --- a/frameworks/native/backend_registrar.cpp +++ b/frameworks/native/backend_registrar.cpp @@ -2,7 +2,7 @@ #include "common/log.h" #include "backend_manager.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/compilation.h b/frameworks/native/compilation.h index 566ba86..ff3972c 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -21,7 +21,7 @@ #include #include "compiler.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/compiler.h b/frameworks/native/compiler.h index 7717264..72ae99f 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -17,7 +17,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 { diff --git a/frameworks/native/inner_model.cpp b/frameworks/native/inner_model.cpp index e098816..9d74dcc 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -718,6 +718,32 @@ std::vector> InnerModel::GetOutputTensors() const return m_outputTensors; } +std::vector> InnerModel::GetInputTensorDescs() const +{ + std::vector> inputTensorDescs; + std::shared_ptr tensorDesc; + for (auto inputTensor : m_inputTensors) { + tensorDesc = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + inputTensor->ConvertToTensorDesc(*(tensorDesc.get())); + inputTensorDescs.emplace_back(tensorDesc); + } + + return inputTensorDescs; +} + +std::vector> InnerModel::GetOutputTensorDescs() const +{ + std::vector> outputTensorDescs; + std::shared_ptr tensorDesc; + for (auto outputTensor : m_outputTensors) { + tensorDesc = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + outputTensor->ConvertToTensorDesc(*(tensorDesc.get())); + outputTensorDescs.emplace_back(tensorDesc); + } + + return outputTensorDescs; +} + void* InnerModel::GetMetaGraph() const { return m_metaGraph; diff --git a/frameworks/native/inner_model.h b/frameworks/native/inner_model.h index a5baf9a..2c54c5a 100644 --- a/frameworks/native/inner_model.h +++ b/frameworks/native/inner_model.h @@ -21,6 +21,7 @@ #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/neural_network_runtime.h" @@ -51,6 +52,8 @@ public: OH_NN_ReturnCode Build(); std::vector> GetInputTensors() const; std::vector> GetOutputTensors() const; + std::vector> GetInputTensorDescs() const; + std::vector> GetOutputTensorDescs() const; std::shared_ptr GetLiteGraphs() const; void* GetMetaGraph() const; Buffer GetQuantBuffer() const; diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 69afcc3..a0feace 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "interfaces/kits/c/neural_network_core.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_core.h" #include #include @@ -445,7 +445,7 @@ Compiler* CreateCompiler(Compilation* compilation) return nullptr; } - Compiler* nnCompiler = backend->CreateCompiler(); + Compiler* nnCompiler = backend->CreateCompiler(compilation); if (nnCompiler == nullptr) { LOGE("CreateCompiler failed, fail to create compiler."); return nullptr; diff --git a/frameworks/native/nn_tensor.cpp b/frameworks/native/nn_tensor.cpp index 18290f8..0b2f019 100644 --- a/frameworks/native/nn_tensor.cpp +++ b/frameworks/native/nn_tensor.cpp @@ -23,7 +23,6 @@ #include "common/log.h" #include "mindir.h" #include "mindir_types.h" -#include "tensor_desc.h" #include "quant_param.h" namespace OHOS { @@ -455,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 ef4a2b7..f2d091d 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -22,6 +22,7 @@ #include "cpp_type.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 { @@ -70,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; diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index cea6120..4194152 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -12,15 +12,18 @@ namespace OHOS { namespace NeuralNetworkRuntime { NNBackend::NNBackend(const std::shared_ptr& device, size_t backendID) - : m_backendID(backendID), - m_device(device) {} + : m_device(device), + m_backendID(backendID) {} NNBackend::~NNBackend() { + if (m_nnCompiler != nullptr) { + DestroyCompiler(reinterpret_cast(m_nnCompiler)); + } + if (m_device != nullptr) { m_device = nullptr; } - m_backendName.clear(); } size_t NNBackend::GetBackendID() const @@ -101,27 +104,26 @@ Compiler* NNBackend::CreateCompiler(Compilation* compilation) { if (compilation == nullptr) { LOGE("[NNBackend] CreateCompiler failed, compilation is nullptr"); - return OH_NN_INVALID_PARAMETER; + return nullptr; } // 如果nnmodel是空值,构建空的编译器,后续从cache编译模型, // 如果nnmodel不为空,则从对应模型构建编译器 - NNCompiler* compilerImpl = nullptr; if (compilation->nnModel == nullptr) { - compilerImpl = new (std::nothrow) NNCompiler(m_device, m_backendID); + m_nnCompiler = new (std::nothrow) NNCompiler(m_device, m_backendID); } else if (compilation->nnModel != nullptr) { - compilerImpl = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); + m_nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); } else { LOGE("[NNBackend] CreateCompiler failed, only support build NN model and NN model cache."); - return OH_NN_INVALID_PARAMETER; + return nullptr; } - if (compilerImpl == nullptr) { + if (m_nnCompiler == nullptr) { LOGE("[NNBackend] CreateCompiler failed, error happend when allocating NN Compiler."); return nullptr; } - return reinterpret_cast(compilerImpl); + return reinterpret_cast(m_nnCompiler); } OH_NN_ReturnCode NNBackend::DestroyCompiler(Compiler* compiler) @@ -139,26 +141,18 @@ OH_NN_ReturnCode NNBackend::DestroyCompiler(Compiler* compiler) Executor* NNBackend::CreateExecutor() { - if (m_preparedModel == nullptr) { - LOGE("[NNBackend] CreateExecutor failed, m_preparedModel is nullptr."); + if (m_nnCompiler == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, m_nnCompiler is nullptr, please create compiler first."); return nullptr; } - std::shared_ptr backend = backendManager.GetBackend(m_backendID); - if (backend == nullptr) { - LOGE("[NNBackend] CreateExecutor failed, backend with backendID %zu is not exist.", m_backendID); + NNExecutor* nnExecutor = m_nnCompiler->CreateExecutor(); + if (nnExecutor == nullptr) { + LOGE("[NNBackend] CreateExecutor failed, fail to create NN Executor."); return nullptr; } - NNExecutor* nnExecutor = new (std::nothrow) NNExecutor(m_backendID, m_preparedModel, ...); - if (executor == nullptr) { - LOGE("[NNBackend] CreateExecutor failed, error happend when allocating NN Executor."); - return nullptr; - } - - Executor* executor = reinterpret_cast(nnExecutor); - - return executor; + return reinterpret_cast(nnExecutor); } OH_NN_ReturnCode NNBackend::DestroyExecutor(Executor* executor) @@ -168,9 +162,19 @@ OH_NN_ReturnCode NNBackend::DestroyExecutor(Executor* executor) return OH_NN_INVALID_PARAMETER; } - delete executor; - executor = nullptr; + if (m_nnCompiler == nullptr) { + LOGE("[NNBackend] DestroyExecutor failed, m_nnCompiler is nullptr, please create compiler first."); + return OH_NN_FAILED; + } + + NNExecutor* nnExecutor = reinterpret_cast(executor); + OH_NN_ReturnCode ret = m_nnCompiler->DestroyExecutor(nnExecutor); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNBackend] DestroyExecutor failed, fail to destroy NN executor."); + return OH_NN_FAILED; + } + executor = nullptr; return OH_NN_SUCCESS; } @@ -181,7 +185,7 @@ Tensor* NNBackend::CreateTensor(TensorDesc* desc) return nullptr; } - NNTensor* tensorImpl = new (std::nothrow) NNTensor(m_backendID, desc); + NNTensor2_0* tensorImpl = new (std::nothrow) NNTensor2_0(m_backendID, desc); if (tensorImpl == nullptr) { LOGE("[NNBackend] CreateTensor failed, error happend when allocating NN Tensor."); return nullptr; @@ -200,21 +204,14 @@ OH_NN_ReturnCode NNBackend::DestroyTensor(Tensor* tensor) delete tensor; tensor = nullptr; - return OH_NN_ReturnCode; -} - -OH_NN_ReturnCode NNBackend::SetDevice(std::shared_ptr device) -{ - m_device = device; - return OH_NN_ReturnCode; + return OH_NN_SUCCESS; } std::shared_ptr NNBackend::GetDevice() const { if (m_device == nullptr) { - LOGE("[NNBackend] GetDevice failed, the device in backend is not available."); + LOGE("[NNBackend] GetDevice failed, m_device is nullptr."); } - return m_device; } } // NeuralNetworkRuntime diff --git a/frameworks/native/nnbackend.h b/frameworks/native/nnbackend.h index 82475fe..a442a68 100644 --- a/frameworks/native/nnbackend.h +++ b/frameworks/native/nnbackend.h @@ -1,16 +1,18 @@ #include "backend.h" -#include "compiler.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); + explicit NNBackend(const std::shared_ptr& device, size_t backendID); ~NNBackend(); // Backend Info @@ -24,15 +26,14 @@ public: OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) override; // Create & Destory Executor - Executor* CreateExecutor() = 0; + Executor* CreateExecutor() override; OH_NN_ReturnCode DestroyExecutor(Executor* executor) override; // Create & Destory Tensor Tensor* CreateTensor(TensorDesc* desc) override; OH_NN_ReturnCode DestroyTensor(Tensor* tensor) override; - // Set & Get Device - OH_NN_ReturnCode SetDevice(std::pair> device); + // Get device std::shared_ptr GetDevice() const; private: @@ -40,9 +41,11 @@ private: const std::string& deviceName, const std::string& vendorName, const std::string& version) const; private: - std::string m_backendID; std::shared_ptr m_device; - std::shared_ptr m_preparedModel {nullptr}; + size_t m_backendID; + NNCompiler* m_nnCompiler {nullptr}; }; } // NeuralNetworkRuntime -} // OHOS \ No newline at end of file +} // 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 index 260df9b..de8ed12 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -53,60 +53,60 @@ static const unsigned short CRC16_TAB[256] = { 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; -NNCore_ReturnCode NNCompiledCache::Save(const std::vector& caches, +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 NNCORE_INVALID_PARAMETER; + return OH_NN_INVALID_PARAMETER; } - if (m_backendName.empty()) { - LOGE("NNCompiledCache::Save failed, m_backendName is empty."); - return NNCORE_INVALID_PARAMETER; + if (m_device == nullptr) { + LOGE("NNCompiledCache::Save failed, m_device is empty."); + return OH_NN_INVALID_PARAMETER; } - NNCore_ReturnCode returnCode = GenerateCacheFiles(caches, cacheDir, version); - if (returnCode != NNCORE_SUCCESS) { + OH_NN_ReturnCode ret = GenerateCacheFiles(caches, cacheDir, version); + if (ret != OH_NN_SUCCESS) { LOGE("NNCompiledCache::Save failed, error happened when calling GenerateCacheFiles."); - return returnCode; + return ret; } LOGI("NNCompiledCache::Save success. %zu caches are saved.", caches.size()); - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, +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 NNCORE_INVALID_PARAMETER; + return OH_NN_INVALID_PARAMETER; } if (!caches.empty()) { LOGE("NNCompiledCache::Restore failed, caches is not empty."); - return NNCORE_INVALID_PARAMETER; + return OH_NN_INVALID_PARAMETER; } - if (m_backendName.empty()) { - LOGE("NNCompiledCache::Restore failed, m_backendName is empty."); - return NNCORE_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 NNCORE_INVALID_PATH; + return OH_NN_INVALID_PARAMETER; } NNCompiledCacheInfo cacheInfo; - NNCore_ReturnCode returnCode = CheckCacheInfo(cacheInfo, cacheInfoPath); - if (returnCode != NNCORE_SUCCESS) { + OH_NN_ReturnCode ret = CheckCacheInfo(cacheInfo, cacheInfoPath); + if (ret != OH_NN_SUCCESS) { LOGE("NNCompiledCache::Restore failed, error happened when calling CheckCacheInfo."); - return returnCode; + return ret; } if ((uint64_t)version != cacheInfo.version) { @@ -114,60 +114,53 @@ NNCore_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, "version is %llu.", version, cacheInfo.version); - return NNCORE_INVALID_PARAMETER; + return OH_NN_INVALID_PARAMETER; } 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 NNCORE_INVALID_PATH; + return OH_NN_INVALID_PARAMETER; } OHOS::NeuralNetworkRuntime::Buffer modelBuffer; - returnCode = ReadCacheModelFile(cacheModelPath, modelBuffer); - if (returnCode != NNCORE_SUCCESS) { + ret = ReadCacheModelFile(cacheModelPath, modelBuffer); + if (ret != OH_NN_SUCCESS) { LOGE("NNCompiledCache::Restore failed, error happened when calling ReadCacheModelFile."); - return returnCode; + 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 NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } caches.emplace_back(std::move(modelBuffer)); } - return returnCode; + return ret; } -NNCore_ReturnCode NNCompiledCache::SetBackendName(const std::string& backendName) +OH_NN_ReturnCode NNCompiledCache::SetBackend(size_t backendID) { - if (backendName.empty()) { - LOGE("NNCompiledCache::SetBackend failed, m_backendName is empty."); - return NNCORE_INVALID_PARAMETER; - } - - OHOS::NeuralNetworkCore::BackendManager& backendManager = OHOS::NeuralNetworkCore::BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(backendName); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(backendID); if (backend == nullptr) { - LOGE("NNCompiledCache::SetBackend failed, backend with backendName %s is not exist.", backendName.c_str()); - return NNCORE_INVALID_PARAMETER; + LOGE("[NNCompiledCache] SetBackend failed, backend with backendID %zu is not exist.", backendID); + return OH_NN_INVALID_PARAMETER; } - std::shared_ptr nnBackend = - std::dynamic_pointer_cast(backend); + std::shared_ptr nnBackend = std::reinterpret_pointer_cast(backend); m_device = nnBackend->GetDevice(); if (m_device == nullptr) { - LOGE("NNCompiledCache::SetBackend failed, device with backendName %s is not exist.", backendName.c_str()); - return NNCORE_FAILED; + LOGE("[NNCompiledCache] SetBackend failed, device with backendID %zu is not exist.", backendID); + return OH_NN_FAILED; } - m_backendID = std::hash{}(backendName); - m_backendName = backendName; - return NNCORE_SUCCESS; + m_backendID = backendID; + return OH_NN_SUCCESS; } void NNCompiledCache::SetModelName(const std::string& modelName) @@ -176,28 +169,28 @@ void NNCompiledCache::SetModelName(const std::string& modelName) } void NNCompiledCache::SetInputTensorDescs( - std::vector> inputTensorDescs) + std::vector> inputTensorDescs) { m_inputTensorDescs = inputTensorDescs; } void NNCompiledCache::SetOutputTensorDescs( - std::vector> outputTensorDescs) + std::vector> outputTensorDescs) { m_outputTensorDescs = outputTensorDescs; } -std::vector> NNCompiledCache::GetInputTensorDescs() const +std::vector> NNCompiledCache::GetInputTensorDescs() const { return m_inputTensorDescs; } -std::vector> NNCompiledCache::GetOutputTensorDescs() const +std::vector> NNCompiledCache::GetOutputTensorDescs() const { return m_outputTensorDescs; } -NNCore_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, +OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, const std::string& cacheDir, uint32_t version) const { @@ -206,26 +199,26 @@ NNCore_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector cacheInfo = std::make_unique(cacheSize); if (cacheInfo == nullptr) { LOGE("Fail to create cacheInfo instance."); - return NNCORE_MEMORY_EXCEPTION; + return OH_NN_MEMORY_ERROR; } - NNCore_ReturnCode ret = GenerateCacheModel(caches, cacheInfo, cacheDir, version); - if (ret != NNCORE_SUCCESS) { + 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 != NNCORE_SUCCESS) { + if (ret != OH_NN_SUCCESS) { LOGE("NNCompiledCache::GenerateCacheFiles failed, error happened when calling WriteCacheInfo."); return ret; } - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector& caches, +OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector& caches, std::unique_ptr& cacheInfo, const std::string& cacheDir, uint32_t version) const @@ -242,7 +235,7 @@ NNCore_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector(caches[i].data), caches[i].length)) { LOGE("[Compilation] Fail to write cache model."); cacheModelStream.close(); - return NNCORE_FAILED; + return OH_NN_FAILED; }; cacheModelStream.close(); } - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, +OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, std::unique_ptr& cacheInfo, const std::string& cacheDir) const { @@ -268,34 +261,34 @@ NNCore_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, 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 NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } if (!cacheInfoStream.write(reinterpret_cast(cacheInfo.get()), cacheSize)) { LOGE("[Compilation] Fail to write cache info."); cacheInfoStream.close(); - return NNCORE_FAILED; + return OH_NN_FAILED; } cacheInfoStream.close(); - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, +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 NNCORE_INVALID_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 NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } // modelCacheInfo.deviceId type is int64_t, @@ -308,7 +301,7 @@ NNCore_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCach deviceId, m_backendID); infoCacheFile.close(); - return NNCORE_INVALID_PARAMETER; + return OH_NN_INVALID_PARAMETER; } std::vector modelCheckSum; @@ -317,46 +310,46 @@ NNCore_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCach 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 NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { modelCacheInfo.modelCheckSum[i] = static_cast(modelCheckSum[i]); } - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, +OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, OHOS::NeuralNetworkRuntime::Buffer& cache) const { // filePath is validate in NNCompiledCache::Restore, no need to check twice. std::ifstream ifs(filePath.c_str(), std::ios::in | std::ios::binary); if (!ifs) { LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); - return NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } int fsize{-1}; - NNCore_ReturnCode returnCode = GetCacheFileLength(ifs, fsize); - if (returnCode != NNCORE_SUCCESS) { + OH_NN_ReturnCode ret = GetCacheFileLength(ifs, fsize); + if (ret != OH_NN_SUCCESS) { ifs.close(); LOGE("Get file %{public}s length fialed.", filePath.c_str()); - return returnCode; + return ret; } ifs.seekg(0, std::ios::beg); if (!ifs.good()) { LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); ifs.close(); - return NNCORE_INVALID_FILE; + 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 NNCORE_MEMORY_EXCEPTION; + return OH_NN_MEMORY_ERROR; } ifs.read(ptr, fsize); @@ -365,22 +358,22 @@ NNCore_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePat ifs.close(); m_device->ReleaseBuffer(ptr); ptr = nullptr; - return NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } ifs.close(); cache.data = ptr; cache.length = static_cast(fsize); // fsize should be non-negative, safe to cast. - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } -NNCore_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const +OH_NN_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const { std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; if (remove(cacheInfoPath.c_str()) == -1) { LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", cacheInfoPath.c_str()); - return NNCORE_FAILED; + return OH_NN_FAILED; } LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove %s.", cacheInfoPath.c_str()); @@ -395,11 +388,11 @@ NNCore_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, if (remove(cacheModelPath.c_str()) == -1) { LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", cacheModelPath.c_str()); - return NNCORE_FAILED; + return OH_NN_FAILED; } LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove the file %s", cacheModelPath.c_str()); } - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } unsigned short NNCompiledCache::GetCrc16(const unsigned char* buffer, size_t length) const @@ -412,30 +405,30 @@ unsigned short NNCompiledCache::GetCrc16(const unsigned char* buffer, size_t len return crc16; } -NNCore_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fileSize) const +OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fileSize) const { ifs.seekg(0, std::ios::end); if (!ifs.good()) { LOGE("NNCompiledCache::GetCacheFileLength fail to set the position of the next character to be extracted from " "the input stream."); - return NNCORE_FAILED; + return OH_NN_FAILED; } int handleValue = ifs.tellg(); if (handleValue == -1) { LOGE("Compiled::GetCacheFileLength fail to get position of the input stream."); - return NNCORE_INVALID_FILE; + 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 NNCORE_INVALID_FILE; + return OH_NN_INVALID_FILE; } fileSize = handleValue; - return NNCORE_SUCCESS; + return OH_NN_SUCCESS; } } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/nncompiled_cache.h b/frameworks/native/nncompiled_cache.h index 9209601..6b514f2 100644 --- a/frameworks/native/nncompiled_cache.h +++ b/frameworks/native/nncompiled_cache.h @@ -20,8 +20,8 @@ #include #include -#include "compat/device.h" -#include "neural_network_runtime.h" +#include "device.h" +#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "tensor_desc.h" namespace OHOS { @@ -40,44 +40,43 @@ public: NNCompiledCache() = default; ~NNCompiledCache() = default; - NNCore_ReturnCode Save(const std::vector& caches, + OH_NN_ReturnCode Save(const std::vector& caches, const std::string& cacheDir, uint32_t version); - NNCore_ReturnCode Restore(const std::string& cacheDir, + OH_NN_ReturnCode Restore(const std::string& cacheDir, uint32_t version, - std::vector& caches); + std::vector& caches); - NNCore_ReturnCode SetBackendName(const std::string& backendName); + OH_NN_ReturnCode SetBackend(size_t backendID); void SetModelName(const std::string& modelName); - void SetInputTensorDescs(std::vector> inputTensorDescs); - void SetOutputTensorDescs(std::vector> outputTensorDescs); - std::vector> GetInputTensorDescs() const; - std::vector> GetOutputTensorDescs() const; + void SetInputTensorDescs(std::vector> inputTensorDescs); + void SetOutputTensorDescs(std::vector> outputTensorDescs); + std::vector> GetInputTensorDescs() const; + std::vector> GetOutputTensorDescs() const; private: - NNCore_ReturnCode GenerateCacheFiles(const std::vector& caches, + OH_NN_ReturnCode GenerateCacheFiles(const std::vector& caches, const std::string& cacheDir, uint32_t version) const; - NNCore_ReturnCode GenerateCacheModel(const std::vector& caches, + OH_NN_ReturnCode GenerateCacheModel(const std::vector& caches, std::unique_ptr& cacheInfo, const std::string& cacheDir, uint32_t version) const; - NNCore_ReturnCode WriteCacheInfo(uint32_t cacheSize, + OH_NN_ReturnCode WriteCacheInfo(uint32_t cacheSize, std::unique_ptr& cacheInfo, const std::string& cacheDir) const; - NNCore_ReturnCode CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const; - NNCore_ReturnCode ReadCacheModelFile(const std::string& file, OHOS::NeuralNetworkRuntime::Buffer& cache) const; - NNCore_ReturnCode RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const; + OH_NN_ReturnCode CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, const std::string& cacheInfoPath) const; + OH_NN_ReturnCode ReadCacheModelFile(const std::string& file, Buffer& cache) const; + OH_NN_ReturnCode RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const; unsigned short GetCrc16(const unsigned char* buffer, size_t length) const; - NNCore_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fileSize) const; + OH_NN_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fileSize) const; private: - size_t m_backendID{0}; - std::string m_backendName; + size_t m_backendID {0}; std::string m_modelName; - std::shared_ptr m_device{nullptr}; - std::vector> m_inputTensorDescs; - std::vector> m_outputTensorDescs; + std::shared_ptr m_device {nullptr}; + std::vector> m_inputTensorDescs; + std::vector> m_outputTensorDescs; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index a1ca2d6..298dbd0 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -3,28 +3,105 @@ #include #include #include +#include #include "mindir.h" +#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 TensorDesc& tensorDesc) + { + OH_NN_ReturnCode ret = tensorDesc.GetDataType(&m_dataType); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting data type from tensor desc."); + return ret; + } + + ret = tensorDesc.GetFormat(&m_format); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting format from tensor desc."); + return ret; + } + + ret = tensorDesc.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.GetName(&m_name); + if (ret != OH_NN_SUCCESS) { + LOGE("CopyFromTensorDesc failed, error happened when getting name from tensor desc."); + return ret; + } + + 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}; + 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_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_innerModel(model), + : m_model(const_cast(model)), m_device(device), m_backendID(backendID) {} NNCompiler::~NNCompiler() { - if (m_prepareModel != nullptr) { - delete m_prepareModel; - m_prepareModel = nullptr; + if (m_preparedModel != nullptr) { + m_preparedModel.reset(); } } @@ -35,7 +112,7 @@ size_t NNCompiler::GetBackendID() const OH_NN_ReturnCode NNCompiler::SetCacheDir(const std::string& cacheModelPath, uint32_t version) { - m_cacheDir = cacheModelPath; + m_cachePath = cacheModelPath; m_cacheVersion = version; return OH_NN_SUCCESS; @@ -44,7 +121,7 @@ OH_NN_ReturnCode NNCompiler::SetCacheDir(const std::string& cacheModelPath, uint OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) { if (m_device == nullptr) { - LOGE("[NNCompiler] SetPerformance failed, cannot set performance before set device, please set device first"); + LOGE("[NNCompiler] SetPerformance failed, m_device is nullptr"); return OH_NN_OPERATION_FORBIDDEN; } @@ -72,7 +149,7 @@ OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) { if (m_device == nullptr) { - LOGE("[NNCompiler] SetPriority failed, cannot set priority before set device, please set device first"); + LOGE("[NNCompiler] SetPriority failed, m_device is nullptr"); return OH_NN_OPERATION_FORBIDDEN; } @@ -100,7 +177,7 @@ OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) { if (m_device == nullptr) { - LOGE("[NNCompiler] SetEnableFp16 failed, cannot set enable fp16 before set device, please set device first"); + LOGE("[NNCompiler] SetEnableFp16 failed, m_device is nullptr"); return OH_NN_OPERATION_FORBIDDEN; } @@ -122,6 +199,45 @@ OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) OH_NN_ReturnCode NNCompiler::Build() { + if (m_isBuild) { + LOGE("[NNCompiler] Build failed, cannot build again."); + return OH_NN_OPERATION_FORBIDDEN; + } + + // To add build from 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; + } + + OH_NN_ReturnCode ret {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 OH_NN_FAILED; + } + + m_isBuild = true; return OH_NN_SUCCESS; } @@ -221,29 +337,32 @@ 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); - OH_NN_ReturnCode ret = m_device->PrepareModelFromModelCache(modelOnlyCaches, config, m_preparedModel); + 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."); return ret; } - LOGI("[Compilation] Restore model cache successfully."); + 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 { - return OH_NN_SUCCESS; + LOGE("[NNCompiler] SaveToCacheBuffer is not supported currently."); + return OH_NN_OPERATION_FORBIDDEN; } OH_NN_ReturnCode NNCompiler::RestoreFromCacheBuffer(const void* buffer, size_t length) { - return OH_NN_SUCCESS; + LOGE("[NNCompiler] RestoreFromCacheBuffer is not supported currently."); + return OH_NN_OPERATION_FORBIDDEN; } OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& configs) { + LOGI("[NNCompiler] SetExtensionConfig complete successfully."); return OH_NN_SUCCESS; } @@ -254,57 +373,149 @@ OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector& options) } +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; + } -OH_NN_ReturnCode NNCompiler::Build(const void* model, Compiled** compiled) -{ - if (m_isBuild) { - LOGE("[NNCompiler] Cannot build again."); - return NNCORE_OPERATION_FORBIDDEN; + if (m_inputTensorDescs.empty()) { + LOGE("[NNCompiler] CreateExecutor failed, m_inputTensorDescs is empty"); + return nullptr; } - const InnerModel* innerModel = reinterpret_cast(model); - std::shared_ptr liteGraph = innerModel->GetLiteGraphs(); - std::vector> inputTensors = innerModel->GetInputTensors(); - std::vector> outputTensors = innerModel->GetOutputTensors(); - void* metaGraph = innerModel->GetMetaGraph(); - Buffer quantBuffer = innerModel->GetQuantBuffer(); + if (m_outputTensorDescs.empty()) { + LOGE("[NNCompiler] CreateExecutor failed, m_outputTensorDescs is empty"); + return nullptr; + } - if ((liteGraph == nullptr) && (metaGraph == nullptr)) { - LOGE("[NNCompiler] Both liteGraph and metaGraph are nullptr."); - return NNCORE_INVALID_PARAMETER; + 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; } - if ((liteGraph != nullptr) && (metaGraph != nullptr)) { - LOGE("[NNCompiler] Neither liteGraph nor metaGraph are nullptr."); - return NNCORE_INVALID_PARAMETER; + return nnExecutor; +} + +OH_NN_ReturnCode NNCompiler::DestroyExecutor(NNExecutor* executor) +{ + if (executor == nullptr) { + LOGE("[NNCompiler] DestroyExecutor failed, executor is nullptr."); + return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret {OH_NN_FAILED}; - ModelConfig config {m_enableFp16, static_cast(m_performance), - static_cast(m_priority)}; - std::shared_ptr preparedModel = nullptr; - if (liteGraph != nullptr) { - ret = m_device->PrepareModel(liteGraph, config, preparedModel); + delete executor; + executor = nullptr; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( + const std::vector>& 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.get())); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] SerializeInputsToBuffer failed, error happened when copying tensorDesc to " + "SerializedTensorDesc."); + immediateTensorDescs.clear(); + return ret; + } + immediateTensorDescs.emplace_back(immediateTensorDesc); } - if (metaGraph != nullptr) { - ret = m_device->PrepareModel(metaGraph, quantBuffer, config, preparedModel); + + size_t totalSize = 0; + for (const auto& tensorDesc : immediateTensorDescs) { + totalSize += SIZE_OF_DATATYPE; + totalSize += SIZE_OF_FORMAT; + totalSize += SIZE_OF_SHAPE_NUM; + totalSize += tensorDesc.m_shapeNum * sizeof(int32_t); + totalSize += strlen(tensorDesc.m_name) + 1; } - if (ret != OH_NN_SUCCESS) { - LOGE("[NNCompiler] Preparing model failed when normally building."); - return NNCORE_FAILED; + + // Allocate memory for the serialized data + char* serializedData = new char[totalSize]; + char* currentPos = serializedData; + + // Serialize each tensor description + for (const auto& tensorDesc : immediateTensorDescs) { + memcpy_s(currentPos, SIZE_OF_DATATYPE, &tensorDesc.m_dataType, SIZE_OF_DATATYPE); + currentPos += SIZE_OF_DATATYPE; + + memcpy_s(currentPos, SIZE_OF_FORMAT, &tensorDesc.m_format, SIZE_OF_FORMAT); + currentPos += SIZE_OF_FORMAT; + + memcpy_s(currentPos, SIZE_OF_SHAPE_NUM, &tensorDesc.m_shapeNum, SIZE_OF_SHAPE_NUM); + currentPos += SIZE_OF_SHAPE_NUM; + + size_t sizeOfShape = tensorDesc.m_shapeNum * sizeof(int32_t); + memcpy_s(currentPos, sizeOfShape, tensorDesc.m_shape, sizeOfShape); + currentPos += sizeOfShape; + + strcpy_s(currentPos, strlen(tensorDesc.m_name) + 1, tensorDesc.m_name); + currentPos += strlen(tensorDesc.m_name) + 1; } - NNCompiler* NNCompiler = new (std::nothrow) NNCompiler( - m_backendName, preparedModel, inputTensors, outputTensors, m_device); - if (NNCompiler == nullptr) { - LOGE("[NNCompiler] Create nn compiled failed."); - return NNCORE_NULL_PTR; + buffer.data = serializedData; + buffer.length = totalSize; + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( + const Buffer& buffer, std::vector>& tensorDescs) +{ + std::vector immediateTensorDescs; + const char* ptr = static_cast(buffer.data); + const char* end = ptr + buffer.length; + while (ptr < end) { + SerializedTensorDesc desc; + + memcpy_s(&desc.m_dataType, SIZE_OF_DATATYPE, ptr, sizeof(desc.m_dataType)); + ptr += sizeof(desc.m_dataType); + + memcpy_s(&desc.m_format, SIZE_OF_FORMAT, ptr, sizeof(desc.m_format)); + ptr += sizeof(desc.m_format); + + memcpy_s(&desc.m_shapeNum, SIZE_OF_SHAPE_NUM, ptr, sizeof(desc.m_shapeNum)); + ptr += sizeof(desc.m_shapeNum); + + desc.m_shape = new int32_t[desc.m_shapeNum]; + memcpy_s(desc.m_shape, desc.m_shapeNum * sizeof(int32_t), ptr, desc.m_shapeNum * sizeof(int32_t)); + 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); } - NNCompiler->SetCompiledOptions(m_options); - *compiled = reinterpret_cast(NNCompiler); - return NNCORE_SUCCESS; + OH_NN_ReturnCode ret {OH_NN_SUCCESS}; + for (const auto& immediateTensorDesc : immediateTensorDescs) { + auto tensorDesc = CreateSharedPtr(); + ret = immediateTensorDesc.CopyToTensorDesc(*(tensorDesc.get())); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] UnserializedInputsFromBuffer failed, error happened when copying " + "SerializedTensorDesc to TensorDesc."); + return ret; + } + + tensorDescs.emplace_back(tensorDesc); + } + + return ret; } + } // NeuralNetworkRuntime } // OHOS \ No newline at end of file diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 511e640..e84b12e 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -3,6 +3,10 @@ #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 { @@ -12,7 +16,7 @@ public: NNCompiler() = delete; NNCompiler(std::shared_ptr device, size_t backendID); NNCompiler(const void* model, std::shared_ptr device, size_t backendID); - ~NNCompiler() = default; + ~NNCompiler(); size_t GetBackendID() const override; @@ -31,18 +35,30 @@ public: OH_NN_ReturnCode SetExtensionConfig(const std::unordered_map>& configs) override; OH_NN_ReturnCode SetOptions(const std::vector& options) override; + NNExecutor* CreateExecutor(); + OH_NN_ReturnCode DestroyExecutor(NNExecutor* executor); + +private: + OH_NN_ReturnCode SerializeTensorsToBuffer( + const std::vector>& tensorDescs, Buffer& buffer) const; + OH_NN_ReturnCode DeserializedTensorsFromBuffer( + const Buffer& buffer, std::vector>& tensorDescs); + private: - void* m_innerModel; + void* m_model {nullptr}; bool m_isBuild {false}; bool m_enableFp16 {false}; - size_t m_backendID; - bool m_isBuild {false}; std::string m_cachePath; - uint32_t m_cacheVersion; - std::shared_ptr m_device; - PreparedModel* m_prepareModel {nullptr}; + uint32_t m_cacheVersion {0}; + std::shared_ptr m_device {nullptr}; + size_t m_backendID {0}; + std::shared_ptr m_preparedModel {nullptr}; OH_NN_Priority m_priority {OH_NN_PRIORITY_NONE}; OH_NN_PerformanceMode m_performance {OH_NN_PERFORMANCE_NONE}; + std::vector> m_inputTensorDescs; + std::vector> m_outputTensorDescs; }; } // NeuralNetworkRuntime -} // OHOS \ No newline at end of file +} // OHOS + +#endif // NEURAL_NETWORK_RUNTIME_NNCOMPILER_H \ No newline at end of file diff --git a/frameworks/native/register_hdi_device_v1_0.cpp b/frameworks/native/register_hdi_device_v1_0.cpp new file mode 100644 index 0000000..1b8d8a1 --- /dev/null +++ b/frameworks/native/register_hdi_device_v1_0.cpp @@ -0,0 +1,60 @@ +#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 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) { + LOGW("Get HDI device failed."); + return nullptr; + } + + auto hdiRet = iDevice->GetDeviceName(deviceName); + if (hdiRet != HDF_SUCCESS) { + 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) { + LOGW("Get version failed. ErrorCode=%d", hdiRet); + 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 backend; +} + +REGISTER_BACKEND(HDIDeviceV1_0, HDIDeviceV1_0Creator) +} // namespace NeuralNetworkBackend +} // namespace OHOS diff --git a/frameworks/native/register_hdi_device_v2_0.cpp b/frameworks/native/register_hdi_device_v2_0.cpp new file mode 100644 index 0000000..e84e7da --- /dev/null +++ b/frameworks/native/register_hdi_device_v2_0.cpp @@ -0,0 +1,77 @@ +#include + +#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 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) { + LOGW("Get HDI device failed."); + return nullptr; + } + + auto ret = iDevice->GetDeviceName(deviceName); + int32_t nnrtSuccess = static_cast(V2_0::NNRT_ReturnCode::NNRT_SUCCESS); + if (ret != nnrtSuccess) { + if (ret < nnrtSuccess) { + LOGW("Get device name failed. An error occurred in HDI, errorcode is %{public}d.", ret); + } else { + OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); + LOGW("Get device name failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_str()); + } + return nullptr; + } + + ret = iDevice->GetVendorName(vendorName); + if (ret != nnrtSuccess) { + if (ret < nnrtSuccess) { + LOGW("Get vendor name failed. An error occurred in HDI, errorcode is %{public}d.", ret); + } else { + OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); + LOGW("Get vendor name failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_str()); + } + return nullptr; + } + + std::pair hdiVersion; + ret = iDevice->GetVersion(hdiVersion.first, hdiVersion.second); + if (ret != nnrtSuccess) { + if (ret < nnrtSuccess) { + LOGW("Get version failed. An error occurred in HDI, errorcode is %{public}d.", ret); + } else { + OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); + LOGW("Get version failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_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 create 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 backend; +} + +REGISTER_BACKEND(HDIDeviceV2_0, HDIDeviceV2_0Creator) +} // namespace NeuralNetworkRuntime +} // namespace OHOS -- Gitee From 05ad0324629095a2527e232b03d5bb123aa1105f Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 15:41:42 +0800 Subject: [PATCH 21/51] update nnbackend --- frameworks/native/backend_registrar.h | 7 ++++++- frameworks/native/nnbackend.cpp | 7 +------ frameworks/native/nnbackend.h | 4 ---- frameworks/native/register_hdi_device_v1_0.cpp | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/frameworks/native/backend_registrar.h b/frameworks/native/backend_registrar.h index d15b4c1..6646764 100644 --- a/frameworks/native/backend_registrar.h +++ b/frameworks/native/backend_registrar.h @@ -4,6 +4,9 @@ #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()>; @@ -19,4 +22,6 @@ public: static OHOS::NeuralNetworkRuntime::BackendRegistrar g_##backendName##_backend_registrar(creator); \ } // namespace } // NeuralNetworkRuntime -} // OHOS \ No newline at end of file +} // OHOS + +#endif // NEURAL_NETWORK_CORE_BACKEND_REGISTRAR_H \ No newline at end of file diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 4194152..27fd245 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -2,6 +2,7 @@ #include #include "common/log.h" +#include "common/utils.h" #include "nncompiler.h" #include "nnexecutor.h" #include "nntensor.h" @@ -63,12 +64,6 @@ OH_NN_ReturnCode NNBackend::GetBackendName(std::string& backendName) const return OH_NN_SUCCESS; } -std::string NNBackend::GenUniqueName( - const std::string& deviceName, const std::string& vendorName, const std::string& version) const -{ - return deviceName + "_" + vendorName + "_" + version; -} - OH_NN_ReturnCode NNBackend::GetBackendType(OH_NN_DeviceType& backendType) const { if (m_device == nullptr) { diff --git a/frameworks/native/nnbackend.h b/frameworks/native/nnbackend.h index a442a68..19076d9 100644 --- a/frameworks/native/nnbackend.h +++ b/frameworks/native/nnbackend.h @@ -36,10 +36,6 @@ public: // Get device std::shared_ptr GetDevice() const; -private: - std::string GenUniqueName( - const std::string& deviceName, const std::string& vendorName, const std::string& version) const; - private: std::shared_ptr m_device; size_t m_backendID; diff --git a/frameworks/native/register_hdi_device_v1_0.cpp b/frameworks/native/register_hdi_device_v1_0.cpp index 1b8d8a1..e3328c1 100644 --- a/frameworks/native/register_hdi_device_v1_0.cpp +++ b/frameworks/native/register_hdi_device_v1_0.cpp @@ -56,5 +56,5 @@ std::shared_ptr HDIDeviceV1_0Creator() } REGISTER_BACKEND(HDIDeviceV1_0, HDIDeviceV1_0Creator) -} // namespace NeuralNetworkBackend +} // namespace NeuralNetworkRuntime } // namespace OHOS -- Gitee From 063f139b7e400a027fe7d852b52e998c7770d1b4 Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 17:25:24 +0800 Subject: [PATCH 22/51] update 1207-v2 --- common/utils.h | 9 +- frameworks/BUILD.gn | 1 + frameworks/native/backend.h | 2 +- frameworks/native/device_discover.h | 27 --- frameworks/native/device_discover_v1_0.cpp | 57 ------ frameworks/native/device_discover_v2_0.cpp | 76 -------- frameworks/native/device_manager.cpp | 177 ------------------ frameworks/native/device_manager.h | 71 ------- frameworks/native/device_registrar.cpp | 32 ---- frameworks/native/device_registrar.h | 41 ---- frameworks/native/inner_model.cpp | 16 +- frameworks/native/neural_network_runtime.cpp | 1 - .../native/neural_network_runtime_compat.cpp | 1 - frameworks/native/nnbackend.cpp | 63 ++++--- frameworks/native/nnbackend.h | 7 +- frameworks/native/nncompiled_cache.cpp | 58 +++--- frameworks/native/nncompiler.cpp | 21 +-- frameworks/native/nncompiler.h | 2 +- frameworks/native/utils.cpp | 12 ++ 19 files changed, 107 insertions(+), 567 deletions(-) delete mode 100644 frameworks/native/device_discover.h delete mode 100644 frameworks/native/device_discover_v1_0.cpp delete mode 100644 frameworks/native/device_discover_v2_0.cpp delete mode 100644 frameworks/native/device_manager.cpp delete mode 100644 frameworks/native/device_manager.h delete mode 100644 frameworks/native/device_registrar.cpp delete mode 100644 frameworks/native/device_registrar.h create mode 100644 frameworks/native/utils.cpp diff --git a/common/utils.h b/common/utils.h index 7db891b..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,13 +34,9 @@ std::shared_ptr CreateSharedPtr(Args&&... args) return nullptr; } return tPtr; -} +}; -std::string GenUniqueName( - const std::string& deviceName, const std::string& vendorName, const std::string& version) -{ - return deviceName + "_" + vendorName + "_" + version; -} +std::string GenUniqueName(const std::string&, const std::string&, const std::string&); } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index 3f57a0b..bf71913 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -155,6 +155,7 @@ nnrt_core_sources = [ "native/validation.cpp", "native/backend_registrar.cpp", "native/backend_manager.cpp", + "native/utils.cpp", ] ohos_shared_library("libneural_network_core") { diff --git a/frameworks/native/backend.h b/frameworks/native/backend.h index 82bdb4d..1d3b21d 100644 --- a/frameworks/native/backend.h +++ b/frameworks/native/backend.h @@ -40,7 +40,7 @@ public: virtual Compiler* CreateCompiler(Compilation* compilation) = 0; virtual OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) = 0; - virtual Executor* CreateExecutor() = 0; + virtual Executor* CreateExecutor(Compilation* compilation) = 0; virtual OH_NN_ReturnCode DestroyExecutor(Executor* executor) = 0; virtual Tensor* CreateTensor(TensorDesc* desc) = 0; diff --git a/frameworks/native/device_discover.h b/frameworks/native/device_discover.h deleted file mode 100644 index ae61475..0000000 --- a/frameworks/native/device_discover.h +++ /dev/null @@ -1,27 +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. - */ - -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H - -#include "device.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); -} // namespace NeuralNetworkRuntime -} // namespace OHOS -#endif // NEURAL_NETWORK_RUNTIME_DEVICE_DISCOVER_H diff --git a/frameworks/native/device_discover_v1_0.cpp b/frameworks/native/device_discover_v1_0.cpp deleted file mode 100644 index e5f802e..0000000 --- a/frameworks/native/device_discover_v1_0.cpp +++ /dev/null @@ -1,57 +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_discover.h" -#include "hdi_device_v1_0.h" -#include "common/log.h" -#include "common/utils.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -std::shared_ptr DiscoverHDIDevicesV1_0(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) { - LOGW("Get HDI device failed."); - return nullptr; - } - - auto hdiRet = iDevice->GetDeviceName(deviceName); - if (hdiRet != HDF_SUCCESS) { - 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) { - LOGW("Get version failed. ErrorCode=%d", hdiRet); - return nullptr; - } - version = 'v' + std::to_string(hdiVersion.first) + '_' + std::to_string(hdiVersion.second); - - std::shared_ptr device = CreateSharedPtr(iDevice); - if (device == nullptr) { - LOGW("Failed to register device, because fail to create device instance."); - } - return device; -} -} // namespace NeuralNetworkRuntime -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/device_discover_v2_0.cpp b/frameworks/native/device_discover_v2_0.cpp deleted file mode 100644 index d71ff33..0000000 --- a/frameworks/native/device_discover_v2_0.cpp +++ /dev/null @@ -1,76 +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_discover.h" -#include "hdi_device_v2_0.h" -#include "hdi_returncode_utils.h" -#include "common/log.h" -#include "common/utils.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -std::shared_ptr DiscoverHDIDevicesV2_0(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) { - LOGW("Get HDI device failed."); - return nullptr; - } - - auto ret = iDevice->GetDeviceName(deviceName); - int32_t nnrtSuccess = static_cast(V2_0::NNRT_ReturnCode::NNRT_SUCCESS); - if (ret != nnrtSuccess) { - if (ret < nnrtSuccess) { - LOGW("Get device name failed. An error occurred in HDI, errorcode is %{public}d.", ret); - } else { - OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); - LOGW("Get device name failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_str()); - } - return nullptr; - } - - ret = iDevice->GetVendorName(vendorName); - if (ret != nnrtSuccess) { - if (ret < nnrtSuccess) { - LOGW("Get vendor name failed. An error occurred in HDI, errorcode is %{public}d.", ret); - } else { - OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); - LOGW("Get vendor name failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_str()); - } - return nullptr; - } - - std::pair hdiVersion; - ret = iDevice->GetVersion(hdiVersion.first, hdiVersion.second); - if (ret != nnrtSuccess) { - if (ret < nnrtSuccess) { - LOGW("Get version failed. An error occurred in HDI, errorcode is %{public}d.", ret); - } else { - OHOS::HDI::Nnrt::V2_0::NNRT_ReturnCode nnrtRet = static_cast(ret); - LOGW("Get version failed. Errorcode is %{public}s.", ConverterRetToString(nnrtRet).c_str()); - } - return nullptr; - } - version = 'v' + std::to_string(hdiVersion.first) + '_' + std::to_string(hdiVersion.second); - - std::shared_ptr device = CreateSharedPtr(iDevice); - if (device == nullptr) { - LOGW("Failed to register device, because fail to create device instance."); - } - return device; -} -} // 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_manager.h b/frameworks/native/device_manager.h deleted file mode 100644 index 0dcef19..0000000 --- a/frameworks/native/device_manager.h +++ /dev/null @@ -1,71 +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. - */ - -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H - -#include -#include -#include -#include -#include -#include - -#include "device.h" -#include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -class DeviceManager { -public: - const std::vector& GetAllDeviceId(); - std::shared_ptr GetDevice(size_t deviceId) const; - const std::string& GetDeviceName(size_t deviceId); - - // register device from C++ API - OH_NN_ReturnCode RegisterDevice(std::function()> creator); - - static DeviceManager& GetInstance() - { - static DeviceManager instance; - instance.DiscoverHDIDevices(); - 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; - -private: - std::unordered_set m_uniqueName; - // key is device id, it is the unique number. - std::unordered_map> m_devices; - std::mutex m_mtx; - - std::string m_tmpDeviceName; - std::vector m_tmpDeviceIds; -}; -} // namespace NeuralNetworkRuntime -} // namespace OHOS - -#endif // NEURAL_NETWORK_RUNTIME_DEVICE_MANAGER_H \ 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/device_registrar.h b/frameworks/native/device_registrar.h deleted file mode 100644 index 521a075..0000000 --- a/frameworks/native/device_registrar.h +++ /dev/null @@ -1,41 +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. - */ - -#ifndef NEURAL_NETWORK_RUNTIME_DEVICE_REGISTRAR_H -#define NEURAL_NETWORK_RUNTIME_DEVICE_REGISTRAR_H - -#include -#include -#include - -#include "device.h" - -namespace OHOS { -namespace NeuralNetworkRuntime { -using CreateDevice = std::function()>; - -class DeviceRegistrar { -public: - DeviceRegistrar(const CreateDevice creator); - ~DeviceRegistrar() = default; -}; - -#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 diff --git a/frameworks/native/inner_model.cpp b/frameworks/native/inner_model.cpp index 9d74dcc..4cbf85a 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; @@ -679,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; } diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp index 49de519..06713b9 100644 --- a/frameworks/native/neural_network_runtime.cpp +++ b/frameworks/native/neural_network_runtime.cpp @@ -17,7 +17,6 @@ #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" diff --git a/frameworks/native/neural_network_runtime_compat.cpp b/frameworks/native/neural_network_runtime_compat.cpp index 5cfc7c1..c6e3cd2 100644 --- a/frameworks/native/neural_network_runtime_compat.cpp +++ b/frameworks/native/neural_network_runtime_compat.cpp @@ -17,7 +17,6 @@ #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h" #include "compilation.h" -#include "device_manager.h" #include "nnexecutor.h" #include "inner_model.h" #include "common/log.h" diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 27fd245..90584ef 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -18,10 +18,6 @@ NNBackend::NNBackend(const std::shared_ptr& device, size_t backendID) NNBackend::~NNBackend() { - if (m_nnCompiler != nullptr) { - DestroyCompiler(reinterpret_cast(m_nnCompiler)); - } - if (m_device != nullptr) { m_device = nullptr; } @@ -104,21 +100,22 @@ Compiler* NNBackend::CreateCompiler(Compilation* compilation) // 如果nnmodel是空值,构建空的编译器,后续从cache编译模型, // 如果nnmodel不为空,则从对应模型构建编译器 + NNCompiler* nnCompiler = nullptr; if (compilation->nnModel == nullptr) { - m_nnCompiler = new (std::nothrow) NNCompiler(m_device, m_backendID); + nnCompiler = new (std::nothrow) NNCompiler(m_device, m_backendID); } else if (compilation->nnModel != nullptr) { - m_nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); + nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); } else { LOGE("[NNBackend] CreateCompiler failed, only support build NN model and NN model cache."); return nullptr; } - if (m_nnCompiler == nullptr) { + if (nnCompiler == nullptr) { LOGE("[NNBackend] CreateCompiler failed, error happend when allocating NN Compiler."); return nullptr; } - return reinterpret_cast(m_nnCompiler); + return reinterpret_cast(nnCompiler); } OH_NN_ReturnCode NNBackend::DestroyCompiler(Compiler* compiler) @@ -134,14 +131,20 @@ OH_NN_ReturnCode NNBackend::DestroyCompiler(Compiler* compiler) return OH_NN_SUCCESS; } -Executor* NNBackend::CreateExecutor() +Executor* NNBackend::CreateExecutor(Compilation* compilation) { - if (m_nnCompiler == nullptr) { - LOGE("[NNBackend] CreateExecutor failed, m_nnCompiler is nullptr, please create compiler first."); + 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; } - NNExecutor* nnExecutor = m_nnCompiler->CreateExecutor(); + NNCompiler* nnCompiler = reinterpret_cast(compilation->compiler); + NNExecutor* nnExecutor = nnCompiler->CreateExecutor(); if (nnExecutor == nullptr) { LOGE("[NNBackend] CreateExecutor failed, fail to create NN Executor."); return nullptr; @@ -157,19 +160,9 @@ OH_NN_ReturnCode NNBackend::DestroyExecutor(Executor* executor) return OH_NN_INVALID_PARAMETER; } - if (m_nnCompiler == nullptr) { - LOGE("[NNBackend] DestroyExecutor failed, m_nnCompiler is nullptr, please create compiler first."); - return OH_NN_FAILED; - } - - NNExecutor* nnExecutor = reinterpret_cast(executor); - OH_NN_ReturnCode ret = m_nnCompiler->DestroyExecutor(nnExecutor); - if (ret != OH_NN_SUCCESS) { - LOGE("[NNBackend] DestroyExecutor failed, fail to destroy NN executor."); - return OH_NN_FAILED; - } - + delete executor; executor = nullptr; + return OH_NN_SUCCESS; } @@ -209,5 +202,27 @@ std::shared_ptr NNBackend::GetDevice() const } 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 index 19076d9..5359773 100644 --- a/frameworks/native/nnbackend.h +++ b/frameworks/native/nnbackend.h @@ -26,20 +26,21 @@ public: OH_NN_ReturnCode DestroyCompiler(Compiler* compiler) override; // Create & Destory Executor - Executor* CreateExecutor() override; + 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; - // Get device + // 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; - NNCompiler* m_nnCompiler {nullptr}; }; } // NeuralNetworkRuntime } // OHOS diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index de8ed12..d9907b2 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -58,22 +58,22 @@ OH_NN_ReturnCode NNCompiledCache::Save(const std::vector& caches) { if (cacheDir.empty()) { - LOGE("NNCompiledCache::Restore failed, cacheDir is empty."); + LOGE("[NNCompiledCache] Restore failed, cacheDir is empty."); return OH_NN_INVALID_PARAMETER; } if (!caches.empty()) { - LOGE("NNCompiledCache::Restore failed, caches is not 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."); + 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."); + 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."); + 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 %u, but the cache files " + LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %u, but the cache files " "version is %llu.", version, cacheInfo.version); @@ -120,20 +120,20 @@ 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, %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."); + 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()); + LOGE("[NNCompiledCache] Restore failed, the cache model file %s has been changed.", cacheModelPath.c_str()); return OH_NN_INVALID_FILE; } @@ -204,14 +204,14 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector(modelCacheInfo.deviceId); if (deviceId != m_backendID) { - LOGE("NNCompiledCache::CheckCacheInfo failed. The deviceId=%zu in the cache files is different from current " + LOGE("[NNCompiledCache] CheckCacheInfo failed. The deviceId=%zu in the cache files is different from current " "deviceId=%zu," "please change the cache directory or current deviceId.", deviceId, @@ -308,7 +308,7 @@ OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCache 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."); + LOGE("[NNCompiledCache] CheckCacheInfo failed. The info cache file has been changed."); infoCacheFile.close(); return OH_NN_INVALID_FILE; } @@ -326,7 +326,7 @@ OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath // filePath is validate in NNCompiledCache::Restore, no need to check twice. std::ifstream ifs(filePath.c_str(), std::ios::in | std::ios::binary); if (!ifs) { - LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); + LOGE("[NNCompiledCache] ReadCacheModelFile failed, file is invalid."); return OH_NN_INVALID_FILE; } @@ -340,21 +340,21 @@ OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath ifs.seekg(0, std::ios::beg); if (!ifs.good()) { - LOGE("NNCompiledCache::ReadCacheModelFile failed, file is invalid."); + 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."); + 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."); + LOGE("[NNCompiledCache] ReadCacheModelFile failed, failed to read file."); ifs.close(); m_device->ReleaseBuffer(ptr); ptr = nullptr; @@ -371,11 +371,11 @@ OH_NN_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, { std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; if (remove(cacheInfoPath.c_str()) == -1) { - LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", + LOGE("[NNCompiledCache] RemoveCacheFiles failed to remove the file %s, please delete the file manually.", cacheInfoPath.c_str()); return OH_NN_FAILED; } - LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove %s.", cacheInfoPath.c_str()); + LOGI("[NNCompiledCache] RemoveCacheFiles succeed to remove %s.", cacheInfoPath.c_str()); for (uint32_t i = 0; i < fileNumber; ++i) { std::string fileName = m_modelName + std::to_string(i) + ".nncache"; @@ -386,11 +386,11 @@ OH_NN_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, } if (remove(cacheModelPath.c_str()) == -1) { - LOGE("NNCompiledCache::RemoveCacheFiles failed to remove the file %s, please delete the file manually.", + LOGE("[NNCompiledCache] RemoveCacheFiles failed to remove the file %s, please delete the file manually.", cacheModelPath.c_str()); return OH_NN_FAILED; } - LOGI("NNCompiledCache::RemoveCacheFiles succeed to remove the file %s", cacheModelPath.c_str()); + LOGI("[NNCompiledCache] RemoveCacheFiles succeed to remove the file %s", cacheModelPath.c_str()); } return OH_NN_SUCCESS; } @@ -409,7 +409,7 @@ OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fi { ifs.seekg(0, std::ios::end); if (!ifs.good()) { - LOGE("NNCompiledCache::GetCacheFileLength fail to set the position of the next character to be extracted from " + LOGE("[NNCompiledCache] GetCacheFileLength fail to set the position of the next character to be extracted from " "the input stream."); return OH_NN_FAILED; } @@ -421,7 +421,7 @@ OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fi } if ((handleValue > MAX_MODEL_SIZE) || (handleValue == NULL_PTR_LENGTH)) { - LOGE("NNCompiledCache::GetCacheFileLength failed, unable to read huge or empty input stream, get cache file " + LOGE("[NNCompiledCache] GetCacheFileLength failed, unable to read huge or empty input stream, get cache file " "size=%{public}d", handleValue); return OH_NN_INVALID_FILE; diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 298dbd0..954abb0 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -197,6 +197,14 @@ OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) return OH_NN_SUCCESS; } +OH_NN_ReturnCode NNCompiler::BuildFromCache() +{ + if (m_cachePath.empty()) { + LOGE("[NNCompiler] BuildFromCache failed, cachePath is empty."); + } + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode NNCompiler::Build() { if (m_isBuild) { @@ -405,19 +413,6 @@ NNExecutor* NNCompiler::CreateExecutor() return nnExecutor; } -OH_NN_ReturnCode NNCompiler::DestroyExecutor(NNExecutor* executor) -{ - if (executor == nullptr) { - LOGE("[NNCompiler] DestroyExecutor failed, executor is nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - delete executor; - executor = nullptr; - - return OH_NN_SUCCESS; -} - OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( const std::vector>& tensorDescs, Buffer& buffer) const { diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index e84b12e..226a285 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -36,9 +36,9 @@ public: OH_NN_ReturnCode SetOptions(const std::vector& options) override; NNExecutor* CreateExecutor(); - OH_NN_ReturnCode DestroyExecutor(NNExecutor* executor); private: + OH_NN_ReturnCode BuildFromCache(); OH_NN_ReturnCode SerializeTensorsToBuffer( const std::vector>& tensorDescs, Buffer& buffer) const; OH_NN_ReturnCode DeserializedTensorsFromBuffer( 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 -- Gitee From 52a98e68e973078ac8ddbb2977433b2110382b47 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Thu, 7 Dec 2023 19:28:08 +0800 Subject: [PATCH 23/51] e2e-1207 --- frameworks/native/compilation.h | 18 ++--- frameworks/native/device.h | 3 + frameworks/native/executor.h | 2 + frameworks/native/hdi_device_v1_0.cpp | 30 ++++++++ frameworks/native/hdi_device_v1_0.h | 3 + frameworks/native/hdi_device_v2_0.cpp | 27 +++++++ frameworks/native/hdi_device_v2_0.h | 3 + frameworks/native/inner_model.cpp | 2 +- frameworks/native/neural_network_core.cpp | 87 ++++++++++++----------- frameworks/native/nncompiler.cpp | 9 ++- frameworks/native/nntensor.cpp | 36 +++++----- frameworks/native/nntensor.h | 2 +- frameworks/native/tensor.h | 2 +- testdemo/demo.cpp | 18 ++--- 14 files changed, 153 insertions(+), 89 deletions(-) diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index ff3972c..d7d37d2 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -26,17 +26,17 @@ namespace OHOS { namespace NeuralNetworkRuntime { struct Compilation { - size_t backendID; - void* nnModel; - char* offlineModelPath; + size_t backendID {0}; + void* nnModel {nullptr}; + char* offlineModelPath {nullptr}; std::pair offlineModelBuffer; - char* cachePath; - uint32_t cacheVersion; + char* cachePath {nullptr}; + uint32_t cacheVersion {0}; std::pair cacheBuffer; - OH_NN_Priority priority; - OH_NN_PerformanceMode performance; - bool enableFp16; - Compiler* compiler; + 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; }; diff --git a/frameworks/native/device.h b/frameworks/native/device.h index 66f7275..274b979 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.h @@ -66,6 +66,9 @@ public: 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/executor.h b/frameworks/native/executor.h index 9671ca9..ba06e67 100644 --- a/frameworks/native/executor.h +++ b/frameworks/native/executor.h @@ -19,6 +19,7 @@ #include #include +#include "compiler.h" #include "tensor_desc.h" #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" @@ -27,6 +28,7 @@ namespace NeuralNetworkRuntime { class Executor { public: Executor() = default; + Executor(Compiler* compiler); virtual ~Executor() = default; virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, diff --git a/frameworks/native/hdi_device_v1_0.cpp b/frameworks/native/hdi_device_v1_0.cpp index e19949f..c28c7ce 100644 --- a/frameworks/native/hdi_device_v1_0.cpp +++ b/frameworks/native/hdi_device_v1_0.cpp @@ -357,6 +357,36 @@ 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); diff --git a/frameworks/native/hdi_device_v1_0.h b/frameworks/native/hdi_device_v1_0.h index 281b895..a7167ba 100644 --- a/frameworks/native/hdi_device_v1_0.h +++ b/frameworks/native/hdi_device_v1_0.h @@ -63,6 +63,9 @@ public: 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 8979042..a4bce4f 100644 --- a/frameworks/native/hdi_device_v2_0.cpp +++ b/frameworks/native/hdi_device_v2_0.cpp @@ -392,6 +392,33 @@ 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); diff --git a/frameworks/native/hdi_device_v2_0.h b/frameworks/native/hdi_device_v2_0.h index f19f4cf..b8dc5f8 100644 --- a/frameworks/native/hdi_device_v2_0.h +++ b/frameworks/native/hdi_device_v2_0.h @@ -63,6 +63,9 @@ public: 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/inner_model.cpp b/frameworks/native/inner_model.cpp index 4cbf85a..8a4281f 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -390,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; } } diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index a0feace..0446d32 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -779,16 +779,15 @@ NNRT_API NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDes return nullptr; } - // todo - /*BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(backendName); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); if (backend == nullptr) { - LOGE("OH_NNTensor_Create failed, passed invalid backend name %{public}s.", backendName); + LOGE("OH_NNTensor_Create failed, passed invalid backend name %{public}zu.", deviceID); return nullptr; } TensorDesc* descImpl = reinterpret_cast(tensorDesc); - Tensor* tensorImpl = backend->CreateTensor(deviceID, descImpl); + Tensor* tensorImpl = backend->CreateTensor(descImpl); if (tensorImpl == nullptr) { LOGE("OH_NNTensor_Create failed, failed to create tensor."); return nullptr; @@ -802,8 +801,7 @@ NNRT_API NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDes } NN_Tensor* tensor = reinterpret_cast(tensorImpl); - return tensor;*/ - return nullptr; + return tensor; } NNRT_API NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc, size_t size) @@ -813,16 +811,15 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *t return nullptr; } - // todo - /*BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(backendName); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); if (backend == nullptr) { - LOGE("OH_NNTensor_CreateWithSize failed, passed invalid backend name %{public}s.", backendName); + LOGE("OH_NNTensor_CreateWithSize failed, passed invalid backend name %{public}zu.", deviceID); return nullptr; } TensorDesc* descImpl = reinterpret_cast(tensorDesc); - Tensor* tensorImpl = backend->CreateTensor(backendName, descImpl); + Tensor* tensorImpl = backend->CreateTensor(descImpl); if (tensorImpl == nullptr) { LOGE("OH_NNTensor_CreateWithSize failed, failed to create tensor."); return nullptr; @@ -836,8 +833,7 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *t } NN_Tensor* tensor = reinterpret_cast(tensorImpl); - return tensor;*/ - return nullptr; + return tensor; } NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( @@ -852,16 +848,15 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( return nullptr; } - // todo - /*BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(backendName); + BackendManager& backendManager = BackendManager::GetInstance(); + std::shared_ptr backend = backendManager.GetBackend(deviceID); if (backend == nullptr) { - LOGE("OH_NNTensor_CreateWithFd failed, passed invalid backend name %{public}s.", backendName); + LOGE("OH_NNTensor_CreateWithFd failed, passed invalid backend name %{public}zu.", deviceID); return nullptr; } TensorDesc* descImpl = reinterpret_cast(tensorDesc); - Tensor* tensorImpl = backend->CreateTensor(backendName, descImpl); + Tensor* tensorImpl = backend->CreateTensor(descImpl); if (tensorImpl == nullptr) { LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); return nullptr; @@ -875,8 +870,7 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( } NN_Tensor* tensor = reinterpret_cast(tensorImpl); - return tensor;*/ - return nullptr; + return tensor; } NNRT_API OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor) @@ -890,28 +884,21 @@ NNRT_API OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor) return OH_NN_INVALID_PARAMETER; } - // todo - /*Tensor* tensorImpl = reinterpret_cast(*tensor); - std::string backendName; - auto ret = tensorImpl->GetBackendName(backendName); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNTensor_Destroy failed, failed to get backend name."); - return ret; - } - + Tensor* tensorImpl = reinterpret_cast(*tensor); + size_t backendID = tensorImpl->GetBackendID(); BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(backendName); + std::shared_ptr backend = backendManager.GetBackend(backendID); if (backend == nullptr) { - LOGE("OH_NNTensor_Destroy failed, passed invalid backend name %{public}s.", backendName.c_str()); + LOGE("OH_NNTensor_Destroy failed, passed invalid backend name %{public}zu.", backendID); return OH_NN_NULL_PTR; } - ret = backend->DestroyTensor(tensorImpl); + auto ret = backend->DestroyTensor(tensorImpl); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNTensor_Destroy failed, failed to destroy tensor."); return ret; } - *tensor = nullptr;*/ + *tensor = nullptr; return OH_NN_SUCCESS; } @@ -1005,8 +992,22 @@ NNRT_API OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation) return nullptr; } - // todo - 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) @@ -1020,21 +1021,21 @@ NNRT_API void OH_NNExecutor_Destroy(OH_NNExecutor **executor) return; } - // todo - /*Executor *executorImpl = reinterpret_cast(*executor); - size_t deviceID = executorImpl->GetDeviceID(); + Executor *executorImpl = reinterpret_cast(*executor); + size_t backendID = executorImpl->GetBackendID(); BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(deviceID); + std::shared_ptr backend = backendManager.GetBackend(backendID); if (backend == nullptr) { - LOGE("OH_NNExecutor_Destroy failed, failed to get backend of %{public}s.", backendName.c_str()); + LOGE("OH_NNExecutor_Destroy failed, failed to get backend of %{public}zu.", backendID); return; } - returnCode = backend->DestroyExecutor(executorImpl); + + auto returnCode = backend->DestroyExecutor(executorImpl); if (returnCode != OH_NN_SUCCESS) { LOGE("OH_NNExecutor_Destroy failed, failed to destroy executor."); return; } - *executor = nullptr;*/ + *executor = nullptr; } NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetOutputShape( diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 954abb0..853f8a9 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -132,7 +132,7 @@ OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) return OH_NN_FAILED; } - if (!isSupportedPerformance) { + if (!isSupportedPerformance and (performance != OH_NN_PERFORMANCE_NONE)) { LOGE("[NNCompiler] SetPerformance failed, this device is not support performance setting."); return OH_NN_OPERATION_FORBIDDEN; } @@ -160,7 +160,7 @@ OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) return OH_NN_FAILED; } - if (!isSupportedPriority) { + if (!isSupportedPriority && (priority != OH_NN_PRIORITY_NONE)) { LOGE("[NNCompiler] SetPriority failed, this device is not support priority setting."); return OH_NN_OPERATION_FORBIDDEN; } @@ -188,7 +188,7 @@ OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) return OH_NN_FAILED; } - if (!isSupportedFp16) { + if (!isSupportedFp16 && isFp16) { LOGE("[NNCompiler] SetEnableFp16 failed, this device is not support float16 precision setting."); return OH_NN_OPERATION_FORBIDDEN; } @@ -376,8 +376,7 @@ OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map& options) { - LOGE("[NNCompiler] SetOptions failed, NN compiler don't support set extentsion options."); - return OH_NN_OPERATION_FORBIDDEN; + return OH_NN_SUCCESS; } diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index 4b2a77e..8f34ca1 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "backend_manager.h" +#include "nnbackend.h" #include "nntensor.h" #include "common/log.h" #include @@ -21,8 +23,6 @@ namespace OHOS { namespace NeuralNetworkRuntime { -const size_t ALLOCATE_BUFFER_LIMIT = 1024 * 1024 * 1024; - NNTensor2_0::~NNTensor2_0() { if (!m_isUserData) { @@ -148,24 +148,22 @@ size_t NNTensor2_0::GetOffset() const OH_NN_ReturnCode NNTensor2_0::AllocateMemory(size_t length) { - // todo - /* BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(m_backendName); + std::shared_ptr backend = backendManager.GetBackend(m_backendID); if (backend == nullptr) { - LOGE("NNTensor2_0::AllocateMemory failed, failed to get backend of %{public}s.", m_backendName.c_str()); - return NNCORE_NULL_PTR; + 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 NNCORE_NULL_PTR; + return OH_NN_NULL_PTR; } auto device = nnBackend->GetDevice(); if (device == nullptr) { LOGE("NNTensor2_0::AllocateMemory failed, device of nnbackend is nullptr."); - return NNCORE_NULL_PTR; + return OH_NN_NULL_PTR; } int fd = 0; auto oldRet = device->AllocateBuffer(length, fd); @@ -186,7 +184,7 @@ OH_NN_ReturnCode NNTensor2_0::AllocateMemory(size_t length) } m_fd = fd; m_offset = 0; - m_size = length;*/ + m_size = length; return OH_NN_SUCCESS; } @@ -201,24 +199,22 @@ OH_NN_ReturnCode NNTensor2_0::ReleaseMemory() return OH_NN_INVALID_PARAMETER; } - // todo - /* BackendManager& backendManager = BackendManager::GetInstance(); - std::shared_ptr backend = backendManager.GetBackend(m_backendName); + std::shared_ptr backend = backendManager.GetBackend(m_backendID); if (backend == nullptr) { - LOGE("NNTensor2_0::ReleaseMemory failed, failed to get backend of %{public}s.", m_backendName.c_str()); - return NNCORE_NULL_PTR; + LOGE("NNTensor2_0::ReleaseMemory failed, failed to get backend of %{public}zu.", m_backendID); + return OH_NN_NULL_PTR; } - // todo backend中拿到device 分配内存 + auto* nnrtBackend = reinterpret_cast(backend.get()); if (nnrtBackend == nullptr) { LOGE("NNTensor2_0::ReleaseMemory failed, failed to convert backend to nnbackend."); - return NNCORE_NULL_PTR; + return OH_NN_NULL_PTR; } auto device = nnrtBackend->GetDevice(); if (device == nullptr) { LOGE(""); - return NNCORE_NULL_PTR; + return OH_NN_NULL_PTR; } auto oldRet = device->ReleaseBuffer(m_fd, m_size); if (oldRet != OH_NN_SUCCESS) { @@ -238,12 +234,12 @@ OH_NN_ReturnCode NNTensor2_0::ReleaseMemory() LOGE("NNTensor2_0::ReleaseMemory failed. fd=%{public}d", m_fd); return OH_NN_MEMORY_ERROR; } - m_fd = 0;*/ + m_fd = 0; return OH_NN_SUCCESS; } -size_t NNTensor2_0::GetDeviceID() const +size_t NNTensor2_0::GetBackendID() const { return m_backendID; } diff --git a/frameworks/native/nntensor.h b/frameworks/native/nntensor.h index c04cbc5..4bcee48 100644 --- a/frameworks/native/nntensor.h +++ b/frameworks/native/nntensor.h @@ -36,7 +36,7 @@ public: int GetFd() const override; size_t GetSize() const override; size_t GetOffset() const override; - size_t GetDeviceID() const override; + size_t GetBackendID() const override; bool CheckTensorData() const; diff --git a/frameworks/native/tensor.h b/frameworks/native/tensor.h index 8cb2f47..bd4aa8f 100644 --- a/frameworks/native/tensor.h +++ b/frameworks/native/tensor.h @@ -36,7 +36,7 @@ public: virtual int GetFd() const = 0; virtual size_t GetSize() const = 0; virtual size_t GetOffset() const = 0; - virtual size_t GetDeviceID() const = 0; + virtual size_t GetBackendID() const = 0; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/testdemo/demo.cpp b/testdemo/demo.cpp index 21a974b..ca39d5c 100644 --- a/testdemo/demo.cpp +++ b/testdemo/demo.cpp @@ -40,7 +40,7 @@ OH_NN_ReturnCode SetInputData(NN_Tensor* inputTensor[], size_t inputSize) CHECKEQ(desc, nullptr, OH_NN_FAILED, "Failed to get desc"); ret = OH_NNTensorDesc_GetDataType(desc, &dataType); CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get data type"); - ret = OH_NNTensorDesc_GetElementNum(desc, &elementNum); + ret = OH_NNTensorDesc_GetElementCount(desc, &elementNum); CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get element num"); switch(dataType) { case OH_NN_FLOAT32: { @@ -76,7 +76,7 @@ OH_NN_ReturnCode Print(NN_Tensor* outputTensor[], size_t outputSize) CHECKEQ(desc, nullptr, OH_NN_FAILED, "Failed to get desc"); ret = OH_NNTensorDesc_GetDataType(desc, &dataType); CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get data type"); - ret = OH_NNTensorDesc_GetElementNum(desc, &elementNum); + ret = OH_NNTensorDesc_GetElementCount(desc, &elementNum); CHECKNEQ(ret, OH_NN_SUCCESS, OH_NN_FAILED, "Failed to get element num"); printf("elementnum:%zu: ", elementNum); switch(dataType) { @@ -118,8 +118,8 @@ int main(int argc, char** argv) { returnCode = OH_NNDevice_GetName(allDevicesID[i], &name); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNDevice_GetName failed."); deviceID = allDevicesID[i]; + printf("deviceID:%zu, backendName:%s\n", deviceID, name); } - printf("backendName:%s\n", name); // 创建模型实例,进行模型构造 OH_NNModel* model = OH_NNModel_Construct(); @@ -212,9 +212,9 @@ int main(int argc, char** argv) { uint32_t inputIndicesValues[2] = {0, 1}; uint32_t paramIndicesValues = 2; uint32_t outputIndicesValues = 3; - OH_NN_UInt32Array paramIndices = {¶mIndicesValues, 1 * 4}; - OH_NN_UInt32Array inputIndices = {inputIndicesValues, 2 * 4}; - OH_NN_UInt32Array outputIndices = {&outputIndicesValues, 1 * 4}; + OH_NN_UInt32Array paramIndices = {¶mIndicesValues, 1}; + OH_NN_UInt32Array inputIndices = {inputIndicesValues, 2}; + OH_NN_UInt32Array outputIndices = {&outputIndicesValues, 1}; // 向模型实例添加Add算子 returnCode = OH_NNModel_AddOperation(model, OH_NN_OPS_ADD, ¶mIndices, &inputIndices, &outputIndices); @@ -241,7 +241,7 @@ int main(int argc, char** argv) { returnCode = OH_NNCompilation_SetPerformanceMode(compilation, OH_NN_PERFORMANCE_EXTREME); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetPerformanceMode failed."); - returnCode = OH_NNCompilation_SetPriority(compilation, OH_NN_PRIORITY_HIGH); + returnCode = OH_NNCompilation_SetPriority(compilation, OH_NN_PRIORITY_NONE); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNCompilation_SetPriority failed."); returnCode = OH_NNCompilation_EnableFloat16(compilation, false); @@ -263,7 +263,7 @@ int main(int argc, char** argv) { // 从executor获取输入输出信息 size_t inputCount = 0; - returnCode = OH_NNExecutor_GetInputNum(executor, &inputCount); + returnCode = OH_NNExecutor_GetInputCount(executor, &inputCount); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNExecutor_GetInputNum failed."); std::vector inputTensorDescs; NN_TensorDesc* tensorDescTmp = nullptr; @@ -273,7 +273,7 @@ int main(int argc, char** argv) { inputTensorDescs.emplace_back(tensorDescTmp); } size_t outputCount = 0; - returnCode = OH_NNExecutor_GetOutputNum(executor, &outputCount); + returnCode = OH_NNExecutor_GetOutputCount(executor, &outputCount); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNExecutor_GetOutputNum failed."); std::vector outputTensorDescs; for (size_t i = 0; i < outputCount; ++i) { -- Gitee From e1bca7941e567a8e6375f32b34744a366cd65057 Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 21:24:35 +0800 Subject: [PATCH 24/51] update compiler, 1207-v2 --- frameworks/native/compilation.h | 5 ++++ frameworks/native/compiler.h | 4 +-- frameworks/native/neural_network_core.cpp | 13 +++++----- frameworks/native/nncompiler.cpp | 31 +++++++++++++++-------- frameworks/native/nncompiler.h | 4 +-- 5 files changed, 35 insertions(+), 22 deletions(-) diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index d7d37d2..3891f5e 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -39,6 +39,11 @@ struct Compilation { Compiler* compiler {nullptr}; std::vector options; std::unordered_map> configs; + + ~Compilation() + { + options.clear(); + } }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h index 72ae99f..31ab1af 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -25,9 +25,6 @@ namespace NeuralNetworkRuntime { class Compiler { public: Compiler() = default; - Compiler(const void* model); - Compiler(const std::string& filePath); - Compiler(const void* modelData, size_t modelSize); virtual ~Compiler() = default; virtual size_t GetBackendID() const = 0; @@ -37,6 +34,7 @@ public: 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; diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 0446d32..62eb29b 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -518,13 +518,6 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) return OH_NN_NULL_PTR; } - // if ((compilationImpr->nnModel == nullptr) && (compilationImpr->offlineModelPath == nullptr) && - // ((compilationImpr->offlineModelBuffer.first == nullptr) || - // (compilationImpr->offlineModelBuffer.second == static_cast(0)))) { - // LOGE("OH_NNCompilation_Build failed, find no model to build compilation."); - // return OH_NN_INVALID_PARAMETER; - // } - if (((compilationImpr->nnModel != nullptr) && (compilationImpr->offlineModelPath != nullptr)) || ((compilationImpr->nnModel != nullptr) && ((compilationImpr->offlineModelBuffer.first != nullptr) || @@ -549,6 +542,12 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) return OH_NN_FAILED; } + bool isBuild = compilationImpr->compiler->IsBuild(); + if (isBuild) { + LOGE("OH_NNCompilation_Build failed, compilation has been built, don't build again."); + return OH_NN_FAILED; + } + ret = compilationImpr->compiler->Build(); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNCompilation_Build failed, faile to build compilation."); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 853f8a9..d56820e 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -103,6 +103,8 @@ NNCompiler::~NNCompiler() if (m_preparedModel != nullptr) { m_preparedModel.reset(); } + m_inputTensorDescs.clear(); + m_outputTensorDescs.clear(); } size_t NNCompiler::GetBackendID() const @@ -132,7 +134,7 @@ OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) return OH_NN_FAILED; } - if (!isSupportedPerformance and (performance != OH_NN_PERFORMANCE_NONE)) { + if (!isSupportedPerformance && (performance != OH_NN_PERFORMANCE_NONE)) { LOGE("[NNCompiler] SetPerformance failed, this device is not support performance setting."); return OH_NN_OPERATION_FORBIDDEN; } @@ -197,12 +199,9 @@ OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNCompiler::BuildFromCache() +bool NNCompiler::IsBuild() const { - if (m_cachePath.empty()) { - LOGE("[NNCompiler] BuildFromCache failed, cachePath is empty."); - } - return OH_NN_SUCCESS; + return m_isBuild; } OH_NN_ReturnCode NNCompiler::Build() @@ -212,8 +211,15 @@ OH_NN_ReturnCode NNCompiler::Build() return OH_NN_OPERATION_FORBIDDEN; } - // To add build from cache; + // cache存在,从cache直接复原prepareModel、input/output TensorDesc + OH_NN_ReturnCode ret = RestoreFromCacheFile(); + if (ret == OH_NN_SUCCESS) { + LOGI("[NNCompiler] Build Success, restore from cache file."); + m_isBuild = true; + return OH_NN_SUCCESS; + } + // cache不存在,正常在线构图 const InnerModel* innerModel = reinterpret_cast(m_model); std::shared_ptr liteGraph = innerModel->GetLiteGraphs(); m_inputTensorDescs = innerModel->GetInputTensorDescs(); @@ -231,7 +237,6 @@ OH_NN_ReturnCode NNCompiler::Build() return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret {OH_NN_FAILED}; ModelConfig config {m_enableFp16, static_cast(m_performance), static_cast(m_priority)}; if (liteGraph != nullptr) { @@ -244,8 +249,15 @@ OH_NN_ReturnCode NNCompiler::Build() LOGE("[NNCompiler] Build failed, fail to prepare model when normally building."); return OH_NN_FAILED; } - m_isBuild = true; + + // 保存cache + ret = SaveToCacheFile(); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build success, but fail to save cache to file."); + return OH_NN_FAILED; + } + return OH_NN_SUCCESS; } @@ -379,7 +391,6 @@ OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector& options) return OH_NN_SUCCESS; } - NNExecutor* NNCompiler::CreateExecutor() { if (m_device == nullptr) { diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 226a285..bd4184b 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -25,6 +25,7 @@ public: 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; @@ -38,7 +39,6 @@ public: NNExecutor* CreateExecutor(); private: - OH_NN_ReturnCode BuildFromCache(); OH_NN_ReturnCode SerializeTensorsToBuffer( const std::vector>& tensorDescs, Buffer& buffer) const; OH_NN_ReturnCode DeserializedTensorsFromBuffer( @@ -52,9 +52,9 @@ private: uint32_t m_cacheVersion {0}; std::shared_ptr m_device {nullptr}; size_t m_backendID {0}; - std::shared_ptr m_preparedModel {nullptr}; 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> m_inputTensorDescs; std::vector> m_outputTensorDescs; }; -- Gitee From c7b08fd68196f2444333b4bfd050169a7928b1ec Mon Sep 17 00:00:00 2001 From: maoyong Date: Thu, 7 Dec 2023 21:58:06 +0800 Subject: [PATCH 25/51] update return err code --- frameworks/native/hdi_prepared_model_v1_0.cpp | 2 +- frameworks/native/hdi_prepared_model_v2_0.cpp | 2 +- frameworks/native/nncompiled_cache.cpp | 4 ++-- frameworks/native/nncompiler.cpp | 2 +- .../c/neural_network_runtime/neural_network_runtime_type.h | 6 +++++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/frameworks/native/hdi_prepared_model_v1_0.cpp b/frameworks/native/hdi_prepared_model_v1_0.cpp index e239107..49b34ed 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.cpp +++ b/frameworks/native/hdi_prepared_model_v1_0.cpp @@ -176,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(); diff --git a/frameworks/native/hdi_prepared_model_v2_0.cpp b/frameworks/native/hdi_prepared_model_v2_0.cpp index f3bdc4b..2bb441f 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.cpp +++ b/frameworks/native/hdi_prepared_model_v2_0.cpp @@ -176,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(); diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index d9907b2..9dde0c0 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -244,7 +244,7 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector(caches[i].data), caches[i].length)) { LOGE("[Compilation] Fail to write cache model."); cacheModelStream.close(); - return OH_NN_FAILED; + return OH_NN_SAVE_CACHE_EXCEPTION; }; cacheModelStream.close(); @@ -267,7 +267,7 @@ OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, if (!cacheInfoStream.write(reinterpret_cast(cacheInfo.get()), cacheSize)) { LOGE("[Compilation] Fail to write cache info."); cacheInfoStream.close(); - return OH_NN_FAILED; + return OH_NN_SAVE_CACHE_EXCEPTION; } cacheInfoStream.close(); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index d56820e..602f759 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -255,7 +255,7 @@ OH_NN_ReturnCode NNCompiler::Build() ret = SaveToCacheFile(); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] Build success, but fail to save cache to file."); - return OH_NN_FAILED; + return OH_NN_SAVE_CACHE_EXCEPTION; } return OH_NN_SUCCESS; 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 2bcdda5..ec521fd 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 @@ -146,7 +146,11 @@ typedef enum { /** Connect Exception. * @since 11 */ - OH_NN_CONNECT_EXCEPTION = 11 + OH_NN_CONNECT_EXCEPTION = 11, + /** Save cache exception. + * @since 11 + */ + OH_NN_SAVE_CACHE_EXCEPTION = 12 } OH_NN_ReturnCode; typedef void (*NN_OnRunDone)(void*, OH_NN_ReturnCode, void* [], int32_t); -- Gitee From 0fede1757a94014ea74c25874460a6827377b185 Mon Sep 17 00:00:00 2001 From: maoyong Date: Fri, 8 Dec 2023 10:12:03 +0800 Subject: [PATCH 26/51] update nncore.cpp, delete reinterpret_cast exception --- frameworks/native/neural_network_core.cpp | 64 ----------------------- 1 file changed, 64 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 62eb29b..ed1108f 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -122,11 +122,6 @@ OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) compilation->nnModel = const_cast(reinterpret_cast(model)); OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); - if (nnCompilation == nullptr) { - LOGE("OH_NNCompilation_Construct failed, cast to OH_NNCompilation pointer failed."); - delete compilation; - return nullptr; - } return nnCompilation; } @@ -146,11 +141,6 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *mod compilation->offlineModelPath = const_cast(modelPath); OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); - if (nnCompilation == nullptr) { - LOGE("OH_NNCompilation_ConstructWithOfflineModelFile failed, cast to OH_NNCompilation pointer failed."); - delete compilation; - return nullptr; - } return nnCompilation; } @@ -176,11 +166,6 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *m compilation->offlineModelBuffer.first = const_cast(modelBuffer); compilation->offlineModelBuffer.second = modelSize; OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); - if (nnCompilation == nullptr) { - LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, cast to OH_NNCompilation pointer failed."); - delete compilation; - return nullptr; - } return nnCompilation; } @@ -194,12 +179,6 @@ OH_NNCompilation *OH_NNCompilation_ConstructForCache() } OH_NNCompilation* nnCompilation = reinterpret_cast(compilation); - if (nnCompilation == nullptr) { - LOGE("OH_NNCompilation_ConstructForCache failed, cast to OH_NNCompilation pointer failed."); - delete compilation; - return nullptr; - } - return nnCompilation; } @@ -229,11 +208,6 @@ OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilat } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_ExportCacheToBuffer failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - if (compilationImpr->compiler == nullptr) { LOGE("OH_NNCompilation_ExportCacheToBuffer failed, should call OH_NNCompilation_Build before export cache."); return OH_NN_INVALID_PARAMETER; @@ -267,11 +241,6 @@ OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compil } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - if (compilationImpr->compiler == nullptr) { LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, should call OH_NNCompilation_Build before import cache."); return OH_NN_INVALID_PARAMETER; @@ -311,10 +280,6 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_AddExtensionConfig failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } std::string configNameStr = configName; std::vector configValueVec(configValueSize, '0'); @@ -342,11 +307,6 @@ OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_ } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_SetDevice failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - compilationImpr->backendID = deviceID; return OH_NN_SUCCESS; @@ -365,11 +325,6 @@ OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_SetCache failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - compilationImpr->cachePath = const_cast(cachePath); compilationImpr->cacheVersion = version; @@ -385,11 +340,6 @@ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilati } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_SetPerformanceMode failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - compilationImpr->performance = performanceMode; return OH_NN_SUCCESS; @@ -403,11 +353,6 @@ OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_ } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_SetPriority failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - compilationImpr->priority = priority; return OH_NN_SUCCESS; @@ -421,11 +366,6 @@ OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, b } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_EnableFloat16 failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } - compilationImpr->enableFp16 = enableFloat16; return OH_NN_SUCCESS; @@ -513,10 +453,6 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr == nullptr) { - LOGE("OH_NNCompilation_Build failed, cast to compilation instance failed."); - return OH_NN_NULL_PTR; - } if (((compilationImpr->nnModel != nullptr) && (compilationImpr->offlineModelPath != nullptr)) || ((compilationImpr->nnModel != nullptr) && -- Gitee From 341dc9223396226eb0388a63d8460c0b6ead5547 Mon Sep 17 00:00:00 2001 From: maoyong Date: Fri, 8 Dec 2023 14:56:20 +0800 Subject: [PATCH 27/51] update compilation, 1208-v2 --- frameworks/native/compilation.h | 3 ++- frameworks/native/compiler.h | 3 ++- frameworks/native/neural_network_core.cpp | 11 +++++++---- frameworks/native/nncompiler.cpp | 24 +++++++++++++++++------ frameworks/native/nncompiler.h | 2 +- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 3891f5e..b9cb69e 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -18,6 +18,7 @@ #include #include +#include #include #include "compiler.h" @@ -37,7 +38,7 @@ struct Compilation { OH_NN_PerformanceMode performance {OH_NN_PERFORMANCE_NONE}; bool enableFp16 {false}; Compiler* compiler {nullptr}; - std::vector options; + std::vector> options; std::unordered_map> configs; ~Compilation() diff --git a/frameworks/native/compiler.h b/frameworks/native/compiler.h index 31ab1af..3b98440 100644 --- a/frameworks/native/compiler.h +++ b/frameworks/native/compiler.h @@ -15,6 +15,7 @@ #ifndef NEURAL_NETWORK_RUNTIME_COMPILER_H #define NEURAL_NETWORK_RUNTIME_COMPILER_H +#include #include #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime_type.h" @@ -43,7 +44,7 @@ public: 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; + virtual OH_NN_ReturnCode SetOptions(const std::vector>& options) = 0; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index ed1108f..7e675a5 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -406,10 +406,13 @@ OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret = compilation->compiler->SetCacheDir(compilation->cachePath, compilation->cacheVersion); - if (ret != OH_NN_SUCCESS) { - LOGE("SetCompilationOptions failed, fail to set cache dir."); - return OH_NN_FAILED; + 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 OH_NN_FAILED; + } } ret = compilation->compiler->SetEnableFp16(compilation->enableFp16); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 602f759..2a8385c 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -252,10 +252,12 @@ OH_NN_ReturnCode NNCompiler::Build() m_isBuild = true; // 保存cache - ret = SaveToCacheFile(); - if (ret != OH_NN_SUCCESS) { - LOGE("[NNCompiler] Build success, but fail to save cache to file."); - return OH_NN_SAVE_CACHE_EXCEPTION; + if (!m_cachePath.empty()) { + ret = SaveToCacheFile(); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build success, but fail to save cache to file."); + return OH_NN_SAVE_CACHE_EXCEPTION; + } } return OH_NN_SUCCESS; @@ -286,6 +288,11 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const } 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); @@ -331,9 +338,14 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() } 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; - OH_NN_ReturnCode ret = compiledCache.Restore(m_cachePath, m_cacheVersion, caches); + ret = compiledCache.Restore(m_cachePath, m_cacheVersion, caches); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] RestoreFromCacheFile failed, error happened when restoring model cache."); return ret; @@ -386,7 +398,7 @@ OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map& options) +OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector>& options) { return OH_NN_SUCCESS; } diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index bd4184b..4332669 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -34,7 +34,7 @@ public: 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; + OH_NN_ReturnCode SetOptions(const std::vector>& options) override; NNExecutor* CreateExecutor(); -- Gitee From bb38567db29d30316a987344810f848042327394 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Fri, 8 Dec 2023 16:33:18 +0800 Subject: [PATCH 28/51] merge weiwei --- frameworks/native/tensor_desc.cpp | 1 + .../neural_network_core.h | 353 ++++++++++++++---- .../neural_network_runtime.h | 127 ++++++- .../neural_network_runtime_compat.h | 36 +- .../neural_network_runtime_type.h | 64 +++- 5 files changed, 481 insertions(+), 100 deletions(-) diff --git a/frameworks/native/tensor_desc.cpp b/frameworks/native/tensor_desc.cpp index 32d6704..1dd2638 100644 --- a/frameworks/native/tensor_desc.cpp +++ b/frameworks/native/tensor_desc.cpp @@ -154,6 +154,7 @@ OH_NN_ReturnCode TensorDesc::GetByteSize(size_t* byteSize) const 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_SUCCESS) { 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 3842cc0..dcaa5f1 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_core.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -17,23 +17,23 @@ * @addtogroup NeuralNeworkRuntime * @{ * - * @brief Provides APIs of Neural Network Runtime for accelerating the model inference. + * @brief Provides APIs of Neural Network Core for accelerating the model inference. * - * @Syscap SystemCapability.Ai.NeuralNetworkRuntime - * @since 9 - * @version 2.0 + * @since 11 + * @version 1.0 */ /** * @file neural_network_core.h * - * @brief Defines the Neural Network Runtime APIs. The AI inference framework uses the Native APIs provided by Neural Network Runtime + * @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 Runtime do not support multi-thread calling. \n + * Note: Currently, the APIs of Neural Network Core do not support multi-thread calling. \n * - * @library libneural_network_runtime.so - * @since 9 - * @version 2.0 + * @library libneural_network_core.so + * @Syscap SystemCapability.Ai.NeuralNetworkRuntime + * @since 11 + * @version 1.0 */ #ifndef NEURAL_NETWORK_CORE_H @@ -65,25 +65,101 @@ extern "C" { * @param model Pointer to the {@link OH_NNModel} instance. * @return Returns the pointer to a {@link OH_NNCompilation} instance. * @since 9 - * @version 2.0 + * @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 + * + * @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 + * + * @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. + * + * 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 + * + * @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 to set these + * custom hardware attributes for the device you chose, if you have queried their names and values from the device vendor documents. + * These attributes will be passed directly to device driver, and this method will return error code if the driver cannot parse them. \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, @@ -101,7 +177,7 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID); @@ -137,14 +213,14 @@ OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_ * @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 2.0 + * @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 + * 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 * @@ -155,7 +231,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, OH_NN_PerformanceMode performanceMode); @@ -163,7 +239,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilati /** * @brief Sets the model computing priority. * - * Neural Network Runtime allows you to set computing priorities for models. + * 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 * @@ -174,14 +250,14 @@ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilati * @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 2.0 + * @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, + * 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 @@ -192,7 +268,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_ * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16); @@ -208,7 +284,7 @@ OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, b * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation); @@ -219,10 +295,10 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation); * * 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, + * @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 2.0 + * @version 1.0 */ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); @@ -238,7 +314,7 @@ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); * - {@link OH_NNTensor_CreateWithSize} * - {@link OH_NNTensor_CreateWithFd} \n * - * @return Returns the pointer to a {@link NN_TensorDesc} instance + * @return Pointer to a {@link NN_TensorDesc} instance * @since 11 * @version 1.0 */ @@ -254,7 +330,7 @@ NN_TensorDesc *OH_NNTensorDesc_Create(); * * If tensorDesc or *tensorDesc is a null pointer, this method will return error code and does not execute the release logic. \n * - * @param tensorDesc Level-2 pointer to the {@link NN_TensorDesc} instance. + * @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 @@ -263,7 +339,7 @@ NN_TensorDesc *OH_NNTensorDesc_Create(); OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); /** - * @brief Set name of a tensorDesc. + * @brief Sets the name of a tensorDesc. * * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor name. \n * @@ -279,7 +355,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char *name); /** - * @brief Get name of a tensorDesc. + * @brief Gets the name of a tensorDesc. * * Call this method to obtain the name of the specified {@link NN_TensorDesc} instance. \n * @@ -287,7 +363,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char * * As an output parameter, *name must be a null pointer, otherwise the method will return an error code. \n * * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. - * @param name Return the name of the tensor. + * @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 @@ -296,7 +372,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char * OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const char **name); /** - * @brief Set data type of a tensorDesc. + * @brief Sets the data type of a tensorDesc. * * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor data type. \n * @@ -312,14 +388,14 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_DataType dataType); /** - * @brief Get data type of a tensorDesc. + * @brief Gets the data type of a 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 Return the data type of the tensor. + * @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 @@ -328,15 +404,15 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_Da OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH_NN_DataType *dataType); /** - * @brief Set shape of a tensorDesc. + * @brief Sets the shape of a 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 shapeLength is 0, this method will return error code. \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 size of the shape list 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 @@ -345,16 +421,16 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeLength); /** - * @brief Get shape of a tensorDesc. + * @brief Gets the shape of a tensorDesc. * * Call this method to obtain the shape of the specified {@link NN_TensorDesc} instance. \n * - * if tensorDesc, shape or shapeLength is a null pointer, this method will return error code. + * 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. \n * * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param shape Return the shape list of the tensor. - * @param shapeLength Return the size of the shape list. + * @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 @@ -363,7 +439,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32 OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength); /** - * @brief Set format of a tensorDesc. + * @brief Sets the format of a tensorDesc. * * After the {@link NN_TensorDesc} instance is created, call this method to set the tensor format. \n * @@ -379,14 +455,14 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32 OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format); /** - * @brief Get format of a tensorDesc. + * @brief Gets the format of a 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 Return the format of the tensor. + * @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 @@ -395,15 +471,15 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Form OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_NN_Format *format); /** - * @brief Get element number of a tensorDesc. + * @brief Gets the element count of a tensorDesc. * - * Call this method to obtain the element number of the specified {@link NN_TensorDesc} instance. + * 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, you can call the {@link OH_NNTensorDesc_GetByteSize} method to obtain it. \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 Return the element number of the tensor. + * @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 @@ -412,7 +488,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_N OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount); /** - * @brief Get byte size of a tensorDesc. + * @brief Gets the byte size of a tensorDesc. * * Call this method to obtain the byte size of the specified {@link NN_TensorDesc} instance. * If you need to obtain element number of the tensor data, you can call the {@link OH_NNTensorDesc_GetElementNum} method to obtain it. \n @@ -420,7 +496,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc * 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 Return the byte size of the tensor. + * @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 @@ -439,7 +515,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, si * * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. - * @return Returns the pointer to a {@link NN_Tensor} instance. + * @return Pointer to a {@link NN_Tensor} instance. * @since 11 * @version 1.0 */ @@ -457,7 +533,7 @@ NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. * @param tensorDesc Pointer to the {@link NN_TensorDesc} instance. * @param size Size of tensor data that need to be allocated. - * @return Returns the pointer to a {@link NN_Tensor} instance. + * @return Pointer to a {@link NN_Tensor} instance. * @since 11 * @version 1.0 */ @@ -481,7 +557,7 @@ NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc * @param fd Fd comes from another {@link NN_Tensor} instance. * @param size Size comes from another {@link NN_Tensor} instance. * @param offset Offset comes from another {@link NN_Tensor} instance. - * @return Returns the pointer to a {@link NN_Tensor} instance. + * @return Pinter to a {@link NN_Tensor} instance. * @since 11 * @version 1.0 */ @@ -500,7 +576,7 @@ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, * * If tensor or *tensor is a null pointer, this method will return error code and does not execute the release logic. \n * - * @param tensorDesc Level-2 pointer to the {@link NN_Tensor} instance. + * @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 @@ -509,43 +585,43 @@ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor); /** - * @brief Get {@link NN_TensorDesc} instance of a tensor. + * @brief Gets the {@link NN_TensorDesc} instance of a tensor. * * Call this method to obtain the {@link NN_TensorDesc} instance of the specified {@link NN_Tensor} instance. - * You can get various tensor information such as name/format/data type/shape from the {@link NN_TensorDesc} instance. \n + * You can get various types of the tensor information such as name/format/data type/shape from the {@link NN_TensorDesc} instance. \n * * if tensor is a null pointer, this method will return null pointer. \n * * @param tensor Pointer to the {@link NN_Tensor} instance. - * @return Returns the pointer to the {@link NN_TensorDesc} instance. If the operation fails, a null pointer is returned. + * @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 Get the data buffer of a tensor. + * @brief Gets the data buffer of a tensor. * * Call this method to obtain the data buffer of the specified {@link NN_Tensor} instance. \n * * if tensor is a null pointer, this method will return null pointer. \n * * @param tensor Pointer to the {@link NN_Tensor} instance. - * @return Returns the pointer to data buffer of the tensor. If the operation fails, a null pointer is returned. + * @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 Get the data size of a tensor. + * @brief Gets the data size of a tensor. * * Call this method to obtain the data size of the specified {@link NN_Tensor} instance. \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 Returns the size of tensor data. + * @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 @@ -554,14 +630,14 @@ void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); /** - * @brief Get the data fd of a tensor. + * @brief Gets the data fd of a tensor. * * Call this method to obtain the data fd of the specified {@link NN_Tensor} instance. \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 Returns the fd of tensor data. + * @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 @@ -577,11 +653,11 @@ OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); * if tensor or offset is a null pointer, this method will return error code. \n * * @param tensor Pointer to the {@link NN_Tensor} instance. - * @param offset Returns the offset of tensor data. + * @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@ + * @version 1.0 */ OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t *offset); @@ -598,7 +674,7 @@ OH_NN_ReturnCode OH_NNTensor_GetOffset(const NN_Tensor *tensor, size_t *offset); * @param compilation Pointer to the {@link OH_NNCompilation} instance. * @return Pointer to a {@link OH_NNExecutor} instance. * @since 9 - * @version 2.0 + * @version 1.0 */ OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation); @@ -619,7 +695,7 @@ OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation); * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, uint32_t outputIndex, @@ -634,36 +710,175 @@ OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, * * 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. + * @param executor Double pointer to the {@link OH_NNExecutor} instance. * @since 9 - * @version 2.0 + * @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 range 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 contains the minimum demensions of the input tensor, and maxInputDims contains the maximum, + * e.g. minInputDims is [1, 10, 10, 3] and maxInputDims is [100, 1024, 1024, 3] with dynamic shape [-1, -1, -1, 3] + * of the input 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 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 yield out the results by inference execution and fill them into output tensors data for you to read. + * 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. + * 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}. \n + * The "userData" 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. + * + * @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. 1000ms. + * @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, @@ -674,12 +889,12 @@ OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, /** - * @brief Obtains the ID of the device connected to Neural Network Runtime. + * @brief Obtains the IDs of all devices connected. * - * 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 + * Each device has a 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. - * The array memory is managed by Neural Network Runtime. + * 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. @@ -687,7 +902,7 @@ OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount); @@ -702,14 +917,14 @@ OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32 * @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 2.0 + * @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: + * 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. @@ -720,7 +935,7 @@ OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name); * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType *deviceType); diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h index 572e400..7e75f14 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h @@ -47,17 +47,82 @@ 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" 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" 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" 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 NN_QuantParam instance needs to be released to avoid memory leak after it is set to a 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. * @@ -68,12 +133,32 @@ OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam **quantParams); * * 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. + * @return Pointer to a {@link OH_NNModel} instance. * @since 9 - * @version 2.0 + * @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 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 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); /** @@ -90,12 +175,34 @@ OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel *model, const NN_TensorD * @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 2.0 + * @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 value 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 value 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); /** @@ -123,7 +230,7 @@ OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_ * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, OH_NN_OperationType op, @@ -148,7 +255,7 @@ OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, const OH_NN_UInt32Array *inputIndices, @@ -169,7 +276,7 @@ OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); @@ -180,9 +287,9 @@ OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); * * 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. + * @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 2.0 + * @version 1.0 */ void OH_NNModel_Destroy(OH_NNModel **model); @@ -206,7 +313,7 @@ void OH_NNModel_Destroy(OH_NNModel **model); * @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 2.0 + * @version 1.0 */ OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model, size_t deviceID, diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h index efdf0ef..d241421 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h @@ -20,19 +20,19 @@ * @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_compat.h * - * @brief The APIs defined in this document are all compatible interfaces of the previous version, which will be deprecated after five versions, - * and it is recommended to use the new APIs defined by neural_network_core.h and neural_network_runtime.h. + * @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 */ @@ -40,15 +40,11 @@ #define NEURAL_NETWORK_RUNTIME_COMPAT_H #include "neural_network_runtime_type.h" -#include "neural_network_core.h" -#include "neural_network_runtime.h" #ifdef __cplusplus extern "C" { #endif -// todo 增加废弃标志,在使用这些接口时进行告警提示(注释,log等) - /** * @brief Adds a tensor to a model instance. * @@ -65,6 +61,8 @@ extern "C" { * @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 */ @@ -98,6 +96,8 @@ OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *ten * @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, * 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 */ @@ -130,6 +130,8 @@ OH_NN_ReturnCode OH_NNExecutor_SetInput(OH_NNExecutor *executor, * @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, * 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 */ @@ -146,6 +148,8 @@ OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, * @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, * 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 */ @@ -164,6 +168,8 @@ OH_NN_ReturnCode OH_NNExecutor_Run(OH_NNExecutor *executor); * 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 */ @@ -182,6 +188,8 @@ OH_NN_Memory *OH_NNExecutor_AllocateInputMemory(OH_NNExecutor *executor, uint32_ * 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 */ @@ -200,7 +208,9 @@ OH_NN_Memory *OH_NNExecutor_AllocateOutputMemory(OH_NNExecutor *executor, uint32 * @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 */ @@ -218,7 +228,9 @@ void OH_NNExecutor_DestroyInputMemory(OH_NNExecutor *executor, uint32_t inputInd * @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 */ @@ -239,6 +251,8 @@ void OH_NNExecutor_DestroyOutputMemory(OH_NNExecutor *executor, uint32_t outputI * @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 */ @@ -261,6 +275,8 @@ OH_NN_ReturnCode OH_NNExecutor_SetInputWithMemory(OH_NNExecutor *executor, * @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 */ 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 ec521fd..74b2855 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 @@ -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,17 +61,35 @@ 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; /** @@ -114,7 +132,7 @@ typedef enum { * @brief Defines error codes for Neural Network Runtime. * * @since 9 - * @version 1.0 + * @version 2.0 */ typedef enum { /** The operation is successful. */ @@ -143,18 +161,42 @@ typedef enum { * @since 11 */ OH_NN_UNSUPPORTED = 10, - /** Connect Exception. + /** Connection Exception. * @since 11 */ - OH_NN_CONNECT_EXCEPTION = 11, + OH_NN_CONNECTION_EXECEPTION = 11, /** Save cache exception. * @since 11 */ OH_NN_SAVE_CACHE_EXCEPTION = 12 } OH_NN_ReturnCode; + +/** + * @brief Defines the callback function handle for the post-process when the asynchronous execution has been done. + * + * Use the first argument to identify the asynchronous execution you want to get. + * It is the argument "userData" passed to {@link OH_NNExecutor_RunAsync}. \n + * Use the second argument 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" 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" passed to {@link OH_NNExecutor_RunAsync} + * @param outputCount Output tensor count, which are same as argument "outputCount" 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" passed to {@link OH_NNExecutor_RunAsync}. + * @since 11 + * @version 1.0 + */ typedef void (*NN_OnServiceDied)(void*); /** @@ -176,7 +218,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). */ @@ -1777,7 +1819,7 @@ typedef struct OH_NN_QuantParam { * you need to specify the data type, number of dimensions, dimension information, and quantization information. * * @deprecated since 11 - * @useinstead {@link NN_Tensor} + * @useinstead {@link NN_TensorDesc} * @since 9 * @version 1.0 */ -- Gitee From 67fd95c77e9cc59952933d13bfd7b4289ac8d9ea Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 09:38:24 +0800 Subject: [PATCH 29/51] update nnCompiler, 1209-v2 --- frameworks/native/nncompiler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 2a8385c..e119d0e 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -214,9 +214,12 @@ OH_NN_ReturnCode NNCompiler::Build() // cache存在,从cache直接复原prepareModel、input/output TensorDesc OH_NN_ReturnCode ret = RestoreFromCacheFile(); if (ret == OH_NN_SUCCESS) { - LOGI("[NNCompiler] Build Success, restore from cache file."); + 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 OH_NN_FAILED; } // cache不存在,正常在线构图 -- Gitee From 2692b7d8b2a9e684b2eb1a07e63572687c2bc740 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Sat, 9 Dec 2023 11:33:58 +0800 Subject: [PATCH 30/51] tensor bugfix --- frameworks/native/neural_network_core.cpp | 22 ++++++++++++++++++-- frameworks/native/nntensor.cpp | 25 ++++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 7e675a5..5352ff1 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -785,6 +785,25 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( 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); @@ -793,14 +812,13 @@ NNRT_API NN_Tensor* OH_NNTensor_CreateWithFd( return nullptr; } - TensorDesc* descImpl = reinterpret_cast(tensorDesc); Tensor* tensorImpl = backend->CreateTensor(descImpl); if (tensorImpl == nullptr) { LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); return nullptr; } - OH_NN_ReturnCode ret = tensorImpl->CreateData(fd, size, offset); + ret = tensorImpl->CreateData(fd, size, offset); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNTensor_CreateWithFd failed, failed to create tensor."); backend->DestroyTensor(tensorImpl); diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index 8f34ca1..496158d 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -79,8 +79,19 @@ OH_NN_ReturnCode NNTensor2_0::CreateData(size_t 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; + } - auto ret = AllocateMemory(size); + ret = AllocateMemory(size); if (ret != OH_NN_SUCCESS) { LOGE("NNTensor2_0::CreateData failed, failed to allocate memory."); return ret; @@ -102,6 +113,18 @@ OH_NN_ReturnCode NNTensor2_0::CreateData(int fd, size_t size, size_t offset) 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; -- Gitee From 33507f3ccf6e7c5ca4168b4d42caf48685c3a8fb Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 15:07:04 +0800 Subject: [PATCH 31/51] update nncore.cpp, bugfix --- frameworks/native/neural_network_core.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 5352ff1..1bbb1f5 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -282,6 +282,11 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati 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); -- Gitee From 16c91feeab14b3750e03a9f4a3ca17363079aed3 Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 16:28:27 +0800 Subject: [PATCH 32/51] update nncore, 1209-v2 --- frameworks/native/backend_manager.cpp | 8 ++++---- frameworks/native/backend_registrar.cpp | 2 +- frameworks/native/neural_network_core.cpp | 13 +++++++------ frameworks/native/nncompiled_cache.cpp | 8 ++++---- frameworks/native/nncompiler.cpp | 4 ++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp index a3aa14a..7c7e2ac 100644 --- a/frameworks/native/backend_manager.cpp +++ b/frameworks/native/backend_manager.cpp @@ -30,7 +30,7 @@ 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=%zu", backendID); + LOGE("[BackendManager] GetBackend failed, not find backendId=%{public}zu", backendID); return nullptr; } @@ -42,7 +42,7 @@ 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 %zu is not registered.", backendID); + LOGE("[BackendManager] GetBackendName failed, backendID %{public}zu is not registered.", backendID); return m_tmpBackendName; } @@ -72,8 +72,8 @@ OH_NN_ReturnCode BackendManager::RegisterBackend(std::function lock(m_mtx); auto setResult = m_backendIDs.emplace(backendID); if (!setResult.second) { - LOGE("[BackendManager] RegisterBackend failed, backend already exists, cannot register again. backendID=%zu", - backendID); + LOGE("[BackendManager] RegisterBackend failed, backend already exists, cannot register again. " + "backendID=%{public}zu", backendID); return OH_NN_FAILED; } diff --git a/frameworks/native/backend_registrar.cpp b/frameworks/native/backend_registrar.cpp index b50ed87..99ec5ce 100644 --- a/frameworks/native/backend_registrar.cpp +++ b/frameworks/native/backend_registrar.cpp @@ -11,7 +11,7 @@ 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=%d", ret); + LOGW("[BackendRegistrar] Register backend failed. ErrorCode=%{public}d", ret); } } } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 1bbb1f5..8cc6637 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -76,7 +76,7 @@ NNRT_API OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name 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 %zu.", deviceID); + LOGE("OH_NNDevice_GetName failed, error happened when getting name of deviceID %{public}zu.", deviceID); *name = nullptr; return OH_NN_FAILED; } @@ -101,7 +101,7 @@ NNRT_API OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType* OH_NN_ReturnCode ret = backend->GetBackendType(*deviceType); if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNDevice_GetType failed, device id: %zu.", deviceID); + LOGE("OH_NNDevice_GetType failed, device id: %{public}zu.", deviceID); return ret; } return OH_NN_SUCCESS; @@ -297,7 +297,8 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati auto emplaceResult = compilationImpr->configs.emplace(configNameStr, configValueVec); if (!emplaceResult.second) { - LOGE("OH_NNCompilation_AddExtensionConfig failed, configName %s already exists, don't set again.", configName); + LOGE("OH_NNCompilation_AddExtensionConfig failed, configName %{public}s already exists," + "don't set again.", configName); return OH_NN_FAILED; } @@ -386,7 +387,7 @@ Compiler* CreateCompiler(Compilation* compilation) BackendManager& manager = BackendManager::GetInstance(); std::shared_ptr backend = manager.GetBackend(compilation->backendID); if(backend == nullptr) { - LOGE("CreateCompiler failed, fail to get backend."); + LOGE("CreateCompiler failed, fail to get backend %{public}zu.", compilation->backendID); return nullptr; } @@ -412,7 +413,7 @@ OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) } OH_NN_ReturnCode ret = OH_NN_SUCCESS; - if (compilation->cachePath != nullptr){ + 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."); @@ -516,7 +517,7 @@ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) BackendManager& manager = BackendManager::GetInstance(); std::shared_ptr backend = manager.GetBackend(compilationImpr->backendID); if(backend == nullptr) { - LOGE("OH_NNCompilation_Destroy failed, fail to get backend."); + LOGE("OH_NNCompilation_Destroy failed, fail to get backend %{public}zu.", compilationImpr->backendID); } OH_NN_ReturnCode ret = backend->DestroyCompiler(compilationImpr->compiler); diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 9dde0c0..b87c87b 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -148,14 +148,14 @@ 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 %zu is not exist.", backendID); + 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 %zu is not exist.", backendID); + LOGE("[NNCompiledCache] SetBackend failed, device with backendID %{public}zu is not exist.", backendID); return OH_NN_FAILED; } @@ -295,8 +295,8 @@ OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCache // 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=%zu in the cache files is different from current " - "deviceId=%zu," + 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); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index e119d0e..7523d8b 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -140,7 +140,7 @@ OH_NN_ReturnCode NNCompiler::SetPerformance(OH_NN_PerformanceMode performance) } if (!Validation::ValidatePerformanceMode(performance)) { - LOGE("[NNCompiler] SetPerformance failed, performance=%d is invalid", performance); + LOGE("[NNCompiler] SetPerformance failed, performance=%{public}d is invalid", performance); return OH_NN_INVALID_PARAMETER; } @@ -168,7 +168,7 @@ OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) } if (!Validation::ValidatePriority(priority)) { - LOGE("[NNCompiler] SetPriority failed, priority=%d is invalid.", priority); + LOGE("[NNCompiler] SetPriority failed, priority=%{public}d is invalid.", priority); return OH_NN_INVALID_PARAMETER; } -- Gitee From 7a79bd674b11223f71abba06eb2aca9b1631fad5 Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 16:48:15 +0800 Subject: [PATCH 33/51] update nncore.cpp, 1209-v2 --- frameworks/native/neural_network_core.cpp | 4 ++-- frameworks/native/nncompiler.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 8cc6637..429e96d 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -440,13 +440,13 @@ OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) } ret = compilation->compiler->SetExtensionConfig(compilation->configs); - if (ret != OH_NN_SUCCESS) { + if ((ret != OH_NN_SUCCESS) && (ret != OH_NN_UNSUPPORTED)) { LOGE("SetCompilationOptions failed, fail to set extenstion configs."); return OH_NN_FAILED; } ret = compilation->compiler->SetOptions(compilation->options); - if (ret != OH_NN_SUCCESS) { + if ((ret != OH_NN_SUCCESS) && (ret != OH_NN_UNSUPPORTED)) { LOGE("SetCompilationOptions failed, fail to set extenstion options."); return OH_NN_FAILED; } diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 7523d8b..c847e5f 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -397,13 +397,14 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheBuffer(const void* buffer, size_t l OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& configs) { - LOGI("[NNCompiler] SetExtensionConfig complete successfully."); + LOGI("[NNCompiler] SetExtensionConfig successfully."); return OH_NN_SUCCESS; } OH_NN_ReturnCode NNCompiler::SetOptions(const std::vector>& options) { - return OH_NN_SUCCESS; + LOGE("[NNCompiler] Not support to set extented options for NN compiler."); + return OH_NN_UNSUPPORTED; } NNExecutor* NNCompiler::CreateExecutor() -- Gitee From 6cd9d6aa83326169c8a3c4793620e4c7d71ce779 Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 17:23:46 +0800 Subject: [PATCH 34/51] update nnbackend, bugfix --- frameworks/native/nnbackend.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 90584ef..5cff856 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -98,16 +98,21 @@ Compiler* NNBackend::CreateCompiler(Compilation* compilation) 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 if (compilation->nnModel != nullptr) { - nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); } else { - LOGE("[NNBackend] CreateCompiler failed, only support build NN model and NN model cache."); - return nullptr; + nnCompiler = new (std::nothrow) NNCompiler(compilation->nnModel, m_device, m_backendID); } if (nnCompiler == nullptr) { -- Gitee From 0899f06998c961eaf73d78bc225b5377b1f3ef49 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Sat, 9 Dec 2023 17:41:10 +0800 Subject: [PATCH 35/51] bugfix --- frameworks/native/nntensor.cpp | 4 ++-- frameworks/native/validation.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index 496158d..e2b9d1b 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -132,7 +132,7 @@ OH_NN_ReturnCode NNTensor2_0::CreateData(int fd, size_t size, size_t offset) 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."); + LOGE("NNTensor2_0::AllocateMemory failed, Map fd to address failed: %{public}s.", strerror(errno)); m_data = nullptr; return OH_NN_MEMORY_ERROR; } @@ -201,7 +201,7 @@ OH_NN_ReturnCode NNTensor2_0::AllocateMemory(size_t length) 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."); + LOGE("NNTensor2_0::AllocateMemory failed, Map fd to address failed: %{public}s.", strerror(errno)); m_data = nullptr; return OH_NN_MEMORY_ERROR; } diff --git a/frameworks/native/validation.cpp b/frameworks/native/validation.cpp index 6f87bcf..69204c6 100644 --- a/frameworks/native/validation.cpp +++ b/frameworks/native/validation.cpp @@ -28,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; -- Gitee From c8a1a003019309764c47b9e7f282a6e26d3b52ff Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 18:34:50 +0800 Subject: [PATCH 36/51] update return code --- frameworks/native/neural_network_core.cpp | 72 ++++++++++++----------- frameworks/native/nnbackend.cpp | 4 +- frameworks/native/nncompiler.cpp | 10 ++-- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 429e96d..f4a08b5 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -27,7 +27,7 @@ using namespace OHOS::NeuralNetworkRuntime; #define NNRT_API __attribute__((visibility("default"))) -OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32_t *deviceCount) +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."); @@ -107,7 +107,7 @@ NNRT_API OH_NN_ReturnCode OH_NNDevice_GetType(size_t deviceID, OH_NN_DeviceType* return OH_NN_SUCCESS; } -OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) +NNRT_API OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) { if (model == nullptr) { LOGE("OH_NNCompilation_Construct failed, passed nullptr to model."); @@ -126,7 +126,7 @@ OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model) return nnCompilation; } -OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *modelPath) +NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *modelPath) { if (modelPath == nullptr) { LOGE("OH_NNCompilation_ConstructWithOfflineModelFile failed, passed nullptr to modelPath."); @@ -145,7 +145,7 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *mod return nnCompilation; } -OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *modelBuffer, size_t modelSize) +NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *modelBuffer, size_t modelSize) { if (modelBuffer == nullptr) { LOGE("OH_NNCompilation_ConstructWithOfflineModelBuffer failed, modelBuffer is nullptr."); @@ -170,7 +170,7 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *m return nnCompilation; } -OH_NNCompilation *OH_NNCompilation_ConstructForCache() +NNRT_API NNRT_API OH_NNCompilation *OH_NNCompilation_ConstructForCache() { Compilation *compilation = new (std::nothrow) Compilation(); if (compilation == nullptr) { @@ -182,10 +182,10 @@ OH_NNCompilation *OH_NNCompilation_ConstructForCache() return nnCompilation; } -OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilation, - const void *buffer, - size_t length, - size_t *modelSize) +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."); @@ -221,9 +221,9 @@ OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilat return ret; } -OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compilation, - const void *buffer, - size_t modelSize) +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."); @@ -254,10 +254,10 @@ OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compil return ret; } -OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, - const char *configName, - const void *configValue, - const size_t configValueSize) +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."); @@ -305,7 +305,7 @@ OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilati return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_t deviceID) +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."); @@ -318,7 +318,9 @@ OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_ return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const char *cachePath, uint32_t version) +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."); @@ -337,8 +339,8 @@ OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilation, - OH_NN_PerformanceMode performanceMode) +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."); @@ -351,7 +353,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilati return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_NN_Priority priority) +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."); @@ -364,7 +366,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetPriority(OH_NNCompilation *compilation, OH_ return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16) +NNRT_API OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, bool enableFloat16) { if (compilation == nullptr) { LOGE("OH_NNCompilation_EnableFloat16 failed, compilation is nullptr."); @@ -417,44 +419,44 @@ OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) ret = compilation->compiler->SetCacheDir(compilation->cachePath, compilation->cacheVersion); if (ret != OH_NN_SUCCESS) { LOGE("SetCompilationOptions failed, fail to set cache dir."); - return OH_NN_FAILED; + return ret; } } - + ret = compilation->compiler->SetEnableFp16(compilation->enableFp16); if (ret != OH_NN_SUCCESS) { LOGE("SetCompilationOptions failed, fail to set enable fp16."); - return OH_NN_FAILED; + return ret; } ret = compilation->compiler->SetPerformance(compilation->performance); if (ret != OH_NN_SUCCESS) { LOGE("SetCompilationOptions failed, fail to set performance."); - return OH_NN_FAILED; + return ret; } ret = compilation->compiler->SetPriority(compilation->priority); if (ret != OH_NN_SUCCESS) { LOGE("SetCompilationOptions failed, fail to set priority."); - return OH_NN_FAILED; + 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 OH_NN_FAILED; + 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 OH_NN_FAILED; + return ret; } return OH_NN_SUCCESS; } -OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) +NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) { if (compilation == nullptr) { LOGE("OH_NNCompilation_Build failed, compilation is nullptr."); @@ -484,7 +486,7 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) OH_NN_ReturnCode ret = SetCompilationOptions(compilationImpr); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNCompilation_Build failed, faile to create compiler."); - return OH_NN_FAILED; + return ret; } bool isBuild = compilationImpr->compiler->IsBuild(); @@ -496,20 +498,22 @@ OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) ret = compilationImpr->compiler->Build(); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNCompilation_Build failed, faile to build compilation."); - return OH_NN_FAILED; + return ret; } return OH_NN_SUCCESS; } -void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) +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); @@ -518,11 +522,13 @@ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation) 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; } } diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 5cff856..80fb5af 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -70,7 +70,7 @@ OH_NN_ReturnCode NNBackend::GetBackendType(OH_NN_DeviceType& backendType) const OH_NN_ReturnCode ret = m_device->GetDeviceType(backendType); if (ret != OH_NN_SUCCESS) { LOGE("[NNBackend] GetBackendType failed, fail to get device type"); - return OH_NN_FAILED; + return ret; } return OH_NN_SUCCESS; @@ -86,7 +86,7 @@ OH_NN_ReturnCode NNBackend::GetBackendStatus(DeviceStatus& status) const OH_NN_ReturnCode ret = m_device->GetDeviceStatus(status); if (ret != OH_NN_SUCCESS) { LOGE("[NNBackend] GetBackendStatus failed, fail to get device status"); - return OH_NN_FAILED; + return ret; } return OH_NN_SUCCESS; } diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index c847e5f..5ade4b6 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -159,7 +159,7 @@ OH_NN_ReturnCode NNCompiler::SetPriority(OH_NN_Priority priority) OH_NN_ReturnCode ret = m_device->IsPrioritySupported(isSupportedPriority); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SetPriority failed, fail to call device."); - return OH_NN_FAILED; + return ret; } if (!isSupportedPriority && (priority != OH_NN_PRIORITY_NONE)) { @@ -187,7 +187,7 @@ OH_NN_ReturnCode NNCompiler::SetEnableFp16(bool isFp16) OH_NN_ReturnCode ret = m_device->IsFloat16PrecisionSupported(isSupportedFp16); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SetEnableFp16 failed, fail to call device."); - return OH_NN_FAILED; + return ret; } if (!isSupportedFp16 && isFp16) { @@ -219,7 +219,7 @@ OH_NN_ReturnCode NNCompiler::Build() return OH_NN_SUCCESS; } else if (m_model == nullptr) { LOGI("[NNCompiler] Build failed, fail to restore from cache file."); - return OH_NN_FAILED; + return ret; } // cache不存在,正常在线构图 @@ -250,7 +250,7 @@ OH_NN_ReturnCode NNCompiler::Build() } if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] Build failed, fail to prepare model when normally building."); - return OH_NN_FAILED; + return ret; } m_isBuild = true; @@ -259,7 +259,7 @@ OH_NN_ReturnCode NNCompiler::Build() ret = SaveToCacheFile(); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] Build success, but fail to save cache to file."); - return OH_NN_SAVE_CACHE_EXCEPTION; + return ret; } } -- Gitee From 123d935fce42a1e94dde62b23ff31f956b040807 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Sat, 9 Dec 2023 18:52:59 +0800 Subject: [PATCH 37/51] bugfix --- frameworks/native/nncompiled_cache.cpp | 17 +++++++++++------ frameworks/native/nncompiler.cpp | 4 ++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index b87c87b..d4e5309 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -109,7 +109,7 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, return ret; } - if ((uint64_t)version != cacheInfo.version) { + if ((uint64_t)version > cacheInfo.version) { LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %u, but the cache files " "version is %llu.", version, @@ -117,6 +117,11 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, return OH_NN_INVALID_PARAMETER; } + if ((uint64_t)version < cacheInfo.version) { + LOGE("[NNCompiledCache] 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) { @@ -234,15 +239,15 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector(GetCrc16(static_cast(caches[i].data), caches[i].length)); *cacheInfoPtr++ = checkSum; if (!cacheModelStream.write(static_cast(caches[i].data), caches[i].length)) { - LOGE("[Compilation] Fail to write cache model."); + LOGE("[NNCompiledCache] Fail to write cache model."); cacheModelStream.close(); return OH_NN_SAVE_CACHE_EXCEPTION; }; @@ -260,12 +265,12 @@ OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, 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("[Compilation] Model cache info file is invalid."); + LOGE("[NNCompiledCache] 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."); + LOGE("[NNCompiledCache] Fail to write cache info."); cacheInfoStream.close(); return OH_NN_SAVE_CACHE_EXCEPTION; } diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 5ade4b6..a9e5698 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -213,6 +213,10 @@ OH_NN_ReturnCode NNCompiler::Build() // 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; -- Gitee From ce0dd0a0e98f4ece18617c6e967080ce317c5574 Mon Sep 17 00:00:00 2001 From: maoyong Date: Sat, 9 Dec 2023 19:42:33 +0800 Subject: [PATCH 38/51] bugfix, judge support nnmodel. --- frameworks/native/nncompiler.cpp | 27 ++++++++++++++++++++++++++- frameworks/native/nncompiler.h | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index a9e5698..dc6d56f 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -5,7 +5,6 @@ #include #include -#include "mindir.h" #include "inner_model.h" #include "validation.h" #include "nncompiled_cache.h" @@ -204,6 +203,26 @@ bool NNCompiler::IsBuild() const return m_isBuild; } +OH_NN_ReturnCode NNCompiler::IsSupportModel(std::shared_ptr& liteGraph) +{ + 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); + return OH_NN_FAILED; + } + } + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode NNCompiler::Build() { if (m_isBuild) { @@ -244,6 +263,12 @@ OH_NN_ReturnCode NNCompiler::Build() return OH_NN_INVALID_PARAMETER; } + ret = IsSupportModel(liteGraph); + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] Build failed, current device not support the model."); + return ret; + } + ModelConfig config {m_enableFp16, static_cast(m_performance), static_cast(m_priority)}; if (liteGraph != nullptr) { diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 4332669..23570ea 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -1,5 +1,6 @@ #include "compiler.h" +#include "mindir.h" #include "device.h" #include "inner_model.h" #include "prepared_model.h" @@ -37,6 +38,7 @@ public: OH_NN_ReturnCode SetOptions(const std::vector>& options) override; NNExecutor* CreateExecutor(); + OH_NN_ReturnCode IsSupportModel(std::shared_ptr& liteGraph); private: OH_NN_ReturnCode SerializeTensorsToBuffer( -- Gitee From 41b7b910096409a0e99d3d6e9457073275c92a83 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Sun, 10 Dec 2023 17:17:34 +0800 Subject: [PATCH 39/51] xts bugfix --- frameworks/native/inner_model.cpp | 26 ++-- frameworks/native/inner_model.h | 4 +- frameworks/native/neural_network_core.cpp | 15 +- frameworks/native/nncompiled_cache.cpp | 22 --- frameworks/native/nncompiled_cache.h | 6 - frameworks/native/nncompiler.cpp | 142 +++++++++++++++--- frameworks/native/nncompiler.h | 9 +- frameworks/native/nnexecutor.cpp | 125 +++++++++++---- frameworks/native/nnexecutor.h | 14 +- frameworks/native/ops_builder.cpp | 4 +- frameworks/native/tensor_desc.cpp | 8 +- .../neural_network_runtime_type.h | 6 +- 12 files changed, 266 insertions(+), 115 deletions(-) diff --git a/frameworks/native/inner_model.cpp b/frameworks/native/inner_model.cpp index 8a4281f..2b275ba 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -720,27 +720,29 @@ std::vector> InnerModel::GetOutputTensors() const return m_outputTensors; } -std::vector> InnerModel::GetInputTensorDescs() const +std::vector, OH_NN_TensorType>> InnerModel::GetInputTensorDescs() const { - std::vector> inputTensorDescs; - std::shared_ptr tensorDesc; + std::vector, OH_NN_TensorType>> inputTensorDescs; + std::pair, OH_NN_TensorType> tensorDescPair; for (auto inputTensor : m_inputTensors) { - tensorDesc = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); - inputTensor->ConvertToTensorDesc(*(tensorDesc.get())); - inputTensorDescs.emplace_back(tensorDesc); + tensorDescPair.first = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + inputTensor->ConvertToTensorDesc(*(tensorDescPair.first.get())); + tensorDescPair.second = inputTensor->GetType(); + inputTensorDescs.emplace_back(tensorDescPair); } return inputTensorDescs; } -std::vector> InnerModel::GetOutputTensorDescs() const +std::vector, OH_NN_TensorType>> InnerModel::GetOutputTensorDescs() const { - std::vector> outputTensorDescs; - std::shared_ptr tensorDesc; + std::vector, OH_NN_TensorType>> outputTensorDescs; + std::pair, OH_NN_TensorType> tensorDescPair; for (auto outputTensor : m_outputTensors) { - tensorDesc = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); - outputTensor->ConvertToTensorDesc(*(tensorDesc.get())); - outputTensorDescs.emplace_back(tensorDesc); + tensorDescPair.first = OHOS::NeuralNetworkRuntime::CreateSharedPtr(); + outputTensor->ConvertToTensorDesc(*(tensorDescPair.first.get())); + tensorDescPair.second = outputTensor->GetType(); + outputTensorDescs.emplace_back(tensorDescPair); } return outputTensorDescs; diff --git a/frameworks/native/inner_model.h b/frameworks/native/inner_model.h index 2c54c5a..a538ed0 100644 --- a/frameworks/native/inner_model.h +++ b/frameworks/native/inner_model.h @@ -52,8 +52,8 @@ public: OH_NN_ReturnCode Build(); std::vector> GetInputTensors() const; std::vector> GetOutputTensors() const; - std::vector> GetInputTensorDescs() const; - std::vector> GetOutputTensorDescs() 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/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index f4a08b5..78b2a92 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -476,13 +476,15 @@ NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) return OH_NN_INVALID_PARAMETER; } - Compiler* nnCompiler = CreateCompiler(compilationImpr); - if (nnCompiler == nullptr) { - LOGE("OH_NNCompilation_Build failed, faile to create compiler."); - return OH_NN_FAILED; + if (compilationImpr->compiler == nullptr) { + Compiler* nnCompiler = CreateCompiler(compilationImpr); + if (nnCompiler == nullptr) { + LOGE("OH_NNCompilation_Build failed, faile to create compiler."); + return OH_NN_FAILED; + } + compilationImpr->compiler = nnCompiler; } - compilationImpr->compiler = nnCompiler; OH_NN_ReturnCode ret = SetCompilationOptions(compilationImpr); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNCompilation_Build failed, faile to create compiler."); @@ -492,7 +494,7 @@ NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) bool isBuild = compilationImpr->compiler->IsBuild(); if (isBuild) { LOGE("OH_NNCompilation_Build failed, compilation has been built, don't build again."); - return OH_NN_FAILED; + return OH_NN_OPERATION_FORBIDDEN; } ret = compilationImpr->compiler->Build(); @@ -1104,7 +1106,6 @@ NNRT_API OH_NN_ReturnCode OH_NNExecutor_GetInputDimRange(const OH_NNExecutor *ex return OH_NN_INVALID_PARAMETER; } - const Executor *executorImpl = reinterpret_cast(executor); return executorImpl->GetInputDimRange(index, minInputDims, maxInputDims, shapeLength); } diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index d4e5309..aa4af48 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -173,28 +173,6 @@ void NNCompiledCache::SetModelName(const std::string& modelName) m_modelName = modelName; } -void NNCompiledCache::SetInputTensorDescs( - std::vector> inputTensorDescs) -{ - m_inputTensorDescs = inputTensorDescs; -} - -void NNCompiledCache::SetOutputTensorDescs( - std::vector> outputTensorDescs) -{ - m_outputTensorDescs = outputTensorDescs; -} - -std::vector> NNCompiledCache::GetInputTensorDescs() const -{ - return m_inputTensorDescs; -} - -std::vector> NNCompiledCache::GetOutputTensorDescs() const -{ - return m_outputTensorDescs; -} - OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, const std::string& cacheDir, uint32_t version) const diff --git a/frameworks/native/nncompiled_cache.h b/frameworks/native/nncompiled_cache.h index 6b514f2..842c313 100644 --- a/frameworks/native/nncompiled_cache.h +++ b/frameworks/native/nncompiled_cache.h @@ -49,10 +49,6 @@ public: OH_NN_ReturnCode SetBackend(size_t backendID); void SetModelName(const std::string& modelName); - void SetInputTensorDescs(std::vector> inputTensorDescs); - void SetOutputTensorDescs(std::vector> outputTensorDescs); - std::vector> GetInputTensorDescs() const; - std::vector> GetOutputTensorDescs() const; private: OH_NN_ReturnCode GenerateCacheFiles(const std::vector& caches, @@ -75,8 +71,6 @@ private: size_t m_backendID {0}; std::string m_modelName; std::shared_ptr m_device {nullptr}; - std::vector> m_inputTensorDescs; - std::vector> m_outputTensorDescs; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index dc6d56f..a224d1f 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -18,32 +18,38 @@ public: SerializedTensorDesc() = default; ~SerializedTensorDesc() = default; - OH_NN_ReturnCode CopyFromTensorDesc(const TensorDesc& tensorDesc) + OH_NN_ReturnCode CopyFromTensorDesc(const std::pair, OH_NN_TensorType>& tensorDesc) { - OH_NN_ReturnCode ret = tensorDesc.GetDataType(&m_dataType); + 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.GetFormat(&m_format); + 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.GetShape(&m_shape, &m_shapeNum); + 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.GetName(&m_name); + 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; } @@ -78,6 +84,7 @@ public: 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 @@ -85,6 +92,7 @@ public: 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 @@ -113,6 +121,23 @@ size_t NNCompiler::GetBackendID() const 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 OH_NN_FAILED; + } + + 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; @@ -469,13 +494,13 @@ NNExecutor* NNCompiler::CreateExecutor() } OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( - const std::vector>& tensorDescs, Buffer& buffer) const + 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.get())); + ret = immediateTensorDesc.CopyFromTensorDesc(tensorDesc); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SerializeInputsToBuffer failed, error happened when copying tensorDesc to " "SerializedTensorDesc."); @@ -489,6 +514,7 @@ OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( 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; @@ -496,24 +522,61 @@ OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( // 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) { - memcpy_s(currentPos, SIZE_OF_DATATYPE, &tensorDesc.m_dataType, SIZE_OF_DATATYPE); + 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; - memcpy_s(currentPos, SIZE_OF_FORMAT, &tensorDesc.m_format, SIZE_OF_FORMAT); + 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; - memcpy_s(currentPos, SIZE_OF_SHAPE_NUM, &tensorDesc.m_shapeNum, SIZE_OF_SHAPE_NUM); + 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); - memcpy_s(currentPos, sizeOfShape, tensorDesc.m_shape, sizeOfShape); + 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; - strcpy_s(currentPos, strlen(tensorDesc.m_name) + 1, tensorDesc.m_name); + 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; } @@ -524,7 +587,7 @@ OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( } OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( - const Buffer& buffer, std::vector>& tensorDescs) + const Buffer& buffer, std::vector, OH_NN_TensorType>>& tensorDescs) { std::vector immediateTensorDescs; const char* ptr = static_cast(buffer.data); @@ -532,17 +595,44 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( while (ptr < end) { SerializedTensorDesc desc; - memcpy_s(&desc.m_dataType, SIZE_OF_DATATYPE, ptr, sizeof(desc.m_dataType)); + 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."); + return OH_NN_MEMORY_ERROR; + } ptr += sizeof(desc.m_dataType); - memcpy_s(&desc.m_format, SIZE_OF_FORMAT, ptr, sizeof(desc.m_format)); + 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."); + return OH_NN_MEMORY_ERROR; + } ptr += sizeof(desc.m_format); - memcpy_s(&desc.m_shapeNum, SIZE_OF_SHAPE_NUM, ptr, sizeof(desc.m_shapeNum)); + 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."); + 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."); + return OH_NN_MEMORY_ERROR; + } ptr += sizeof(desc.m_shapeNum); - desc.m_shape = new int32_t[desc.m_shapeNum]; - memcpy_s(desc.m_shape, desc.m_shapeNum * sizeof(int32_t), ptr, desc.m_shapeNum * sizeof(int32_t)); + desc.m_shape = new int32_t[desc.m_shapeNum]; // todo 何时删除 + if (desc.m_shape == nullptr) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to create shape buffer."); + 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."); + return OH_NN_MEMORY_ERROR; + } ptr += desc.m_shapeNum * sizeof(int32_t); desc.m_name = ptr; @@ -553,15 +643,23 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( OH_NN_ReturnCode ret {OH_NN_SUCCESS}; for (const auto& immediateTensorDesc : immediateTensorDescs) { - auto tensorDesc = CreateSharedPtr(); - ret = immediateTensorDesc.CopyToTensorDesc(*(tensorDesc.get())); + std::pair, OH_NN_TensorType> tensorDescPair; + tensorDescPair.first = CreateSharedPtr(); + if (tensorDescPair.first == nullptr) { + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, failed to create tensor desc."); + tensorDescs.clear(); + return OH_NN_NULL_PTR; + } + ret = immediateTensorDesc.CopyToTensorDesc(*(tensorDescPair.first.get())); if (ret != OH_NN_SUCCESS) { - LOGE("[NNCompiler] UnserializedInputsFromBuffer failed, error happened when copying " + LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, error happened when copying " "SerializedTensorDesc to TensorDesc."); + tensorDescs.clear(); return ret; } + tensorDescPair.second = immediateTensorDesc.m_tensorType; - tensorDescs.emplace_back(tensorDesc); + tensorDescs.emplace_back(tensorDescPair); } return ret; diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 23570ea..3e99f5b 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -42,9 +42,10 @@ public: private: OH_NN_ReturnCode SerializeTensorsToBuffer( - const std::vector>& tensorDescs, Buffer& buffer) const; + const std::vector, OH_NN_TensorType>>& tensorDescs, + Buffer& buffer) const; OH_NN_ReturnCode DeserializedTensorsFromBuffer( - const Buffer& buffer, std::vector>& tensorDescs); + const Buffer& buffer, std::vector, OH_NN_TensorType>>& tensorDescs); private: void* m_model {nullptr}; @@ -57,8 +58,8 @@ 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}; - std::vector> m_inputTensorDescs; - std::vector> m_outputTensorDescs; + std::vector, OH_NN_TensorType>> m_inputTensorDescs; + std::vector, OH_NN_TensorType>> m_outputTensorDescs; }; } // NeuralNetworkRuntime } // OHOS diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index e616740..6942e51 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -27,8 +27,8 @@ namespace OHOS { namespace NeuralNetworkRuntime { NNExecutor::NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, - std::vector> inputTensorDescs, - std::vector> outputTensorDescs) + const std::vector, OH_NN_TensorType>>& inputTensorDescs, + const std::vector, OH_NN_TensorType>>& outputTensorDescs) { m_backendID = backendID; m_device = device; @@ -89,8 +89,12 @@ OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shap 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]; + auto tensorDesc = m_outputTensorDescs[outputIndex].first; auto ret = tensorDesc->GetShape(shape, shapeNum); if (ret != OH_NN_SUCCESS) { LOGE("NNExecutor::GetOutputShape failed, failed to get shape from tensor desc."); @@ -116,6 +120,10 @@ NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) const 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}u is nullptr.", index); + return nullptr; + } TensorDesc* tensorDescImpl = new (std::nothrow) TensorDesc(); if (tensorDescImpl == nullptr) { @@ -124,7 +132,7 @@ NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) const } // Copy the member attributes to new tensor description - *tensorDescImpl = *(m_inputTensorDescs[index].get()); + *tensorDescImpl = *(m_inputTensorDescs[index].first.get()); return reinterpret_cast(tensorDescImpl); } @@ -135,6 +143,10 @@ NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) const 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}u is nullptr.", index); + return nullptr; + } TensorDesc* tensorDescImpl = new (std::nothrow) TensorDesc(); if (tensorDescImpl == nullptr) { @@ -143,7 +155,7 @@ NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) const } // Copy the member attributes to new tensor description - *tensorDescImpl = *(m_outputTensorDescs[index].get()); + *tensorDescImpl = *(m_outputTensorDescs[index].first.get()); return reinterpret_cast(tensorDescImpl); } @@ -163,6 +175,17 @@ OH_NN_ReturnCode NNExecutor::SetOnServiceDied(NN_OnServiceDied onServiceDied) 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) { @@ -173,11 +196,19 @@ OH_NN_ReturnCode NNExecutor::RunSync(NN_Tensor* inputTensors[], size_t inputSize 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]); } @@ -209,7 +240,7 @@ OH_NN_ReturnCode NNExecutor::RunSync(NN_Tensor* inputTensors[], size_t inputSize " output id: %zu.", i); return ret; } - ret = m_outputTensorDescs[i]->SetShape(outputsDims[i].data(), outputsDims[i].size()); + 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); @@ -242,12 +273,14 @@ OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size } if (inputSize != minInputDims.size()) { - LOGE("NNExecutor::CheckInputDimRanges failed, size of minInputDims is not equal to inputSize."); + 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 is not equal to inputSize."); + LOGE("NNExecutor::CheckInputDimRanges failed, size of maxInputDims:%{public}zu is not equal to " + "inputSize:%{public}zu.", maxInputDims.size(), inputSize); return OH_NN_INVALID_PARAMETER; } @@ -271,10 +304,11 @@ OH_NN_ReturnCode NNExecutor::CheckInputDimRanges(NN_Tensor* inputTensors[], size return OH_NN_SUCCESS; } -bool NNExecutor::CompareAttribute(std::shared_ptr tensorDesc, const NNTensor& tensor) const +bool NNExecutor::CompareAttribute( + const std::pair, OH_NN_TensorType>& tensorDesc, const NNTensor& tensor) const { OH_NN_DataType dataType; - auto ret = tensorDesc->GetDataType(&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; @@ -286,7 +320,7 @@ bool NNExecutor::CompareAttribute(std::shared_ptr tensorDesc, const int32_t* shape {nullptr}; size_t shapeNum {0}; - ret = tensorDesc->GetShape(&shape, &shapeNum); + ret = tensorDesc.first->GetShape(&shape, &shapeNum); if (ret != OH_NN_SUCCESS) { LOGE("CompareAttribute failed, failed to get shape from tensor desc."); return false; @@ -306,6 +340,11 @@ bool NNExecutor::CompareAttribute(std::shared_ptr tensorDesc, const } } + if (tensorDesc.second != tensor.GetType()) { + LOGI("Tensors have different type: %{public}d and %{public}d.", tensorDesc.second, tensor.GetType()); + return false; + } + return true; } @@ -317,6 +356,10 @@ OH_NN_ReturnCode NNExecutor::BuildInputTensor(uint32_t index, const OH_NN_Tensor 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); @@ -331,7 +374,7 @@ OH_NN_ReturnCode NNExecutor::BuildInputTensor(uint32_t index, const OH_NN_Tensor } OH_NN_Format format; - ret = m_inputTensorDescs[index]->GetFormat(&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; @@ -344,7 +387,7 @@ OH_NN_ReturnCode NNExecutor::BuildInputTensor(uint32_t index, const OH_NN_Tensor } const char* name {nullptr}; - ret = m_inputTensorDescs[index]->GetName(&name); + ret = m_inputTensorDescs[index].first->GetName(&name); if (ret != OH_NN_SUCCESS) { LOGE("BuildInputTensor failed, failed to get tensor name from desc."); return ret; @@ -558,7 +601,8 @@ OH_NN_ReturnCode NNExecutor::SetInputFromMemory(uint32_t index, const OH_NN_Tens return OH_NN_SUCCESS; } -std::shared_ptr NNExecutor::BuildNNTensorFromDesc(std::shared_ptr tensorDesc) +std::shared_ptr NNExecutor::BuildNNTensorFromDesc( + const std::pair, OH_NN_TensorType>& tensorDesc) { std::shared_ptr tensor = CreateSharedPtr(); if (tensor == nullptr) { @@ -567,33 +611,34 @@ std::shared_ptr NNExecutor::BuildNNTensorFromDesc(std::shared_ptr(tensorDesc.get()); + 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; } - if (tensor->IsDynamicShape()) { - LOGE("BuildNNTensorFromDesc failed, input nnTensor should has certain dimensions which cannot contain -1."); - return nullptr; - } - OH_NN_Format format; - ret = tensorDesc->GetFormat(&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->GetName(&name); + ret = tensorDesc.first->GetName(&name); if (ret != OH_NN_SUCCESS) { LOGE("BuildNNTensorFromDesc failed, failed to get tensor name from desc."); return nullptr; @@ -608,9 +653,13 @@ OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t leng 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 {0}; - auto ret = m_outputTensorDescs[index]->GetByteSize(&dataLength); + 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; @@ -644,9 +693,13 @@ OH_NN_ReturnCode NNExecutor::SetOutput(uint32_t index, void* buffer, size_t leng ExeTensor exeTensor; m_outputTensors[index] = exeTensor; 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 = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[index]); + 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; @@ -667,9 +720,13 @@ OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Mem 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 {0}; - auto ret = m_outputTensorDescs[index]->GetByteSize(&dataLength); + 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; @@ -690,6 +747,10 @@ OH_NN_ReturnCode NNExecutor::SetOutputFromMemory(uint32_t index, const OH_NN_Mem ExeTensor exeTensor; m_outputTensors[index] = exeTensor; 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 @@ -707,9 +768,13 @@ OH_NN_ReturnCode NNExecutor::CreateInputMemory(uint32_t index, size_t length, OH LOGE("CreateInputMemory failed, input index is out of range."); return OH_NN_INVALID_PARAMETER; } + 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 - void* deviceInputBuffer = m_device->AllocateTensorBuffer(length, m_inputTensorDescs[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; @@ -768,9 +833,13 @@ OH_NN_ReturnCode NNExecutor::CreateOutputMemory(uint32_t index, size_t length, O 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 - void* deviceOutputBuffer = m_device->AllocateTensorBuffer(length, m_outputTensorDescs[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; @@ -861,7 +930,7 @@ OH_NN_ReturnCode NNExecutor::Run(const std::vector>& i LOGE("Run failed, error happened when setting output tensor's dimensions, output id: %zu.", i); return ret; } - ret = m_outputTensorDescs[i]->SetShape(outputsDims[i].data(), outputsDims[i].size()); + 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); diff --git a/frameworks/native/nnexecutor.h b/frameworks/native/nnexecutor.h index 1a0a710..bf011c7 100644 --- a/frameworks/native/nnexecutor.h +++ b/frameworks/native/nnexecutor.h @@ -28,8 +28,8 @@ public: NNExecutor(size_t backendID, std::shared_ptr device, std::shared_ptr preparedModel, - std::vector> inputTensorDescs, - std::vector> outputTensorDescs); + const std::vector, OH_NN_TensorType>>& inputTensorDescs, + const std::vector, OH_NN_TensorType>>& outputTensorDescs); virtual ~NNExecutor(); virtual OH_NN_ReturnCode GetInputDimRange(size_t inputIndex, @@ -76,8 +76,10 @@ private: // The following APIs are compatible with older versions OH_NN_ReturnCode Run(const std::vector>& inputTensors, std::vector>& outputTensors); - bool CompareAttribute(std::shared_ptr tensorDesc, const NNTensor& tensor) const; - std::shared_ptr BuildNNTensorFromDesc(std::shared_ptr tensorDesc); + 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, @@ -90,8 +92,8 @@ private: size_t m_backendID {0}; std::shared_ptr m_device {nullptr}; std::shared_ptr m_preparedModel {nullptr}; - std::vector> m_inputTensorDescs; - std::vector> m_outputTensorDescs; + 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 { 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/tensor_desc.cpp b/frameworks/native/tensor_desc.cpp index 1dd2638..34c3ce4 100644 --- a/frameworks/native/tensor_desc.cpp +++ b/frameworks/native/tensor_desc.cpp @@ -139,9 +139,9 @@ OH_NN_ReturnCode TensorDesc::GetElementNum(size_t* elementNum) const size_t shapeNum = m_shape.size(); for (size_t i = 0; i < shapeNum; ++i) { if (m_shape[i] <= 0) { - LOGE("GetElementNum failed, shape[%{public}zu] should larger than zero, now is %{public}d.", i, m_shape[i]); + LOGW("GetElementNum return 0 with dynamic shape, shape[%{public}zu] is %{public}d.", i, m_shape[i]); *elementNum = 0; - return OH_NN_INVALID_PARAMETER; + return OH_NN_DYNAMIC_SHAPE; } (*elementNum) *= m_shape[i]; } @@ -157,7 +157,9 @@ OH_NN_ReturnCode TensorDesc::GetByteSize(size_t* byteSize) const *byteSize = 0; size_t elementNum = 0; auto ret = GetElementNum(&elementNum); - if (ret != OH_NN_SUCCESS) { + 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; } 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 74b2855..02cc266 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 @@ -168,7 +168,11 @@ typedef enum { /** Save cache exception. * @since 11 */ - OH_NN_SAVE_CACHE_EXCEPTION = 12 + OH_NN_SAVE_CACHE_EXCEPTION = 12, + /** Dynamic shape. + * @since 11 + */ + OH_NN_DYNAMIC_SHAPE = 13 } OH_NN_ReturnCode; -- Gitee From 8ef2d0bb3e424c6d332242bbc3691e2f515693e0 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 11 Dec 2023 10:23:56 +0800 Subject: [PATCH 40/51] tnesor and des sep --- frameworks/native/nnbackend.cpp | 9 ++++- frameworks/native/nncompiled_cache.cpp | 6 +-- frameworks/native/nncompiler.cpp | 53 +++++++++++++++++++++++++- frameworks/native/nncompiler.h | 2 + frameworks/native/nntensor.cpp | 32 ++++++++++++++-- frameworks/native/nntensor.h | 4 +- frameworks/native/tensor.h | 3 +- testdemo/demo.cpp | 11 ++++++ 8 files changed, 108 insertions(+), 12 deletions(-) diff --git a/frameworks/native/nnbackend.cpp b/frameworks/native/nnbackend.cpp index 80fb5af..fde6190 100644 --- a/frameworks/native/nnbackend.cpp +++ b/frameworks/native/nnbackend.cpp @@ -178,12 +178,19 @@ Tensor* NNBackend::CreateTensor(TensorDesc* desc) return nullptr; } - NNTensor2_0* tensorImpl = new (std::nothrow) NNTensor2_0(m_backendID, desc); + 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); } diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index aa4af48..2e2c27b 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -78,8 +78,8 @@ OH_NN_ReturnCode NNCompiledCache::Save(const std::vector& caches) + uint32_t version, + std::vector& caches) { if (cacheDir.empty()) { LOGE("[NNCompiledCache] Restore failed, cacheDir is empty."); @@ -304,7 +304,7 @@ OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCache } OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, - OHOS::NeuralNetworkRuntime::Buffer& cache) const + OHOS::NeuralNetworkRuntime::Buffer& cache) const { // filePath is validate in NNCompiledCache::Restore, no need to check twice. std::ifstream ifs(filePath.c_str(), std::ios::in | std::ios::binary); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index a224d1f..32d453a 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -320,6 +320,30 @@ OH_NN_ReturnCode NNCompiler::Build() return OH_NN_SUCCESS; } +void NNCompiler::ReleaseBuffer(std::vector& buffers) const +{ + // for (size_t i = 0; i < buffers.size(); ++i) { + // if (i == 0) { + // // release cache buffer which is allocated by idevice. + // m_device->ReleaseBuffer(buffers[i].data); + + // } else { + // // 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()) { @@ -348,6 +372,7 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = compiledCache.SetBackend(m_backendID); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, fail to set backend."); + ReleaseBuffer(caches); return ret; } @@ -355,6 +380,7 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = SerializeTensorsToBuffer(m_inputTensorDescs, inputTensorDescBuffer); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing input tensor desc."); + ReleaseBuffer(caches); return ret; } caches.emplace_back(inputTensorDescBuffer); @@ -363,6 +389,7 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = SerializeTensorsToBuffer(m_outputTensorDescs, outputTensorDescBuffer); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing output tensor desc."); + ReleaseBuffer(caches); return ret; } caches.emplace_back(outputTensorDescBuffer); @@ -370,9 +397,11 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = compiledCache.Save(caches, m_cachePath, m_cacheVersion); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, error happened when saving model cache."); + ReleaseBuffer(caches); return ret; } + ReleaseBuffer(caches); LOGI("[NNCompiler] Export model cache successfully."); return OH_NN_SUCCESS; } @@ -405,6 +434,7 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() 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; } @@ -412,12 +442,14 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() 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; } @@ -430,8 +462,10 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() 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; @@ -586,6 +620,14 @@ OH_NN_ReturnCode NNCompiler::SerializeTensorsToBuffer( 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) { @@ -598,6 +640,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( 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); @@ -605,6 +648,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( 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); @@ -612,6 +656,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( 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); @@ -619,18 +664,21 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( 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]; // todo 何时删除 + 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); @@ -648,6 +696,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( 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())); @@ -655,6 +704,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( LOGE("[NNCompiler] DeserializedTensorsFromBuffer failed, error happened when copying " "SerializedTensorDesc to TensorDesc."); tensorDescs.clear(); + ReleaseDescShape(immediateTensorDescs); return ret; } tensorDescPair.second = immediateTensorDesc.m_tensorType; @@ -662,6 +712,7 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( tensorDescs.emplace_back(tensorDescPair); } + ReleaseDescShape(immediateTensorDescs); return ret; } diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index 3e99f5b..c957c33 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -41,6 +41,8 @@ public: OH_NN_ReturnCode IsSupportModel(std::shared_ptr& liteGraph); 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; diff --git a/frameworks/native/nntensor.cpp b/frameworks/native/nntensor.cpp index e2b9d1b..dfbf242 100644 --- a/frameworks/native/nntensor.cpp +++ b/frameworks/native/nntensor.cpp @@ -29,10 +29,8 @@ NNTensor2_0::~NNTensor2_0() ReleaseMemory(); } - if (m_tensorDesc != nullptr) { - delete m_tensorDesc; - m_tensorDesc = nullptr; - } + delete m_tensorDesc; + m_tensorDesc = nullptr; m_data = nullptr; m_fd = 0; @@ -41,12 +39,30 @@ NNTensor2_0::~NNTensor2_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); @@ -74,6 +90,10 @@ OH_NN_ReturnCode NNTensor2_0::CreateData(size_t size) 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); @@ -106,6 +126,10 @@ OH_NN_ReturnCode NNTensor2_0::CreateData(int fd, size_t size, size_t offset) 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); diff --git a/frameworks/native/nntensor.h b/frameworks/native/nntensor.h index 4bcee48..24ba9fc 100644 --- a/frameworks/native/nntensor.h +++ b/frameworks/native/nntensor.h @@ -23,10 +23,10 @@ namespace OHOS { namespace NeuralNetworkRuntime { class NNTensor2_0 : public Tensor { public: - NNTensor2_0(size_t backendID, TensorDesc* tensorDesc) : - m_backendID(backendID), m_tensorDesc(tensorDesc) {} + 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; diff --git a/frameworks/native/tensor.h b/frameworks/native/tensor.h index bd4aa8f..0ab606f 100644 --- a/frameworks/native/tensor.h +++ b/frameworks/native/tensor.h @@ -24,9 +24,10 @@ namespace NeuralNetworkRuntime { class Tensor { public: Tensor() = default; - Tensor(size_t backendID, TensorDesc* tensorDesc); + 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; diff --git a/testdemo/demo.cpp b/testdemo/demo.cpp index ca39d5c..51c246e 100644 --- a/testdemo/demo.cpp +++ b/testdemo/demo.cpp @@ -298,6 +298,17 @@ int main(int argc, char** argv) { CHECKEQ(tensor, nullptr, -1, "OH_NNTensor_Create failed."); outputTensors[i] = tensor; } + + // 销毁输入输出tensordesc + for (size_t i = 0; i < inputCount; ++i) { + returnCode = OH_NNTensorDesc_Destroy(&inputTensorDescs[i]); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNTensorDesc_Destroy failed."); + } + for (size_t i = 0; i < outputCount; ++i) { + returnCode = OH_NNTensorDesc_Destroy(&outputTensorDescs[i]); + CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "OH_NNTensorDesc_Destroy failed."); + } + // 设置输入元素值 returnCode = SetInputData(inputTensors, inputCount); CHECKNEQ(returnCode, OH_NN_SUCCESS, -1, "SetInputData failed."); -- Gitee From 47da79dddcc67985500a6c1d813aa3b870e2a9b8 Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 10:06:36 +0800 Subject: [PATCH 41/51] bugfix, nncore import cache buffer --- frameworks/native/neural_network_core.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 78b2a92..76c2166 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -241,17 +241,10 @@ NNRT_API OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilatio } Compilation* compilationImpr = reinterpret_cast(compilation); - if (compilationImpr->compiler == nullptr) { - LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, should call OH_NNCompilation_Build before import cache."); - return OH_NN_INVALID_PARAMETER; - } - - OH_NN_ReturnCode ret = compilationImpr->compiler->RestoreFromCacheBuffer(buffer, modelSize); - if (ret != OH_NN_SUCCESS) { - LOGE("OH_NNCompilation_ImportCacheFromBuffer failed, fail to import cache from buffer."); - } + compilationImpr->offlineModelBuffer.first = const_cast(buffer); + compilationImpr->offlineModelBuffer.second = modelSize; - return ret; + return OH_NN_SUCCESS; } NNRT_API OH_NN_ReturnCode OH_NNCompilation_AddExtensionConfig(OH_NNCompilation *compilation, -- Gitee From 056f05034b5d8eff49c64c41be0027acd071db01 Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 11:08:14 +0800 Subject: [PATCH 42/51] update import cache buffer ret code --- frameworks/native/nncompiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 32d453a..7adc9d7 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -130,7 +130,7 @@ OH_NN_ReturnCode NNCompiler::SetCacheDir(const std::string& cacheModelPath, uint OH_NN_ReturnCode ret = m_device->IsModelCacheSupported(isSupportedCache); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SetCacheDir failed, fail to call device."); - return OH_NN_FAILED; + return ret; } if (!isSupportedCache && !cacheModelPath.empty()) { @@ -474,13 +474,13 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() 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_OPERATION_FORBIDDEN; + 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_OPERATION_FORBIDDEN; + return OH_NN_UNSUPPORTED; } OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& configs) -- Gitee From e80200f7a69c6e619b6cfe4067b5303ce3643dd6 Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 14:42:48 +0800 Subject: [PATCH 43/51] 1211-v2, update head file note info --- frameworks/native/backend_manager.cpp | 2 +- frameworks/native/hdi_device_v1_0.cpp | 24 +- frameworks/native/hdi_device_v2_0.cpp | 22 +- frameworks/native/hdi_prepared_model_v1_0.cpp | 4 +- frameworks/native/hdi_prepared_model_v2_0.cpp | 10 +- .../neural_network_core.h | 313 +++++++++++------- .../neural_network_runtime.h | 53 ++- .../neural_network_runtime_compat.h | 82 ++--- .../neural_network_runtime_type.h | 49 +-- .../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 +- .../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 +- 21 files changed, 361 insertions(+), 272 deletions(-) diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp index 7c7e2ac..b3dba2f 100644 --- a/frameworks/native/backend_manager.cpp +++ b/frameworks/native/backend_manager.cpp @@ -64,7 +64,7 @@ OH_NN_ReturnCode BackendManager::RegisterBackend(std::functionGetBackendID(); diff --git a/frameworks/native/hdi_device_v1_0.cpp b/frameworks/native/hdi_device_v1_0.cpp index c28c7ce..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); diff --git a/frameworks/native/hdi_device_v2_0.cpp b/frameworks/native/hdi_device_v2_0.cpp index a4bce4f..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; } diff --git a/frameworks/native/hdi_prepared_model_v1_0.cpp b/frameworks/native/hdi_prepared_model_v1_0.cpp index 49b34ed..e3211ce 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.cpp +++ b/frameworks/native/hdi_prepared_model_v1_0.cpp @@ -221,7 +221,7 @@ 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; @@ -263,7 +263,7 @@ 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; diff --git a/frameworks/native/hdi_prepared_model_v2_0.cpp b/frameworks/native/hdi_prepared_model_v2_0.cpp index 2bb441f..adca2bf 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.cpp +++ b/frameworks/native/hdi_prepared_model_v2_0.cpp @@ -220,11 +220,11 @@ 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_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; @@ -265,11 +265,11 @@ 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_UNAVALIDABLE_DEVICE; + return OH_NN_UNAVAILABLE_DEVICE; } return OH_NN_SUCCESS; @@ -280,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/interfaces/kits/c/neural_network_runtime/neural_network_core.h b/interfaces/kits/c/neural_network_runtime/neural_network_core.h index dcaa5f1..7ba73a2 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_core.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_core.h @@ -17,7 +17,7 @@ * @addtogroup NeuralNeworkRuntime * @{ * - * @brief Provides APIs of Neural Network Core for accelerating the model inference. + * @brief Provides APIs of Neural Network Runtime for accelerating the model inference. * * @since 11 * @version 1.0 @@ -51,7 +51,7 @@ extern "C" { * 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 + * 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: @@ -60,7 +60,7 @@ extern "C" { * - {@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 + * 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. @@ -74,6 +74,13 @@ OH_NNCompilation *OH_NNCompilation_Construct(const OH_NNModel *model); * * 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. @@ -85,8 +92,10 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelFile(const char *mod /** * @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, + * 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. @@ -99,6 +108,8 @@ OH_NNCompilation *OH_NNCompilation_ConstructWithOfflineModelBuffer(const void *m /** * @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 * @@ -131,6 +142,8 @@ OH_NN_ReturnCode OH_NNCompilation_ExportCacheToBuffer(OH_NNCompilation *compilat * @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. @@ -147,9 +160,12 @@ OH_NN_ReturnCode OH_NNCompilation_ImportCacheFromBuffer(OH_NNCompilation *compil /** * @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 to set these - * custom hardware attributes for the device you chose, if you have queried their names and values from the device vendor documents. - * These attributes will be passed directly to device driver, and this method will return error code if the driver cannot parse them. \n + * 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. @@ -184,9 +200,9 @@ OH_NN_ReturnCode OH_NNCompilation_SetDevice(OH_NNCompilation *compilation, size_ /** * @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. + * 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 + * 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 @@ -220,14 +236,14 @@ OH_NN_ReturnCode OH_NNCompilation_SetCache(OH_NNCompilation *compilation, const /** * @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 + * 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}. + * @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 @@ -240,7 +256,7 @@ OH_NN_ReturnCode OH_NNCompilation_SetPerformanceMode(OH_NNCompilation *compilati * @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 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 @@ -276,7 +292,8 @@ OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compilation, b * @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. + * 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 * @@ -291,9 +308,10 @@ 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 + * 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 logic. \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. @@ -304,15 +322,17 @@ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); /** - * @brief Creates an instance of the {@link NN_TensorDesc} type. + * @brief Creates an {@link NN_TensorDesc} instance. * - * This method creates an instance of the {@link NN_TensorDesc} type to describe various tensor information, - * including name/data type/shape/format, etc. \n + * 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 tensor instance based on the passed {@link NN_TensorDesc} instance: + * 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 @@ -321,14 +341,12 @@ void OH_NNCompilation_Destroy(OH_NNCompilation **compilation); NN_TensorDesc *OH_NNTensorDesc_Create(); /** - * @brief Releases an instance of the {@link NN_TensorDesc} type. + * @brief Releases an {@link NN_TensorDesc} instance. * - * After the {@link NN_TensorDesc} instance is created, this method needs to be called to release the instance. - * After creating a tensor and passing the {@link NN_TensorDesc} instance to the tensor, - * the {@link NN_TensorDesc} memory will be released at the same time as the {@link OH_NNTensor_Destroy} call, - * and you do not need to call this method to release the {@link NN_TensorDesc} memory. Otherwise, memory leak will occur. \n + * 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 logic. \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. @@ -339,9 +357,10 @@ NN_TensorDesc *OH_NNTensorDesc_Create(); OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); /** - * @brief Sets the name of a 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. \n + * 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 * @@ -355,12 +374,16 @@ OH_NN_ReturnCode OH_NNTensorDesc_Destroy(NN_TensorDesc **tensorDesc); OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char *name); /** - * @brief Gets the name of a tensorDesc. + * @brief Gets the name of a {@link NN_TensorDesc}. * - * Call this method to obtain the name of the specified {@link NN_TensorDesc} instance. \n + * 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 * - * 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. \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. @@ -372,7 +395,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetName(NN_TensorDesc *tensorDesc, const char * OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const char **name); /** - * @brief Sets the data type of a tensorDesc. + * @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 * @@ -388,7 +411,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetName(const NN_TensorDesc *tensorDesc, const OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_DataType dataType); /** - * @brief Gets the data type of a tensorDesc. + * @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 * @@ -404,7 +427,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetDataType(NN_TensorDesc *tensorDesc, OH_NN_Da OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH_NN_DataType *dataType); /** - * @brief Sets the shape of a tensorDesc. + * @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 * @@ -421,12 +444,15 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetDataType(const NN_TensorDesc *tensorDesc, OH OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32_t *shape, size_t shapeLength); /** - * @brief Gets the shape of a tensorDesc. + * @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. \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. @@ -439,7 +465,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetShape(NN_TensorDesc *tensorDesc, const int32 OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32_t **shape, size_t *shapeLength); /** - * @brief Sets the format of a tensorDesc. + * @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 * @@ -455,7 +481,7 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetShape(const NN_TensorDesc *tensorDesc, int32 OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Format format); /** - * @brief Gets the format of a tensorDesc. + * @brief Gets the format of a {@link NN_TensorDesc}. * * Call this method to obtain the format of the specified {@link NN_TensorDesc} instance. \n * @@ -471,10 +497,12 @@ OH_NN_ReturnCode OH_NNTensorDesc_SetFormat(NN_TensorDesc *tensorDesc, OH_NN_Form OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_NN_Format *format); /** - * @brief Gets the element count of a tensorDesc. + * @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, you can call the {@link OH_NNTensorDesc_GetByteSize} method to obtain it. \n + * 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 * @@ -488,10 +516,13 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetFormat(const NN_TensorDesc *tensorDesc, OH_N OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc, size_t *elementCount); /** - * @brief Gets the byte size of a tensorDesc. + * @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. - * If you need to obtain element number of the tensor data, you can call the {@link OH_NNTensorDesc_GetElementNum} method to obtain it. \n + * 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 * @@ -505,15 +536,23 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetElementCount(const NN_TensorDesc *tensorDesc OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, size_t *byteSize); /** - * @brief Creates an instance of the {@link NN_Tensor} type. + * @brief Creates a {@link NN_Tensor} instance from {@link NN_TensorDesc}. * - * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is calculated by {@link OH_NNTensorDesc_GetByteSize} is allocated. - * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * tensorDesc must be provided, if it is a null pointer, the method returns an error code. \n + * 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 created by this method. tensorDesc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @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 @@ -522,15 +561,23 @@ OH_NN_ReturnCode OH_NNTensorDesc_GetByteSize(const NN_TensorDesc *tensorDesc, si NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); /** - * @brief Creates an instance of the {@link NN_Tensor} type. + * @brief Creates a {@link NN_Tensor} instance with specified size. * - * This method creates an instance of the {@link NN_Tensor} type. Tensor data whose length is specified by size is allocated. - * deviceName indicates the selected backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * tensorDesc must be provided, if it is a null pointer, the method returns an error code. \n + * 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 created by this method. tensorDesc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @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. @@ -540,23 +587,28 @@ NN_Tensor* OH_NNTensor_Create(size_t deviceID, NN_TensorDesc *tensorDesc); NN_Tensor* OH_NNTensor_CreateWithSize(size_t deviceID, NN_TensorDesc *tensorDesc, size_t size); /** - * @brief Creates an instance of the {@link NN_Tensor} type. + * @brief Creates a {@link NN_Tensor} instance with specified fd. * - * This method creates an instance of the {@link NN_Tensor} type. This method reuses the memory corresponding to the fd passed by the user. - * When you call the {@link OH_NNTensor_DestroyTensor} method to release the tensor created by this method, the data memory is not released. \n + * 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 backend, which can be a null pointer. If it is a null pointer, the 0th backend is used by default. - * tensorDesc must be provided, if it is a null pointer, the method returns an error code. - * fd, size and offset come from another {@link NN_Tensor} instance. (size - offset) must be greater than or - * equal to the byte size obtained by the {@link OH_NNTensorDesc_GetByteSize} in tensorDesc. \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 created by this method. tensorDesc will also be released. \n + * Call {@link OH_NNTensor_DestroyTensor} to release the {@link NN_Tensor} instance. \n * - * @param deviceName The name of the backend which can be a null pointer, if it is a null pointer, the 0th backend in the current backend list is used by default. + * @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 comes from another {@link NN_Tensor} instance. - * @param size Size comes from another {@link NN_Tensor} instance. - * @param offset Offset comes from another {@link NN_Tensor} 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 @@ -568,13 +620,12 @@ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, size_t offset); /** - * @brief Releases an instance of the {@link NN_Tensor} type. + * @brief Releases a {@link NN_Tensor} instance. * - * After the {@link NN_Tensor} instance is created, this method needs to be called to release the instance. Otherwise, memory leak will occur. - * The {@link NN_TensorDesc} memory will be released at the same time as the {@link OH_NNTensor_DestroyTensor} call, - * and you do not need to call {@link OH_NNTensorDesc_Destroy} to release the {@link NN_TensorDesc} memory. \n + * 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 logic. \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. @@ -585,10 +636,13 @@ NN_Tensor* OH_NNTensor_CreateWithFd(size_t deviceID, OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor); /** - * @brief Gets the {@link NN_TensorDesc} instance of a tensor. + * @brief Gets the {@link NN_TensorDesc} instance of a {@link NN_Tensor}. * - * Call this method to obtain the {@link NN_TensorDesc} instance of the specified {@link NN_Tensor} instance. - * You can get various types of the tensor information such as name/format/data type/shape from the {@link NN_TensorDesc} instance. \n + * 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 * @@ -600,9 +654,12 @@ OH_NN_ReturnCode OH_NNTensor_Destroy(NN_Tensor **tensor); NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor); /** - * @brief Gets the data buffer of a tensor. + * @brief Gets the data buffer of a {@link NN_Tensor}. * - * Call this method to obtain the data buffer of the specified {@link NN_Tensor} instance. \n + * 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 * @@ -614,9 +671,12 @@ NN_TensorDesc* OH_NNTensor_GetTensorDesc(const NN_Tensor *tensor); void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); /** - * @brief Gets the data size of a tensor. + * @brief Gets the data size of a {@link NN_Tensor}. * - * Call this method to obtain the data size of the specified {@link NN_Tensor} instance. \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 + * + * 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 * @@ -630,15 +690,16 @@ void* OH_NNTensor_GetDataBuffer(const NN_Tensor *tensor); OH_NN_ReturnCode OH_NNTensor_GetSize(const NN_Tensor *tensor, size_t *size); /** - * @brief Gets the data fd of a tensor. + * @brief Gets the data fd of a {@link NN_Tensor}. * - * Call this method to obtain the data fd of the specified {@link NN_Tensor} instance. \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 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. + * @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 @@ -648,13 +709,16 @@ OH_NN_ReturnCode OH_NNTensor_GetFd(const NN_Tensor *tensor, int *fd); /** * @brief Get the data offset of a tensor. * - * Call this method to obtain the data offset of the specified {@link NN_Tensor} instance. \n + * 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. + * @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 @@ -664,11 +728,9 @@ 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. 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 + * This method constructs a model inference executor associated with the device based on the passed compiler. \n * - * After calling this method to create the {@link OH_NNExecutor} instance, you can release the {@link OH_NNCompilation} + * 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. @@ -683,7 +745,12 @@ OH_NNExecutor *OH_NNExecutor_Construct(OH_NNCompilation *compilation); * * 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. @@ -705,10 +772,10 @@ OH_NN_ReturnCode OH_NNExecutor_GetOutputShape(OH_NNExecutor *executor, /** * @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 + * 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 logic. \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 @@ -749,7 +816,7 @@ OH_NN_ReturnCode OH_NNExecutor_GetOutputCount(const OH_NNExecutor *executor, siz /** * @brief Creates an input tensor descriptor with its index. * - * The input tensor descriptor contains all attributes of the input tensor. + * 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. @@ -763,7 +830,7 @@ NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor /** * @brief Creates an output tensor descriptor with its index. * - * The output tensor descriptor contains all attributes of the output tensor. + * 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. @@ -775,13 +842,20 @@ NN_TensorDesc* OH_NNExecutor_CreateInputTensorDesc(const OH_NNExecutor *executor NN_TensorDesc* OH_NNExecutor_CreateOutputTensorDesc(const OH_NNExecutor *executor, size_t index); /** - * @brief Gets the dimension range of an input tensor. + * @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 contains the minimum demensions of the input tensor, and maxInputDims contains the maximum, - * e.g. minInputDims is [1, 10, 10, 3] and maxInputDims is [100, 1024, 1024, 3] with dynamic shape [-1, -1, -1, 3] - * of the input tensor. If the index exceeds the outputCount - 1, this method will return error code. \n + * *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. @@ -832,7 +906,8 @@ OH_NN_ReturnCode OH_NNExecutor_SetOnServiceDied(OH_NNExecutor *executor, NN_OnSe * * 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. + * 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 @@ -858,21 +933,25 @@ OH_NN_ReturnCode OH_NNExecutor_RunSync(OH_NNExecutor *executor, * * 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. + * 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}. \n - * The "userData" 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. + * 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. 1000ms. + * @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}. @@ -887,13 +966,13 @@ OH_NN_ReturnCode OH_NNExecutor_RunAsync(OH_NNExecutor *executor, int32_t timeout, void* userData); - /** * @brief Obtains the IDs of all devices connected. * - * Each device has a unique and fixed ID. This method returns device IDs on the current device through the uint32_t array. \n + * 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. + * 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 * @@ -910,11 +989,15 @@ OH_NN_ReturnCode OH_NNDevice_GetAllDevicesID(const size_t **allDevicesID, uint32 * @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 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, + * @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 @@ -931,8 +1014,8 @@ OH_NN_ReturnCode OH_NNDevice_GetName(size_t deviceID, const char **name); * - 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, + * @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 diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h index 7e75f14..041a416 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime.h @@ -63,7 +63,7 @@ NN_QuantParam *OH_NNQuantParam_Create(); /** * @brief Sets the scales of the quantization parameter instance. * - * The parameter "quantCount" is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * 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. @@ -79,7 +79,7 @@ OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam *quantParams, const dou /** * @brief Sets the zero points of the quantization parameter instance. * - * The parameter "quantCount" is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * 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. @@ -95,7 +95,7 @@ OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam *quantParams, const /** * @brief Sets the number bits of the quantization parameter instance. * - * The parameter "quantCount" is the number of quantization parameters of a tensor, e.g. the quantCount is the channel + * 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. @@ -111,7 +111,7 @@ OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam *quantParams, const ui /** * @brief Releases a quantization parameter instance. * - * The NN_QuantParam instance needs to be released to avoid memory leak after it is set to a NN_TensorDesc. + * 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 * @@ -128,10 +128,10 @@ OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam **quantParams); * * 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. + * 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 + * 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 @@ -143,13 +143,13 @@ 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}. + * 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 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 + * 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. + * 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. @@ -164,12 +164,12 @@ OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel *model, const NN_TensorD /** * @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 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 value of a tensor. + * @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. @@ -183,7 +183,7 @@ OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model, uint32_t index, con * @brief Sets the quantization parameter of a tensor. * * @param model Pointer to the {@link OH_NNModel} instance. - * @param index Index value of a tensor. + * @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}. @@ -196,7 +196,7 @@ OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel *model, uint32_t ind * @brief Sets the tensor type. See {@link OH_NN_TensorType} for details. * * @param model Pointer to the {@link OH_NNModel} instance. - * @param index Index value of a tensor. + * @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}. @@ -209,16 +209,16 @@ OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel *model, uint32_t index, OH_ * @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. + * 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. + * 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. + * 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 for adding an operator, this method returns {@link OH_NN_INVALID_PARAMETER}. + * 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 * @@ -242,9 +242,9 @@ OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model, * @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 + * using {@link OH_NNModel_SetTensorData}. \n * - * The index value of a tensor is determined by the sequence in which the tensor is added to the model. + * 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 @@ -264,7 +264,7 @@ OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model, /** * @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, + * 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 @@ -285,7 +285,7 @@ OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model); * * 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 + * 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 @@ -306,9 +306,8 @@ void OH_NNModel_Destroy(OH_NNModel **model); * * @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 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}. diff --git a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h index d241421..44f302e 100644 --- a/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h +++ b/interfaces/kits/c/neural_network_runtime/neural_network_runtime_compat.h @@ -27,7 +27,7 @@ /** * @file neural_network_runtime_compat.h * - * @brief The APIs defined in this document are all compatible APIs of the previous version, which will be deprecated after five versions. + * @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 * @@ -49,16 +49,16 @@ extern "C" { * @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 @@ -72,29 +72,29 @@ OH_NN_ReturnCode OH_NNModel_AddTensor(OH_NNModel *model, const OH_NN_Tensor *ten * @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} @@ -110,25 +110,25 @@ 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} @@ -146,7 +146,7 @@ OH_NN_ReturnCode OH_NNExecutor_SetOutput(OH_NNExecutor *executor, * 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} @@ -158,13 +158,13 @@ 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. @@ -178,13 +178,13 @@ 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. @@ -199,14 +199,14 @@ 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 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 @@ -219,14 +219,14 @@ 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 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 @@ -239,13 +239,13 @@ 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}. @@ -264,16 +264,16 @@ 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} 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 02cc266..03c9fe9 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 @@ -129,7 +129,7 @@ typedef enum { } OH_NN_Priority; /** - * @brief Defines error codes for Neural Network Runtime. + * @brief Defines error codes. * * @since 9 * @version 2.0 @@ -149,44 +149,51 @@ 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, - /** Timeout. + /** A hardware error occurs, for example, HDL service crash. + * @since 11 + */ + OH_NN_UNAVAILABLE_DEVICE = 9, + /** Timeout. * @since 11 */ - OH_NN_TIMEOUT = 9, - /** Unsupported. + OH_NN_TIMEOUT = 10, + /** Unsupported. * @since 11 */ - OH_NN_UNSUPPORTED = 10, + OH_NN_UNSUPPORTED = 11, /** Connection Exception. * @since 11 */ - OH_NN_CONNECTION_EXECEPTION = 11, + OH_NN_CONNECTION_EXCEPTION = 12, /** Save cache exception. * @since 11 */ - OH_NN_SAVE_CACHE_EXCEPTION = 12, + OH_NN_SAVE_CACHE_EXCEPTION = 13, /** Dynamic shape. * @since 11 */ - OH_NN_DYNAMIC_SHAPE = 13 + 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 to identify the asynchronous execution you want to get. - * It is the argument "userData" passed to {@link OH_NNExecutor_RunAsync}. \n - * Use the second argument of type {@link OH_NN_ReturnCode} to get the error code returned by the asynchronous execution. \n + * 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" passed to {@link OH_NNExecutor_RunAsync}. + * @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" passed to {@link OH_NNExecutor_RunAsync} - * @param outputCount Output tensor count, which are same as argument "outputCount" passed to {@link OH_NNExecutor_RunAsync} + * @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 */ @@ -197,14 +204,14 @@ typedef void (*NN_OnRunDone)(void*, OH_NN_ReturnCode, void* [], int32_t); * * You should recompile the model if this callback function is called. \n * - * @param userData Asynchronous execution identifier, which is the argument "userData" passed to {@link OH_NNExecutor_RunAsync}. + * @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 @@ -238,7 +245,7 @@ typedef enum { } OH_NN_Format; /** - * @brief Defines device types supported by Neural Network Runtime. + * @brief Defines device types. * * @since 9 * @version 1.0 @@ -255,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 @@ -291,7 +298,7 @@ typedef enum { /** - * @brief Defines operator types supported by Neural Network Runtime. + * @brief Defines operator types. * * @since 9 * @version 1.0 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/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); } /* -- Gitee From 5dd86f8558c1655a36d68c128e4ff8cb3599b88f Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 16:28:28 +0800 Subject: [PATCH 44/51] 1211-v2, bugfix --- frameworks/native/backend_manager.cpp | 1 + frameworks/native/neural_network_core.cpp | 41 ++++++++++++++--------- frameworks/native/nncompiled_cache.cpp | 2 +- frameworks/native/nncompiler.cpp | 18 +++++++--- frameworks/native/nncompiler.h | 3 +- 5 files changed, 43 insertions(+), 22 deletions(-) diff --git a/frameworks/native/backend_manager.cpp b/frameworks/native/backend_manager.cpp index b3dba2f..64a29d9 100644 --- a/frameworks/native/backend_manager.cpp +++ b/frameworks/native/backend_manager.cpp @@ -10,6 +10,7 @@ BackendManager::~BackendManager() { m_backends.clear(); m_backendIDs.clear(); + m_tmpBackendIds.clear(); } const std::vector& BackendManager::GetAllBackendsID() diff --git a/frameworks/native/neural_network_core.cpp b/frameworks/native/neural_network_core.cpp index 76c2166..9300d4c 100644 --- a/frameworks/native/neural_network_core.cpp +++ b/frameworks/native/neural_network_core.cpp @@ -372,27 +372,32 @@ NNRT_API OH_NN_ReturnCode OH_NNCompilation_EnableFloat16(OH_NNCompilation *compi return OH_NN_SUCCESS; } -Compiler* CreateCompiler(Compilation* compilation) +OH_NN_ReturnCode CreateCompiler(Compilation* compilation, Compiler** compiler) { if (compilation == nullptr) { LOGE("CreateCompiler failed, compilation is nullptr."); - return 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 nullptr; + return OH_NN_FAILED; } - Compiler* nnCompiler = backend->CreateCompiler(compilation); - if (nnCompiler == nullptr) { + *compiler = backend->CreateCompiler(compilation); + if (*compiler == nullptr) { LOGE("CreateCompiler failed, fail to create compiler."); - return nullptr; + return OH_NN_FAILED; } - return nnCompiler; + return OH_NN_SUCCESS; } OH_NN_ReturnCode SetCompilationOptions(Compilation* compilation) @@ -469,16 +474,22 @@ NNRT_API OH_NN_ReturnCode OH_NNCompilation_Build(OH_NNCompilation *compilation) return OH_NN_INVALID_PARAMETER; } - if (compilationImpr->compiler == nullptr) { - Compiler* nnCompiler = CreateCompiler(compilationImpr); - if (nnCompiler == nullptr) { - LOGE("OH_NNCompilation_Build failed, faile to create compiler."); - return OH_NN_FAILED; - } - compilationImpr->compiler = nnCompiler; + 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; - OH_NN_ReturnCode ret = SetCompilationOptions(compilationImpr); + ret = SetCompilationOptions(compilationImpr); if (ret != OH_NN_SUCCESS) { LOGE("OH_NNCompilation_Build failed, faile to create compiler."); return ret; diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 2e2c27b..f1180a2 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -258,7 +258,7 @@ OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, } OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo, - const std::string& cacheInfoPath) const + const std::string& cacheInfoPath) const { // cacheInfoPath is validated outside. std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary); diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 7adc9d7..0b8f8fb 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -112,6 +112,7 @@ NNCompiler::~NNCompiler() } m_inputTensorDescs.clear(); m_outputTensorDescs.clear(); + m_model = nullptr; } size_t NNCompiler::GetBackendID() const @@ -228,7 +229,8 @@ bool NNCompiler::IsBuild() const return m_isBuild; } -OH_NN_ReturnCode NNCompiler::IsSupportModel(std::shared_ptr& liteGraph) +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); @@ -241,10 +243,12 @@ OH_NN_ReturnCode NNCompiler::IsSupportModel(std::shared_ptr(m_performance), @@ -453,7 +462,6 @@ OH_NN_ReturnCode NNCompiler::RestoreFromCacheFile() return ret; } - // TODO: Add NNOption check here. ModelConfig config; config.enableFloat16 = m_enableFp16; config.mode = m_performance; @@ -491,7 +499,7 @@ OH_NN_ReturnCode NNCompiler::SetExtensionConfig(const std::unordered_map>& options) { - LOGE("[NNCompiler] Not support to set extented options for NN compiler."); + LOGE("[NNCompiler] SetOptions is not supported for NN compiler currently."); return OH_NN_UNSUPPORTED; } diff --git a/frameworks/native/nncompiler.h b/frameworks/native/nncompiler.h index c957c33..8d35056 100644 --- a/frameworks/native/nncompiler.h +++ b/frameworks/native/nncompiler.h @@ -38,7 +38,8 @@ public: OH_NN_ReturnCode SetOptions(const std::vector>& options) override; NNExecutor* CreateExecutor(); - OH_NN_ReturnCode IsSupportModel(std::shared_ptr& liteGraph); + OH_NN_ReturnCode IsSupporttedModel(const std::shared_ptr& liteGraph, + bool& isSupporttedModel) const; private: void ReleaseBuffer(std::vector& buffers) const; -- Gitee From e5b3d85fcfb83cb73c169af73e599cd5b041dd47 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 11 Dec 2023 17:22:09 +0800 Subject: [PATCH 45/51] mem bugfix --- frameworks/native/nncompiler.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/frameworks/native/nncompiler.cpp b/frameworks/native/nncompiler.cpp index 0b8f8fb..275843d 100644 --- a/frameworks/native/nncompiler.cpp +++ b/frameworks/native/nncompiler.cpp @@ -331,17 +331,11 @@ OH_NN_ReturnCode NNCompiler::Build() void NNCompiler::ReleaseBuffer(std::vector& buffers) const { - // for (size_t i = 0; i < buffers.size(); ++i) { - // if (i == 0) { - // // release cache buffer which is allocated by idevice. - // m_device->ReleaseBuffer(buffers[i].data); - - // } else { - // // release tensor buffer which is allocated by new method. - // delete[] (char*)buffers[i].data; - // } - // } - // buffers.clear(); + 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 @@ -371,6 +365,7 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const } 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."); @@ -381,7 +376,6 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = compiledCache.SetBackend(m_backendID); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, fail to set backend."); - ReleaseBuffer(caches); return ret; } @@ -389,28 +383,29 @@ OH_NN_ReturnCode NNCompiler::SaveToCacheFile() const ret = SerializeTensorsToBuffer(m_inputTensorDescs, inputTensorDescBuffer); if (ret != OH_NN_SUCCESS) { LOGE("[NNCompiler] SaveToCacheFile failed, error happened when serializing input tensor desc."); - ReleaseBuffer(caches); 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(caches); + 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(caches); + ReleaseBuffer(tensorBuffers); return ret; } - ReleaseBuffer(caches); + ReleaseBuffer(tensorBuffers); LOGI("[NNCompiler] Export model cache successfully."); return OH_NN_SUCCESS; } -- Gitee From cb68bc77db19ef72b5913e74a7de6b5baf98bec5 Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 17:22:23 +0800 Subject: [PATCH 46/51] 1211-v2, update compiled_cache --- frameworks/native/nncompiled_cache.cpp | 48 ++++++-------------------- frameworks/native/nncompiled_cache.h | 23 ++++++------ 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index f1180a2..c94d444 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -54,8 +54,8 @@ static const unsigned short CRC16_TAB[256] = { 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; OH_NN_ReturnCode NNCompiledCache::Save(const std::vector& caches, - const std::string& cacheDir, - uint32_t version) + const std::string& cacheDir, + uint32_t version) { if (caches.empty()) { LOGE("[NNCompiledCache] Save failed, caches is empty."); @@ -174,8 +174,8 @@ void NNCompiledCache::SetModelName(const std::string& modelName) } OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, - const std::string& cacheDir, - uint32_t version) const + const std::string& cacheDir, + uint32_t version) const { const size_t cacheNumber = caches.size(); uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber; @@ -202,9 +202,9 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector& caches, - std::unique_ptr& cacheInfo, - const std::string& cacheDir, - uint32_t version) const + std::unique_ptr& cacheInfo, + const std::string& cacheDir, + uint32_t version) const { size_t cacheNumber = caches.size(); @@ -237,8 +237,8 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector& cacheInfo, - const std::string& cacheDir) const + 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); @@ -306,7 +306,7 @@ OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCache OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath, OHOS::NeuralNetworkRuntime::Buffer& cache) const { - // filePath is validate in NNCompiledCache::Restore, no need to check twice. + // 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."); @@ -350,34 +350,6 @@ OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNCompiledCache::RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const -{ - std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache"; - if (remove(cacheInfoPath.c_str()) == -1) { - LOGE("[NNCompiledCache] RemoveCacheFiles failed to remove the file %s, please delete the file manually.", - cacheInfoPath.c_str()); - return OH_NN_FAILED; - } - LOGI("[NNCompiledCache] RemoveCacheFiles succeed to remove %s.", cacheInfoPath.c_str()); - - for (uint32_t i = 0; i < fileNumber; ++i) { - std::string fileName = m_modelName + std::to_string(i) + ".nncache"; - std::string cacheModelPath = cacheDir + fileName; - if (access(cacheModelPath.c_str(), 0) != 0) { - LOGW("The file %s does not exist, no need to delete the file.", cacheModelPath.c_str()); - continue; - } - - if (remove(cacheModelPath.c_str()) == -1) { - LOGE("[NNCompiledCache] RemoveCacheFiles failed to remove the file %s, please delete the file manually.", - cacheModelPath.c_str()); - return OH_NN_FAILED; - } - LOGI("[NNCompiledCache] RemoveCacheFiles succeed to remove the file %s", cacheModelPath.c_str()); - } - return OH_NN_SUCCESS; -} - unsigned short NNCompiledCache::GetCrc16(const unsigned char* buffer, size_t length) const { unsigned short crc16 = 0; diff --git a/frameworks/native/nncompiled_cache.h b/frameworks/native/nncompiled_cache.h index 842c313..2664cac 100644 --- a/frameworks/native/nncompiled_cache.h +++ b/frameworks/native/nncompiled_cache.h @@ -41,29 +41,28 @@ public: ~NNCompiledCache() = default; OH_NN_ReturnCode Save(const std::vector& caches, - const std::string& cacheDir, - uint32_t version); + const std::string& cacheDir, + uint32_t version); OH_NN_ReturnCode Restore(const std::string& cacheDir, - uint32_t version, - std::vector& caches); + 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; + 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; + 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; + 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; - OH_NN_ReturnCode RemoveCacheFiles(const std::string& cacheDir, uint32_t fileNumber) const; unsigned short GetCrc16(const unsigned char* buffer, size_t length) const; OH_NN_ReturnCode GetCacheFileLength(std::ifstream& ifs, int& fileSize) const; -- Gitee From 1b8484872c26ebc1c868e644217f809ca9105f73 Mon Sep 17 00:00:00 2001 From: maoyong Date: Mon, 11 Dec 2023 17:42:07 +0800 Subject: [PATCH 47/51] 1211-v2, update log info --- frameworks/native/nncompiled_cache.cpp | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index c94d444..0572418 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -118,7 +118,8 @@ OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir, } if ((uint64_t)version < cacheInfo.version) { - LOGE("[NNCompiledCache] The current version is lower than the cache files, please set a higher version."); + LOGE("[NNCompiledCache] Restore failed, the current version is lower than the cache files, " + "please set a higher version."); return OH_NN_OPERATION_FORBIDDEN; } @@ -138,7 +139,8 @@ 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.", cacheModelPath.c_str()); + LOGE("[NNCompiledCache] Restore failed, the cache model file %s has been changed.", + cacheModelPath.c_str()); return OH_NN_INVALID_FILE; } @@ -181,7 +183,7 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector cacheInfo = std::make_unique(cacheSize); if (cacheInfo == nullptr) { - LOGE("Fail to create cacheInfo instance."); + LOGE("[NNCompiledCache] GenerateCacheFiles failed, fail to create cacheInfo instance."); return OH_NN_MEMORY_ERROR; } @@ -217,7 +219,7 @@ OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector(GetCrc16(static_cast(caches[i].data), caches[i].length)); *cacheInfoPtr++ = checkSum; if (!cacheModelStream.write(static_cast(caches[i].data), caches[i].length)) { - LOGE("[NNCompiledCache] Fail to write cache model."); + LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to write cache model."); cacheModelStream.close(); return OH_NN_SAVE_CACHE_EXCEPTION; }; @@ -243,12 +245,12 @@ OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize, 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] Model cache info file is invalid."); + 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] Fail to write cache info."); + LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to write cache info."); cacheInfoStream.close(); return OH_NN_SAVE_CACHE_EXCEPTION; } @@ -317,7 +319,7 @@ OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath OH_NN_ReturnCode ret = GetCacheFileLength(ifs, fsize); if (ret != OH_NN_SUCCESS) { ifs.close(); - LOGE("Get file %{public}s length fialed.", filePath.c_str()); + LOGE("[NNCompiledCache] ReadCacheModelFile failed, get file %{public}s length fialed.", filePath.c_str()); return ret; } @@ -364,20 +366,20 @@ OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(std::ifstream& ifs, int& fi { ifs.seekg(0, std::ios::end); if (!ifs.good()) { - LOGE("[NNCompiledCache] GetCacheFileLength fail to set the position of the next character to be extracted from " - "the input stream."); + 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("Compiled::GetCacheFileLength fail to get position of the input stream."); + 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", + LOGE("[NNCompiledCache] GetCacheFileLength failed, unable to read huge or empty input stream, " + "get cache file size=%{public}d", handleValue); return OH_NN_INVALID_FILE; } -- Gitee From 7caac3470e3c83e240430b793e04ac6f78e289f0 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 11 Dec 2023 19:42:57 +0800 Subject: [PATCH 48/51] add dlopen nnrt_ext --- frameworks/native/neural_network_runtime.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp index 06713b9..b34fce5 100644 --- a/frameworks/native/neural_network_runtime.cpp +++ b/frameworks/native/neural_network_runtime.cpp @@ -23,6 +23,11 @@ #include "quant_param.h" #include "validation.h" +#include + +namespace { +void* g_libHandle = dlopen("libneural_network_runtime_ext.so", RTLD_NOW | RTLD_GLOBAL); +} using namespace OHOS::NeuralNetworkRuntime; -- Gitee From 4901e9feae1f10bd412ed6bf9840afc9efbd6e5e Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 11 Dec 2023 20:42:54 +0800 Subject: [PATCH 49/51] bugfix --- frameworks/native/nncompiled_cache.cpp | 2 +- frameworks/native/nnexecutor.cpp | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 0572418..724bcaa 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -111,7 +111,7 @@ 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 %u, but the cache files " - "version is %llu.", + "version is %lu.", version, cacheInfo.version); return OH_NN_INVALID_PARAMETER; diff --git a/frameworks/native/nnexecutor.cpp b/frameworks/native/nnexecutor.cpp index 6942e51..6bd9671 100644 --- a/frameworks/native/nnexecutor.cpp +++ b/frameworks/native/nnexecutor.cpp @@ -78,8 +78,8 @@ OH_NN_ReturnCode NNExecutor::GetInputDimRange( return OH_NN_INVALID_PARAMETER; } *shapeNum = minInputDimVec.size(); - *minInputDims = static_cast(minInputDimVec.data()); - *maxInputDims = static_cast(maxInputDimVec.data()); + *minInputDims = reinterpret_cast(minInputDimVec.data()); + *maxInputDims = reinterpret_cast(maxInputDimVec.data()); return OH_NN_SUCCESS; } @@ -95,11 +95,13 @@ OH_NN_ReturnCode NNExecutor::GetOutputShape(uint32_t outputIndex, int32_t** shap } auto tensorDesc = m_outputTensorDescs[outputIndex].first; - auto ret = tensorDesc->GetShape(shape, shapeNum); + 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; } @@ -121,7 +123,7 @@ NN_TensorDesc* NNExecutor::CreateInputTensorDesc(size_t index) const return nullptr; } if (m_inputTensorDescs[index].first == nullptr) { - LOGE("NNExecutor::CreateInputTensorDesc failed, tensor desc of input %{public}u is nullptr.", index); + LOGE("NNExecutor::CreateInputTensorDesc failed, tensor desc of input %{public}zu is nullptr.", index); return nullptr; } @@ -144,7 +146,7 @@ NN_TensorDesc* NNExecutor::CreateOutputTensorDesc(size_t index) const return nullptr; } if (m_outputTensorDescs[index].first == nullptr) { - LOGE("NNExecutor::CreateOutputTensorDesc failed, tensor desc of output %{public}u is nullptr.", index); + LOGE("NNExecutor::CreateOutputTensorDesc failed, tensor desc of output %{public}zu is nullptr.", index); return nullptr; } -- Gitee From 26b61ed7153222b79b299a173278e96b37700130 Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Mon, 11 Dec 2023 20:46:39 +0800 Subject: [PATCH 50/51] bugfix --- frameworks/native/nncompiled_cache.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/native/nncompiled_cache.cpp b/frameworks/native/nncompiled_cache.cpp index 724bcaa..75c2ce6 100644 --- a/frameworks/native/nncompiled_cache.cpp +++ b/frameworks/native/nncompiled_cache.cpp @@ -110,10 +110,10 @@ 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 %u, but the cache files " - "version is %lu.", + LOGE("[NNCompiledCache] Restore failed, version is not match. The current version is %{public}u, but the cache files " + "version is %{public}zu.", version, - cacheInfo.version); + (size_t)cacheInfo.version); return OH_NN_INVALID_PARAMETER; } -- Gitee From 881b79961fc95e0964bd378d2ca744a13480a87f Mon Sep 17 00:00:00 2001 From: wangchuanxia Date: Tue, 12 Dec 2023 11:21:57 +0800 Subject: [PATCH 51/51] bugfix Signed-off-by: wangchuanxia --- frameworks/BUILD.gn | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frameworks/BUILD.gn b/frameworks/BUILD.gn index bf71913..90d5d4c 100644 --- a/frameworks/BUILD.gn +++ b/frameworks/BUILD.gn @@ -22,13 +22,6 @@ 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", -- Gitee