diff --git a/frameworks/native/compilation.cpp b/frameworks/native/compilation.cpp index 1d54550dacf65dddbb4f39576f966b2daba25de7..eb8b2a3756c3abafca892e649f296a37acaa5bc5 100644 --- a/frameworks/native/compilation.cpp +++ b/frameworks/native/compilation.cpp @@ -74,7 +74,10 @@ static const unsigned short CRC16_TAB[256] = { Compilation::Compilation(const InnerModel* innerModel) : m_liteGraph(innerModel->GetLiteGraphs()), m_inputTensors(innerModel->GetInputTensors()), - m_outputTensors(innerModel->GetOutputTensors()) {} + m_outputTensors(innerModel->GetOutputTensors()), + m_metaGraph(innerModel->GetMetaGraph()), + m_quantBuffer(innerModel->GetQuantBuffer()), + m_modelName(innerModel->GetModelName()) {} OH_NN_ReturnCode Compilation::SetDevice(size_t deviceId) { @@ -275,7 +278,7 @@ unsigned short Compilation::GetCrc16(const unsigned char* buffer, size_t length) OH_NN_ReturnCode Compilation::GenerateCacheInfo(uint32_t cacheSize, std::unique_ptr& cacheInfo) const { - std::string cacheInfoPath = m_cachePath + "cache_info.nncache"; + 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."); @@ -293,24 +296,24 @@ OH_NN_ReturnCode Compilation::GenerateCacheInfo(uint32_t cacheSize, std::unique_ } OH_NN_ReturnCode Compilation::GenerateCacheModel(size_t cacheNumber, std::unique_ptr& cacheInfo, - std::vector modelBuffer) const + 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 + std::to_string(i) + ".nncache"; + 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].buffer), + uint64_t checkSum = static_cast(GetCrc16(static_cast(modelBuffer[i].data), modelBuffer[i].length)); *cacheInfoPtr++ = checkSum; - if (!cacheModelStream.write(static_cast(modelBuffer[i].buffer), modelBuffer[i].length)) { + if (!cacheModelStream.write(static_cast(modelBuffer[i].data), modelBuffer[i].length)) { LOGE("[Compilation] Fail to write cache model."); cacheModelStream.close(); return OH_NN_FAILED; @@ -322,7 +325,7 @@ OH_NN_ReturnCode Compilation::GenerateCacheModel(size_t cacheNumber, std::unique return OH_NN_SUCCESS; } -OH_NN_ReturnCode Compilation::GenerateCacheFiles(const std::vector& modelBuffer) const +OH_NN_ReturnCode Compilation::GenerateCacheFiles(const std::vector& modelBuffer) const { const size_t cacheNumber = modelBuffer.size(); uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber; @@ -369,7 +372,7 @@ OH_NN_ReturnCode Compilation::GetCacheFileLength(std::ifstream& ifs, int& fsize) return OH_NN_SUCCESS; } -OH_NN_ReturnCode Compilation::ReadCacheModelFile(const std::string& file, ModelBuffer& modelBuffer) const +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); @@ -410,7 +413,7 @@ OH_NN_ReturnCode Compilation::ReadCacheModelFile(const std::string& file, ModelB } ifs.close(); - modelBuffer.buffer = ptr; + modelBuffer.data = ptr; modelBuffer.length = static_cast(fsize); // fsize should be non-negative, safe to cast. return OH_NN_SUCCESS; } @@ -459,7 +462,7 @@ OH_NN_ReturnCode Compilation::CheckCacheInfo(ModelCacheInfo& modelCacheInfo, con OH_NN_ReturnCode Compilation::RemoveCacheFiles(uint32_t fileNumber) const { - std::string cacheInfoPath = m_cachePath + "cache_info.nncache"; + 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; @@ -467,7 +470,7 @@ OH_NN_ReturnCode Compilation::RemoveCacheFiles(uint32_t fileNumber) const LOGI("[Compilation] Succeed to remove the file cache_info.nncach."); for (uint32_t i = 0; i < fileNumber; ++i) { - std::string fileName = std::to_string(i) + ".nncache"; + 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()); @@ -484,23 +487,23 @@ OH_NN_ReturnCode Compilation::RemoveCacheFiles(uint32_t fileNumber) const } OH_NN_ReturnCode Compilation::CheckCacheModel(const ModelCacheInfo& modelCacheInfo, - std::vector& modelBuffers) const + std::vector& modelBuffers) const { for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) { - std::string cacheModelPath = m_cachePath + std::to_string(i) + ".nncache"; + 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; } - ModelBuffer modelBuffer; + 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.buffer), + 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; @@ -515,7 +518,23 @@ OH_NN_ReturnCode Compilation::CheckCacheModel(const ModelCacheInfo& modelCacheIn OH_NN_ReturnCode Compilation::NormalBuild(std::shared_ptr& preparedModel) { ModelConfig config {m_enableFp16, m_performance, m_priority}; - OH_NN_ReturnCode ret = m_device->PrepareModel(m_liteGraph, config, preparedModel); + 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; @@ -523,7 +542,7 @@ OH_NN_ReturnCode Compilation::NormalBuild(std::shared_ptr& prepar m_executionPlan = CreateSharedPtr(preparedModel, m_device); if (m_executionPlan == nullptr) { - LOGE("Fail to create ExecutionPlan instance."); + LOGE("[Compilation] Fail to create ExecutionPlan instance."); return OH_NN_MEMORY_ERROR; } @@ -538,7 +557,7 @@ OH_NN_ReturnCode Compilation::GenCacheBuild(std::shared_ptr& prep return ret; } - std::vector modelBuffers; + std::vector modelBuffers; ret = preparedModel->ExportModelCache(modelBuffers); if (ret != OH_NN_SUCCESS) { LOGE("[Compilation] Export model cache failed."); @@ -575,14 +594,14 @@ OH_NN_ReturnCode Compilation::ReGenCacheBuild(uint32_t fileNumber, std::shared_p OH_NN_ReturnCode Compilation::LoadCacheBuild(std::shared_ptr& preparedModel, const ModelCacheInfo& cacheInfo) { - std::vector modelBuffers; + 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].buffer); - modelBuffers[i].buffer = nullptr; + m_device->ReleaseBuffer(modelBuffers[i].data); + modelBuffers[i].data = nullptr; modelBuffers[i].length = 0; } return ret; @@ -597,6 +616,15 @@ OH_NN_ReturnCode Compilation::LoadCacheBuild(std::shared_ptr& pre 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."); @@ -609,7 +637,7 @@ OH_NN_ReturnCode Compilation::LoadCacheBuild(std::shared_ptr& pre OH_NN_ReturnCode Compilation::BuildCacheModel(std::shared_ptr& preparedModel) { OH_NN_ReturnCode ret; - std::string cacheInfoPath = m_cachePath + "cache_info.nncache"; + 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) { @@ -644,7 +672,12 @@ OH_NN_ReturnCode Compilation::BuildCacheModel(std::shared_ptr& pr ret = LoadCacheBuild(preparedModel, cacheInfo); if (ret != OH_NN_SUCCESS) { - return ret; + // 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; @@ -751,11 +784,21 @@ bool Compilation::IsDynamicShape() const OH_NN_ReturnCode Compilation::IsOfflineModel(bool& isOfflineModel) const { isOfflineModel = false; // Initialize the returned value - if (m_liteGraph == nullptr) { - LOGE("[Compilation] LiteGraph is empty when identifying the offline model."); + 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; diff --git a/frameworks/native/compilation.h b/frameworks/native/compilation.h index 5fa3099a71d1082bda235eee77f9394cc0a57206..171badcb859b923f5630eecfe2810dbd44ceb4d8 100644 --- a/frameworks/native/compilation.h +++ b/frameworks/native/compilation.h @@ -61,18 +61,21 @@ private: 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 GenerateCacheFiles(const std::vector& modelBuffer) const; OH_NN_ReturnCode GenerateCacheModel(size_t cacheNumber, std::unique_ptr& cacheInfo, - std::vector modelBuffer) const; + 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, ModelBuffer& modelBuffer) 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; + 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); diff --git a/frameworks/native/cpp_type.h b/frameworks/native/cpp_type.h index 7e906cc29944f26a918044980668fdfb5ae14714..2f256cc2297e54c527d7fed8e0b429eca9d0a3df 100644 --- a/frameworks/native/cpp_type.h +++ b/frameworks/native/cpp_type.h @@ -39,8 +39,8 @@ struct ModelConfig { OH_NN_Priority priority; }; -struct ModelBuffer { - void* buffer; +struct Buffer { + void* data; size_t length; }; diff --git a/frameworks/native/device.h b/frameworks/native/device.h index e4ae27782a1902980ebd83a24daff3a5d1dae77c..f8f3ecc52c55117021bedd8862138e4ecb12cd2a 100644 --- a/frameworks/native/device.h +++ b/frameworks/native/device.h @@ -22,6 +22,7 @@ #include "interfaces/kits/c/neural_network_runtime_type.h" #include "cpp_type.h" +#include "nn_tensor.h" #include "prepared_model.h" #include "mindir.h" @@ -49,7 +50,11 @@ public: virtual OH_NN_ReturnCode PrepareModel(std::shared_ptr model, const ModelConfig& config, std::shared_ptr& preparedModel) = 0; - virtual OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, + virtual OH_NN_ReturnCode PrepareModel(const void* metaGraph, + const Buffer& quantBuffer, + const ModelConfig& config, + std::shared_ptr& preparedModel) = 0; + virtual OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, const ModelConfig& config, std::shared_ptr& preparedModel) = 0; virtual OH_NN_ReturnCode PrepareOfflineModel(std::shared_ptr model, @@ -57,6 +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 OH_NN_ReturnCode ReleaseBuffer(const void* buffer) = 0; }; } // namespace NeuralNetworkRuntime diff --git a/frameworks/native/execution_plan.cpp b/frameworks/native/execution_plan.cpp index a07449286d25c5f7c86f5de6e7a6e888afdc26c8..18fd280a6f2b310f02bec48617caf59272afa8c2 100644 --- a/frameworks/native/execution_plan.cpp +++ b/frameworks/native/execution_plan.cpp @@ -64,6 +64,10 @@ OH_NN_ReturnCode ExecutionPlan::Run(const std::vector> // 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) { diff --git a/frameworks/native/executor.cpp b/frameworks/native/executor.cpp index 51654043f99cd1e7fd5f89f6a8f0d2cdbb2f4cb8..fda1fff012f3d902d53570fc1dfdde57dc82a1ad 100644 --- a/frameworks/native/executor.cpp +++ b/frameworks/native/executor.cpp @@ -218,7 +218,7 @@ OH_NN_ReturnCode Executor::SetInput(uint32_t index, const OH_NN_Tensor& nnTensor * - The buffer held in m_inputTensors is allocated and set by CreateInputMemory() and SetInputFromMemory(). */ std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - void* inputBuffer = inputDevice->AllocateBuffer(length); + void* inputBuffer = inputDevice->AllocateTensorBuffer(length, inputTensor); if (inputBuffer == nullptr) { LOGE("SetInput failed, error happened when allocating input device buffer."); return OH_NN_MEMORY_ERROR; @@ -314,7 +314,7 @@ OH_NN_ReturnCode Executor::SetOutput(uint32_t index, void* buffer, size_t length m_outputTensors[index].tensor = m_modelOutputs[index]; } - void* deviceOutputBuffer = outputDevice->AllocateBuffer(length); + 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; @@ -400,7 +400,7 @@ OH_NN_ReturnCode Executor::CreateInputMemory(uint32_t index, size_t length, OH_N // Allocate device buffer std::shared_ptr inputDevice = m_executionPlan->GetInputDevice(); - void* deviceInputBuffer = inputDevice->AllocateBuffer(length); + void* deviceInputBuffer = inputDevice->AllocateTensorBuffer(length, m_modelInputs[index]); if (deviceInputBuffer == nullptr) { LOGE("CreateInputMemory failed, allocating intput device buffer failed."); return OH_NN_MEMORY_ERROR; @@ -463,7 +463,7 @@ OH_NN_ReturnCode Executor::CreateOutputMemory(uint32_t index, size_t length, OH_ // Allocate device buffer std::shared_ptr outputDevice = m_executionPlan->GetOutputDevice(); - void* deviceOutputBuffer = outputDevice->AllocateBuffer(length); + void* deviceOutputBuffer = outputDevice->AllocateTensorBuffer(length, m_modelOutputs[index]); if (deviceOutputBuffer == nullptr) { LOGE("CreateOutputMemory failed, allocating output device buffer failed."); return OH_NN_MEMORY_ERROR; diff --git a/frameworks/native/hdi_device_v1_0.cpp b/frameworks/native/hdi_device_v1_0.cpp index 110485e267f06dd44dcaef4263dba73a4bed9db2..3a4582e694612e34a6e052471445802fdaed7edb 100644 --- a/frameworks/native/hdi_device_v1_0.cpp +++ b/frameworks/native/hdi_device_v1_0.cpp @@ -290,7 +290,15 @@ OH_NN_ReturnCode HDIDeviceV1_0::PrepareModel(std::shared_ptr& modelCache, +OH_NN_ReturnCode HDIDeviceV1_0::PrepareModel(const void* metaGraph, + const Buffer& quantBuffer, + const ModelConfig& config, + std::shared_ptr& preparedModel) +{ + return OH_NN_OPERATION_FORBIDDEN; +} + +OH_NN_ReturnCode HDIDeviceV1_0::PrepareModelFromModelCache(const std::vector& modelCache, const ModelConfig& config, std::shared_ptr& preparedModel) { std::vector iBuffers; @@ -299,7 +307,7 @@ OH_NN_ReturnCode HDIDeviceV1_0::PrepareModelFromModelCache(const std::vectorGetMemory(modelCache[i].buffer, memory); + ret = memManager->GetMemory(modelCache[i].data, memory); if (ret != OH_NN_SUCCESS) { LOGE("The %zuth model cache is invalid. Please put valid model cache.", i + 1); return ret; @@ -349,6 +357,11 @@ void* HDIDeviceV1_0::AllocateBuffer(size_t length) return addr; } +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 740835d9b0d91d7f93e5a04397d4e5b0dd448529..77a9d85332aa7a4c9a0bb332a2ce8da401bbae9e 100644 --- a/frameworks/native/hdi_device_v1_0.h +++ b/frameworks/native/hdi_device_v1_0.h @@ -47,7 +47,11 @@ public: OH_NN_ReturnCode PrepareModel(std::shared_ptr model, const ModelConfig& config, std::shared_ptr& preparedModel) override; - OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, + OH_NN_ReturnCode PrepareModel(const void* metaGraph, + const Buffer& quantBuffer, + const ModelConfig& config, + std::shared_ptr& preparedModel) override; + OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, const ModelConfig& config, std::shared_ptr& preparedModel) override; OH_NN_ReturnCode PrepareOfflineModel(std::shared_ptr model, @@ -55,6 +59,7 @@ public: std::shared_ptr& preparedModel) override; void* AllocateBuffer(size_t length) 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 f2a8865209e45bb16d8e4417bdac5e90abec1528..d10b508b5fbac5b3618664d2b562bd1420305cc2 100644 --- a/frameworks/native/hdi_device_v2_0.cpp +++ b/frameworks/native/hdi_device_v2_0.cpp @@ -327,7 +327,15 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareModel(std::shared_ptr& modelCache, +OH_NN_ReturnCode HDIDeviceV2_0::PrepareModel(const void* metaGraph, + const Buffer& quantBuffer, + const ModelConfig& config, + std::shared_ptr& preparedModel) +{ + return OH_NN_OPERATION_FORBIDDEN; +} + +OH_NN_ReturnCode HDIDeviceV2_0::PrepareModelFromModelCache(const std::vector& modelCache, const ModelConfig& config, std::shared_ptr& preparedModel) { std::vector iBuffers; @@ -336,7 +344,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareModelFromModelCache(const std::vectorGetMemory(modelCache[i].buffer, memory); + ret = memManager->GetMemory(modelCache[i].data, memory); if (ret != OH_NN_SUCCESS) { LOGE("The %{public}zuth model cache is invalid. Please put valid model cache.", i + 1); return ret; @@ -384,6 +392,11 @@ void* HDIDeviceV2_0::AllocateBuffer(size_t length) return addr; } +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) { @@ -454,7 +467,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::GetOfflineModelFromLiteGraph(std::shared_ptr>& offlineModels, std::vector& deviceBuffers) + const std::vector>& offlineModels, std::vector& deviceBuffers) { // offlineModels is guaranteed to have at least one element in GetOfflineModelFromLiteGraph, no need to check size. deviceBuffers.clear(); @@ -466,8 +479,8 @@ OH_NN_ReturnCode HDIDeviceV2_0::AllocateDeviceBufferForOfflineModel( if (newModelBuffer == nullptr) { // Release allocated model buffer if error happens. OH_NN_ReturnCode status {OH_NN_SUCCESS}; - for (const ModelBuffer& deviceBuffer : deviceBuffers) { - status = ReleaseBuffer(deviceBuffer.buffer); + for (const Buffer& deviceBuffer : deviceBuffers) { + status = ReleaseBuffer(deviceBuffer.data); if (status != OH_NN_SUCCESS) { LOGE("Release shared buffer of offline model failed."); return status; @@ -479,8 +492,8 @@ OH_NN_ReturnCode HDIDeviceV2_0::AllocateDeviceBufferForOfflineModel( return OH_NN_MEMORY_ERROR; } - ModelBuffer modelBuffer {nullptr, 0}; - modelBuffer.buffer = newModelBuffer; + Buffer modelBuffer {nullptr, 0}; + modelBuffer.data = newModelBuffer; modelBuffer.length = offlineModelSize; deviceBuffers.emplace_back(modelBuffer); } @@ -489,7 +502,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::AllocateDeviceBufferForOfflineModel( } OH_NN_ReturnCode HDIDeviceV2_0::CopyOfflineModelToDevice(const std::vector>& offlineModels, - std::vector& deviceBuffers) + std::vector& deviceBuffers) { if (offlineModels.size() != deviceBuffers.size()) { LOGE("CopyOfflineModelToDevice failed, number of offlineModels not equal to allocated buffers."); @@ -505,7 +518,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::CopyOfflineModelToDevice(const std::vector& deviceBuffers, +OH_NN_ReturnCode HDIDeviceV2_0::PrepareOfflineModel(std::vector& deviceBuffers, const ModelConfig& config, const std::map> extensions, std::shared_ptr& preparedModel) @@ -537,7 +550,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareOfflineModel(std::vector& de OH_NN_ReturnCode ret; size_t numOfflineModel = deviceBuffers.size(); for (size_t i = 0; i < numOfflineModel; i++) { - ret = memManager->GetMemory(deviceBuffers[i].buffer, memory); + ret = memManager->GetMemory(deviceBuffers[i].data, memory); if (ret != OH_NN_SUCCESS) { LOGE("Retrieve the memory of %zuth device buffer failed.", i); return ret; @@ -549,8 +562,8 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareOfflineModel(std::vector& de // Release allocated model buffer after prepare model. OH_NN_ReturnCode status {OH_NN_SUCCESS}; - for (const ModelBuffer& deviceBuffer : deviceBuffers) { - status = ReleaseBuffer(deviceBuffer.buffer); + for (const Buffer& deviceBuffer : deviceBuffers) { + status = ReleaseBuffer(deviceBuffer.data); if (status != OH_NN_SUCCESS) { LOGE("Release shared buffer of offline model failed."); return status; @@ -587,7 +600,7 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareOfflineModel(std::shared_ptr deviceBuffers; + std::vector deviceBuffers; status = AllocateDeviceBufferForOfflineModel(offlineModels, deviceBuffers); if (status != OH_NN_SUCCESS) { LOGE("Error happens when allocating device buffers for offline model."); @@ -600,8 +613,8 @@ OH_NN_ReturnCode HDIDeviceV2_0::PrepareOfflineModel(std::shared_ptr model, const ModelConfig& config, std::shared_ptr& preparedModel) override; - OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, + OH_NN_ReturnCode PrepareModel(const void* metaGraph, + const Buffer& quantBuffer, + const ModelConfig& config, + std::shared_ptr& preparedModel) override; + OH_NN_ReturnCode PrepareModelFromModelCache(const std::vector& modelCache, const ModelConfig& config, std::shared_ptr& preparedModel) override; OH_NN_ReturnCode PrepareOfflineModel(std::shared_ptr model, @@ -55,6 +59,7 @@ public: std::shared_ptr& preparedModel) override; void* AllocateBuffer(size_t length) override; + void* AllocateTensorBuffer(size_t length, std::shared_ptr tensor) override; OH_NN_ReturnCode ReleaseBuffer(const void* buffer) override; private: @@ -62,10 +67,10 @@ private: OH_NN_ReturnCode GetOfflineModelFromLiteGraph(std::shared_ptr graph, std::vector>& offlineModels); OH_NN_ReturnCode AllocateDeviceBufferForOfflineModel(const std::vector>& offlineModels, - std::vector& deviceBuffers); + std::vector& deviceBuffers); OH_NN_ReturnCode CopyOfflineModelToDevice(const std::vector>& offlineModels, - std::vector& deviceBuffers); - OH_NN_ReturnCode PrepareOfflineModel(std::vector& deviceBuffers, + std::vector& deviceBuffers); + OH_NN_ReturnCode PrepareOfflineModel(std::vector& deviceBuffers, const ModelConfig& config, const std::map> extensions, std::shared_ptr& preparedModel); diff --git a/frameworks/native/hdi_prepared_model_v1_0.cpp b/frameworks/native/hdi_prepared_model_v1_0.cpp index 5df1eee12f61ad23ed21aa566778adc8b053dd7d..35fccc61f079f50592c2543264c43fb6316e4b9c 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.cpp +++ b/frameworks/native/hdi_prepared_model_v1_0.cpp @@ -99,7 +99,7 @@ HDIPreparedModelV1_0::HDIPreparedModelV1_0(OHOS::sptr hdiP hdiPreparedModel->GetVersion(m_hdiVersion.first, m_hdiVersion.second); } -OH_NN_ReturnCode HDIPreparedModelV1_0::ExportModelCache(std::vector& modelCache) +OH_NN_ReturnCode HDIPreparedModelV1_0::ExportModelCache(std::vector& modelCache) { if (!modelCache.empty()) { LOGE("The vector of modelCache should be empty. size=%zu", modelCache.size()); @@ -121,7 +121,7 @@ OH_NN_ReturnCode HDIPreparedModelV1_0::ExportModelCache(std::vector LOGE("Export the %zuth model cache failed, cannot not map fd to address.", i + 1); return OH_NN_MEMORY_ERROR; } - ModelBuffer modelbuffer {addr, iBuffers[i].bufferSize}; + Buffer modelbuffer {addr, iBuffers[i].bufferSize}; modelCache.emplace_back(modelbuffer); } diff --git a/frameworks/native/hdi_prepared_model_v1_0.h b/frameworks/native/hdi_prepared_model_v1_0.h index 4b71c71df8807505a1a391cec1ca1fdba9e7150c..b98a7ecfb739ba9cc15d8cf428806e71545f4512 100644 --- a/frameworks/native/hdi_prepared_model_v1_0.h +++ b/frameworks/native/hdi_prepared_model_v1_0.h @@ -34,7 +34,7 @@ class HDIPreparedModelV1_0 : public PreparedModel { public: explicit HDIPreparedModelV1_0(OHOS::sptr hdiPreparedModel); - OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) override; + OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) override; OH_NN_ReturnCode Run(const std::vector& inputs, const std::vector& outputs, diff --git a/frameworks/native/hdi_prepared_model_v2_0.cpp b/frameworks/native/hdi_prepared_model_v2_0.cpp index 37777f97f39d7890d64271a2b09a37941621f1c2..40b15b28484e2cad907009af344a49eae8b55cc0 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.cpp +++ b/frameworks/native/hdi_prepared_model_v2_0.cpp @@ -100,7 +100,7 @@ HDIPreparedModelV2_0::HDIPreparedModelV2_0(OHOS::sptr hdiP hdiPreparedModel->GetVersion(m_hdiVersion.first, m_hdiVersion.second); } -OH_NN_ReturnCode HDIPreparedModelV2_0::ExportModelCache(std::vector& modelCache) +OH_NN_ReturnCode HDIPreparedModelV2_0::ExportModelCache(std::vector& modelCache) { if (!modelCache.empty()) { LOGE("The vector of modelCache should be empty. size=%{public}zu", modelCache.size()); @@ -121,7 +121,7 @@ OH_NN_ReturnCode HDIPreparedModelV2_0::ExportModelCache(std::vector LOGE("Export the %{public}zuth model cache failed, cannot not map fd to address.", i + 1); return OH_NN_MEMORY_ERROR; } - ModelBuffer modelbuffer {addr, iBuffers[i].bufferSize}; + Buffer modelbuffer {addr, iBuffers[i].bufferSize}; modelCache.emplace_back(modelbuffer); } diff --git a/frameworks/native/hdi_prepared_model_v2_0.h b/frameworks/native/hdi_prepared_model_v2_0.h index 5b3e67ad98a78772026fb974f47488712bf4e18e..9648eae722a1dfdab99981f8c0508e3cbc85708e 100644 --- a/frameworks/native/hdi_prepared_model_v2_0.h +++ b/frameworks/native/hdi_prepared_model_v2_0.h @@ -35,7 +35,7 @@ class HDIPreparedModelV2_0 : public PreparedModel { public: explicit HDIPreparedModelV2_0(OHOS::sptr hdiPreparedModel); - OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) override; + OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) override; OH_NN_ReturnCode Run(const std::vector& inputs, const std::vector& outputs, diff --git a/frameworks/native/inner_model.cpp b/frameworks/native/inner_model.cpp index e3df670754667a14bd4e9434834bda6850e304c9..a09643ea374087e4378b1e05b2d5b49cfbabcc68 100644 --- a/frameworks/native/inner_model.cpp +++ b/frameworks/native/inner_model.cpp @@ -52,6 +52,7 @@ std::shared_ptr ConstructNNTensorFromLiteGraphTensor(const MSLITE::Ten std::vector msDims = MSLITE::MindIR_Tensor_GetDims(msTensor); std::vector msQuantParams = MSLITE::MindIR_Tensor_GetQuantParams(msTensor); std::vector nnQuantParams = MSToNN::TransformQuantParams(msQuantParams); + OH_NN_Format nnFormat = MSToNN::TransformFormat(MSLITE::MindIR_Tensor_GetFormat(msTensor)); std::shared_ptr nnTensor = CreateSharedPtr(); if (nnTensor == nullptr) { @@ -65,6 +66,8 @@ std::shared_ptr ConstructNNTensorFromLiteGraphTensor(const MSLITE::Ten return nullptr; } + nnTensor->SetFormat(nnFormat); + return nnTensor; } @@ -102,7 +105,7 @@ InnerModel::InnerModel() {} bool InnerModel::IsBuild() const { - return (m_liteGraph != nullptr); + return ((m_liteGraph != nullptr) || (m_metaGraph != nullptr)); } OH_NN_ReturnCode InnerModel::BuildFromLiteGraph(const MSLITE::LiteGraph* liteGraph) @@ -113,8 +116,8 @@ OH_NN_ReturnCode InnerModel::BuildFromLiteGraph(const MSLITE::LiteGraph* liteGra return OH_NN_INVALID_PARAMETER; } - if (m_liteGraph != nullptr) { - LOGE("BuildFromLiteGraph failed, liteGraph has been built or loaded before."); + if (IsBuild()) { + LOGE("BuildFromLiteGraph failed, inner model has been built or loaded before."); return OH_NN_OPERATION_FORBIDDEN; } @@ -143,10 +146,36 @@ OH_NN_ReturnCode InnerModel::BuildFromLiteGraph(const MSLITE::LiteGraph* liteGra return OH_NN_SUCCESS; } +OH_NN_ReturnCode InnerModel::BuildFromMetaGraph( + const void* metaGraph, const Buffer& quantBuffer, const std::string& modelName) +{ + NNRT_TRACE_NAME("Build model from meta graph"); + if (metaGraph == nullptr) { + LOGE("BuildFromMetaGraph failed, passed empty metaGraph."); + return OH_NN_INVALID_PARAMETER; + } + + if (IsBuild()) { + LOGE("BuildFromMetaGraph failed, inner model has been built or loaded before."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (m_allTensors.empty()) { + LOGE("BuildFromMetaGraph failed, SetInputsAndOutputsInfo should be called before building metaGraph."); + return OH_NN_OPERATION_FORBIDDEN; + } + + m_metaGraph = const_cast(metaGraph); + m_quantBuffer = quantBuffer; + m_modelName = modelName; + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode InnerModel::AddTensor(const OH_NN_Tensor& nnTensor) { - if (m_liteGraph != nullptr) { - LOGE("AddTensor failed, AddTensor is forbidden after Finish() or LoadLiteGraph() has been called."); + if (IsBuild()) { + LOGE("AddTensor failed, AddTensor is forbidden after model has been built."); return OH_NN_OPERATION_FORBIDDEN; } @@ -172,8 +201,8 @@ OH_NN_ReturnCode InnerModel::AddTensor(const OH_NN_Tensor& nnTensor) // DOTO: 圈复杂度待优化 OH_NN_ReturnCode InnerModel::SetTensorValue(uint32_t index, const void* buffer, size_t length) { - if (m_liteGraph != nullptr) { - LOGE("SetTensorValue failed, SetTensorValue is forbidden after Finish() or LoadLiteGraph() has been called."); + if (IsBuild()) { + LOGE("SetTensorValue failed, SetTensorValue is forbidden after model has been built."); return OH_NN_OPERATION_FORBIDDEN; } @@ -302,8 +331,8 @@ OH_NN_ReturnCode InnerModel::ValidateTensorArray(const OH_NN_UInt32Array& indice OH_NN_ReturnCode InnerModel::AddOperation(OH_NN_OperationType opType, const OH_NN_UInt32Array& paramIndices, const OH_NN_UInt32Array& inputIndices, const OH_NN_UInt32Array& outputIndices) { - if (m_liteGraph != nullptr) { - LOGE("AddOperation failed, AddOperation is forbidden after after Finish() or LoadLiteGraph() has been called."); + if (IsBuild()) { + LOGE("AddOperation failed, AddOperation is forbidden after model has been built."); return OH_NN_OPERATION_FORBIDDEN; } @@ -342,9 +371,8 @@ OH_NN_ReturnCode InnerModel::AddOperation(OH_NN_OperationType opType, const OH_N OH_NN_ReturnCode InnerModel::SpecifyInputsAndOutputs( const OH_NN_UInt32Array& inputIndices, const OH_NN_UInt32Array& outputIndices) { - if (m_liteGraph != nullptr) { - LOGE("SpecifyInputsAndOutputs failed, " - "SpecifyInputsAndOutputs is forbidden after Finish() or LoadLiteGraph() has been called."); + if (IsBuild()) { + LOGE("SpecifyInputsAndOutputs failed, SpecifyInputsAndOutputs is forbidden after model has been built."); return OH_NN_OPERATION_FORBIDDEN; } @@ -373,12 +401,90 @@ OH_NN_ReturnCode InnerModel::SpecifyInputsAndOutputs( return OH_NN_SUCCESS; } +OH_NN_ReturnCode InnerModel::CheckParameters() const +{ + if (m_liteGraph != nullptr) { + LOGE("CheckParameters failed, liteGraph is not nullptr."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (m_metaGraph != nullptr) { + LOGE("CheckParameters failed, metaGraph is not nullptr."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (!m_allTensors.empty()) { + LOGE("CheckParameters failed, m_allTensors is not empty."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (!(m_inputTensors.empty() && (m_inputIndices.empty()))) { + LOGE("CheckParameters failed, m_inputTensors is not empty."); + return OH_NN_OPERATION_FORBIDDEN; + } + + if (!(m_outputTensors.empty() && (m_outputIndices.empty()))) { + LOGE("CheckParameters failed, m_outputTensors is not empty."); + return OH_NN_OPERATION_FORBIDDEN; + } + + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode InnerModel::SetInputsAndOutputsInfo(const OH_NN_TensorInfo* inputsInfo, size_t inputSize, + const OH_NN_TensorInfo* outputsInfo, size_t outputSize) +{ + OH_NN_ReturnCode ret = CheckParameters(); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInputsAndOutputsInfo failed, error happened when checking parameters."); + return ret; + } + + // 根据inputsInfo设置输入NNTensor + for (size_t i = 0; i < inputSize; ++i) { + std::shared_ptr tensor = CreateSharedPtr(); + if (tensor == nullptr) { + LOGE("SetInputsAndOutputsInfo failed, error happened when creating input NNTensor."); + return OH_NN_MEMORY_ERROR; + } + + ret = tensor->BuildFromOHNNTensorInfo(inputsInfo[i]); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInputsAndOutputsInfo failed, error happened when building input NNTensor from info."); + return ret; + } + m_inputIndices.emplace_back(i); + m_allTensors.emplace_back(tensor); + m_inputTensors.emplace_back(tensor); + } + + // 根据outputsInfo设置输入NNTensor + for (size_t i = 0; i < outputSize; ++i) { + std::shared_ptr tensor = CreateSharedPtr(); + if (tensor == nullptr) { + LOGE("SetInputsAndOutputsInfo failed, error happened when creating output NNTensor."); + return OH_NN_MEMORY_ERROR; + } + + ret = tensor->BuildFromOHNNTensorInfo(outputsInfo[i]); + if (ret != OH_NN_SUCCESS) { + LOGE("SetInputsAndOutputsInfo failed, error happened when building output NNTensor from info."); + return ret; + } + m_outputIndices.emplace_back(i + inputSize); + m_allTensors.emplace_back(tensor); + m_outputTensors.emplace_back(tensor); + } + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode InnerModel::Build() { NNRT_TRACE_NAME("Build model"); - if (m_liteGraph != nullptr) { - LOGE("Build failed," - " OH_NNModel is not allowed to build again after Build() or BuildFromLiteGraph() has been called."); + if (IsBuild()) { + LOGE("Build failed, OH_NNModel_Finish() shouldn't be called after OH_NNModel_Finish() or " + "OH_NNModel_BuildFromMetaGraph() or OH_NNModel_BuildFromLiteGraph()."); return OH_NN_OPERATION_FORBIDDEN; } @@ -542,5 +648,20 @@ std::vector> InnerModel::GetOutputTensors() const { return m_outputTensors; } + +void* InnerModel::GetMetaGraph() const +{ + return m_metaGraph; +} + +Buffer InnerModel::GetQuantBuffer() const +{ + return m_quantBuffer; +} + +std::string InnerModel::GetModelName() const +{ + return m_modelName; +} } // namespace NeuralNetworkRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inner_model.h b/frameworks/native/inner_model.h index 6a4460d79677d41b68a55289d5e5a217db100ad5..8c7f3d5f74e4a1e991f7d8481094488284566a2c 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 "interfaces/innerkits/c/neural_network_runtime_inner.h" #include "interfaces/kits/c/neural_network_runtime.h" namespace OHOS { @@ -31,6 +32,8 @@ public: bool IsBuild() const; OH_NN_ReturnCode BuildFromLiteGraph(const mindspore::lite::LiteGraph* liteGraph); + 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 SetTensorValue(uint32_t index, const void* buffer, size_t length); OH_NN_ReturnCode AddOperation(OH_NN_OperationType opType, @@ -40,10 +43,15 @@ public: OH_NN_ReturnCode GetSupportedOperations(size_t deviceID, const bool** isSupported, uint32_t& opCount); OH_NN_ReturnCode SpecifyInputsAndOutputs( const OH_NN_UInt32Array& inputIndices, const OH_NN_UInt32Array& outputIndices); + OH_NN_ReturnCode SetInputsAndOutputsInfo(const OH_NN_TensorInfo* inputsInfo, size_t inputSize, + const OH_NN_TensorInfo* outputsInfo, size_t outputSize); OH_NN_ReturnCode Build(); std::vector> GetInputTensors() const; std::vector> GetOutputTensors() const; std::shared_ptr GetLiteGraphs() const; + void* GetMetaGraph() const; + Buffer GetQuantBuffer() const; + std::string GetModelName() const; private: void AddTensorsToLiteGraph(std::unordered_map& modelIDToGraphID); @@ -51,6 +59,7 @@ private: OH_NN_ReturnCode ValidateInputAndOutput( const OH_NN_UInt32Array& inputIndices, const OH_NN_UInt32Array& outputIndices) const; OH_NN_ReturnCode ValidateTensorArray(const OH_NN_UInt32Array& indices) const; + OH_NN_ReturnCode CheckParameters() const; private: std::vector m_supportedOperations; // std::vector not support data(), use std::vector instead. @@ -61,6 +70,9 @@ private: std::vector> m_inputTensors; // Used to pass input tensors to compilation. std::vector> m_outputTensors; // Used to pass output tensors to compilation. std::shared_ptr m_liteGraph {nullptr}; + void* m_metaGraph {nullptr}; + Buffer m_quantBuffer; + std::string m_modelName; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/memory_manager.cpp b/frameworks/native/memory_manager.cpp index 7c437cd2ac5c1ed0aecf57c7331125ff72e6a3e1..1c6cc874438c3adced65f6963ebe1a64e84807b1 100644 --- a/frameworks/native/memory_manager.cpp +++ b/frameworks/native/memory_manager.cpp @@ -93,7 +93,7 @@ OH_NN_ReturnCode MemoryManager::GetMemory(const void* buffer, Memory& memory) co } memory.fd = iter->second.fd; - memory.data = buffer; + memory.data = iter->second.data; memory.length = iter->second.length; return OH_NN_SUCCESS; diff --git a/frameworks/native/neural_network_runtime.cpp b/frameworks/native/neural_network_runtime.cpp index dfd5f366f1171ee3abdaf123efd7b49e5e468ede..f492754217c0ba477be721f78e6415dbc0f97a43 100644 --- a/frameworks/native/neural_network_runtime.cpp +++ b/frameworks/native/neural_network_runtime.cpp @@ -164,6 +164,57 @@ NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromLiteGraph(OH_NNModel *model, const 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) { diff --git a/frameworks/native/nn_tensor.cpp b/frameworks/native/nn_tensor.cpp index fcdcfddf8e70586ff1734da5cef1475c502187c1..71755a1c955c64a23355dc1a86390c6938ff51a7 100644 --- a/frameworks/native/nn_tensor.cpp +++ b/frameworks/native/nn_tensor.cpp @@ -115,7 +115,7 @@ OH_NN_ReturnCode NNTensor::BuildFromOHNNTensor(const OH_NN_Tensor& nnTensor) return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret = ParseDimensions(nnTensor); + OH_NN_ReturnCode ret = ParseDimensions(nnTensor.dimensions, nnTensor.dimensionCount); if (ret != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, passed invalid nnTensor dimensions."); return ret; @@ -130,6 +130,30 @@ OH_NN_ReturnCode NNTensor::BuildFromOHNNTensor(const OH_NN_Tensor& nnTensor) return OH_NN_SUCCESS; } +OH_NN_ReturnCode NNTensor::BuildFromOHNNTensorInfo(const OH_NN_TensorInfo& nnTensorInfo) +{ + if (!Validation::ValidateTensorDataType(nnTensorInfo.dataType)) { + LOGE("BuildFromOHNNTensorInfo failed, passed invalid data type: %d.", nnTensorInfo.dataType); + return OH_NN_INVALID_PARAMETER; + } + m_dataType = nnTensorInfo.dataType; + + if (!Validation::ValidateTensorFormat(nnTensorInfo.format)) { + LOGE("BuildFromOHNNTensorInfo failed, passed invalid nnTensorInfo format: %d.", nnTensorInfo.format); + return OH_NN_INVALID_PARAMETER; + } + m_format = nnTensorInfo.format; + m_name = nnTensorInfo.name; + + OH_NN_ReturnCode ret = ParseDimensions(nnTensorInfo.dimensions, nnTensorInfo.dimensionCount); + if (ret != OH_NN_SUCCESS) { + LOGE("BuildFromOHNNTensorInfo failed, passed invalid nnTensorInfo dimensions."); + return ret; + } + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode NNTensor::ParseDimensions(const std::vector& dimensions) { // Temporary variable to check overflow. @@ -167,16 +191,16 @@ OH_NN_ReturnCode NNTensor::ParseDimensions(const std::vector& dimension return OH_NN_SUCCESS; } -OH_NN_ReturnCode NNTensor::ParseDimensions(const OH_NN_Tensor& nnTensor) +OH_NN_ReturnCode NNTensor::ParseDimensions(const int32_t* dimensions, uint32_t dimensionCount) { - OH_NN_ReturnCode ret = Validation::ValidateArray(nnTensor.dimensions, nnTensor.dimensionCount); + OH_NN_ReturnCode ret = Validation::ValidateArray(dimensions, dimensionCount); if (ret != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, please check dimension and dimensionCount in NNTensor."); return ret; } - std::vector dimensions = ConstructVectorFromArray(nnTensor.dimensions, nnTensor.dimensionCount); + std::vector dimensionsVec = ConstructVectorFromArray(dimensions, dimensionCount); - ret = ParseDimensions(dimensions); + ret = ParseDimensions(dimensionsVec); if (ret != OH_NN_SUCCESS) { LOGE("BuildFromOHNNTensor failed, passed invalid dimension info."); return ret; @@ -248,7 +272,7 @@ void NNTensor::SetBuffer(const void* buffer, size_t length) m_bufferLength = length; } -void NNTensor::SetFormat(OH_NN_Format format) +void NNTensor::SetFormat(const OH_NN_Format& format) { m_format = format; } diff --git a/frameworks/native/nn_tensor.h b/frameworks/native/nn_tensor.h index 60d6de5bf314116a12ef9b6299915a0f2c04a40e..fc7db023825ea80e8d8dbcaffa627b82343005d5 100644 --- a/frameworks/native/nn_tensor.h +++ b/frameworks/native/nn_tensor.h @@ -21,6 +21,7 @@ #include "cpp_type.h" #include "interfaces/kits/c/neural_network_runtime.h" +#include "interfaces/innerkits/c/neural_network_runtime_inner.h" namespace OHOS { namespace NeuralNetworkRuntime { @@ -39,6 +40,7 @@ public: NNTensor& operator=(const NNTensor& tensor) = delete; OH_NN_ReturnCode BuildFromOHNNTensor(const OH_NN_Tensor& nnTensor); + OH_NN_ReturnCode BuildFromOHNNTensorInfo(const OH_NN_TensorInfo& nnTensorInfo); OH_NN_ReturnCode Build(OH_NN_DataType dataType, const std::vector& dimensions, const std::vector& quantParam, @@ -47,7 +49,7 @@ public: void SetName(const std::string& name); void SetBuffer(const void* buffer, size_t length); - void SetFormat(OH_NN_Format format); + void SetFormat(const OH_NN_Format& format); OH_NN_ReturnCode SetDimensions(const std::vector& dimensions); std::string GetName() const; @@ -74,7 +76,7 @@ public: private: // Used in BuildFromOHNNTensor() OH_NN_ReturnCode ParseQuantParams(const OH_NN_QuantParam* quantParams); - OH_NN_ReturnCode ParseDimensions(const OH_NN_Tensor& nnTensor); + 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); diff --git a/frameworks/native/prepared_model.h b/frameworks/native/prepared_model.h index 06ed645fa7b673d9744e2a755ea2f57030a7049a..7e64f08a68ac9232720658b3451d0f9eb4f469ed 100644 --- a/frameworks/native/prepared_model.h +++ b/frameworks/native/prepared_model.h @@ -28,7 +28,7 @@ public: PreparedModel() = default; virtual ~PreparedModel() = default; - virtual OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) = 0; + virtual OH_NN_ReturnCode ExportModelCache(std::vector& modelCache) = 0; virtual OH_NN_ReturnCode Run(const std::vector& inputs, const std::vector& outputs, diff --git a/frameworks/native/transform.cpp b/frameworks/native/transform.cpp index d3705d5381f93b45c79d0def51b688b8608adf5f..12e51b05209f2a7e2fd1c63b07c26bf6854805a4 100644 --- a/frameworks/native/transform.cpp +++ b/frameworks/native/transform.cpp @@ -167,5 +167,16 @@ std::vector MSToNN::TransformQuantParams(std::vector TransformQuantParams(std::vector msQuantParams); +OH_NN_Format TransformFormat(mindspore::lite::Format msFormat); } // namespace MSToNN } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/validation.cpp b/frameworks/native/validation.cpp index 719c8be3600821f1462179d5bd76efa34caae588..d451601d122036d916cf0fac1dd5eb7f2a240318 100644 --- a/frameworks/native/validation.cpp +++ b/frameworks/native/validation.cpp @@ -28,6 +28,14 @@ bool ValidateTensorDataType(OH_NN_DataType dataType) return false; } +bool ValidateTensorFormat(OH_NN_Format format) +{ + if ((format >= OH_NN_FORMAT_NONE) && (format <= OH_NN_FORMAT_NHWC)) { + return true; + } + return false; +} + bool ValidatePerformanceMode(OH_NN_PerformanceMode performanceMode) { if ((performanceMode >= OH_NN_PERFORMANCE_NONE) && (performanceMode <= OH_NN_PERFORMANCE_EXTREME)) { diff --git a/frameworks/native/validation.h b/frameworks/native/validation.h index 003df7bc72dc4d50cfc56c546c5418fbc1e54129..7c6d54012a3dfb923e4edcb21b61c7abac399758 100644 --- a/frameworks/native/validation.h +++ b/frameworks/native/validation.h @@ -35,6 +35,7 @@ OH_NN_ReturnCode ValidateArray(const T* data, size_t size) bool ValidateTensorType(OH_NN_TensorType nnTensorType); bool ValidateTensorDataType(OH_NN_DataType dataType); +bool ValidateTensorFormat(OH_NN_Format format); bool ValidatePerformanceMode(OH_NN_PerformanceMode performanceMode); bool ValidatePriority(OH_NN_Priority priority); bool ValidateFuseType(OH_NN_FuseType fuseType); diff --git a/interfaces/innerkits/c/neural_network_runtime_inner.h b/interfaces/innerkits/c/neural_network_runtime_inner.h index 4b298e4f00498836eba507488ac578e5139ae63c..314e986ff92704608cf8d0cb5674c5ff07aae082 100644 --- a/interfaces/innerkits/c/neural_network_runtime_inner.h +++ b/interfaces/innerkits/c/neural_network_runtime_inner.h @@ -22,6 +22,32 @@ extern "C" { #endif +/** + * @brief 定义Tensor信息结构体。包含名字,数据类型,维度信息,格式信息。 + * + * @since 10 + * @version 1.1 + */ +typedef struct OH_NN_TensorInfo { + char name[128]; + OH_NN_DataType dataType; + uint32_t dimensionCount; + const int32_t *dimensions; + OH_NN_Format format; +} OH_NN_TensorInfo; + +/** + * @brief 定义扩展字段结构体。 + * + * @since 10 + * @version 1.1 + */ +typedef struct OH_NN_Extension { + char name[128]; + char *value; + size_t valueSize; +} OH_NN_Extension; + /** * @brief 直接加载LiteGraph,完成模型搭建。 * @@ -33,7 +59,7 @@ extern "C" { * 等构图接口混用,否则返回{@link OH_NN_OPERATION_FORBIDDEN}错误。\n * * 如果本方法调用成功,返回{@link OH_NN_SUCCESS},liteGraph将由NNRt管理,调用者无需释放,避免造成二次释放; - * 如果方法返回其他错误码,则NNRt不会持有liteGraph,此时需要调用者主动释放内存。 + * 如果方法返回其他错误码,则NNRt不会持有liteGraph,此时需要调用者主动释放内存。\n * * * 本接口不作为Neural Network Runtime接口对外开放。\n @@ -48,6 +74,59 @@ extern "C" { */ OH_NN_ReturnCode OH_NNModel_BuildFromLiteGraph(OH_NNModel *model, const void *liteGraph); +/** + * @brief 设置MetaGraph的输入输出信息。 + * + * 调用{@link OH_NNModel_Construct}创建模型实例后,直接调用本方法设置MetaGraph的输入输出信息。然后调用{@link OH_NNModel_BuildFromMetaGraph} + * 加载MetaGraph,完成模型搭建。\n + * + * 不允许本方法与{@link OH_NNModel_AddTensor}、和{@link OH_NNModel_SpecifyInputsAndOutputs} + * 等构图接口混用,否则返回{@link OH_NN_OPERATION_FORBIDDEN}错误。\n + * + * 如果本方法调用成功,返回{@link OH_NN_SUCCESS}。\n + * + * + * 本接口不作为Neural Network Runtime接口对外开放。\n + * + * @param model 指向{@link OH_NNModel}实例的指针。 + * @param inputsInfo 指向{@link OH_NN_TensorInfo}数组的指针,代表传入的输入Tensor信息。 + * @param inputSize 代表inputsInfo数组大小。 + * @param outputsInfo 指向{@link OH_NN_TensorInfo}数组的指针,代表传入的输出Tensor信息。 + * @param outputSize 代表outputsInfo数组大小。 + * @return 函数执行的结果状态,执行成功返回OH_NN_SUCCESS,失败返回具体错误码,参考{@link OH_NN_ReturnCode}。 + * @since 10 + * @version 1.1 + */ +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); + +/** + * @brief 直接加载MetaGraph,完成模型搭建。 + * + * 调用{@link OH_NNModel_SetInputsAndOutputsInfo}设置好MetaGraph输入输出信息后,直接调用本方法加载MetaGraph。加载MetaGraph后,只能调用 + * {@link OH_NNCompilation_Construct}创建模型编译器,或者调用{@link OH_NNModel_Destroy}销毁模型实例。\n + * + * 不允许本方法与{@link OH_NNModel_AddTensor}、{@link OH_NNModel_AddOperation}、 + * {@link OH_NNModel_SetTensorData}、{@link OH_NNModel_SpecifyInputsAndOutputs}和{@link OH_NNModel_Finish} + * 等构图接口混用,否则返回{@link OH_NN_OPERATION_FORBIDDEN}错误。\n + * + * 如果本方法调用成功,返回{@link OH_NN_SUCCESS}。\n + * + * + * 本接口不作为Neural Network Runtime接口对外开放。\n + * + * @param model 指向{@link OH_NNModel}实例的指针。 + * @param metaGraph 指向MetaGraph的指针。 + * @param extensions 指向{@ OH_NN_Extension}数组的指针,代表传入的扩展字段。 + * 例如,传递量化信息时,指定Extension.name为"QuantBuffer",将量化Buffer赋给value和valueSize。 + * @param extensionSize 代表extensions数组大小。 + * @return 函数执行的结果状态,执行成功返回OH_NN_SUCCESS,失败返回具体错误码,参考{@link OH_NN_ReturnCode}。 + * @since 10 + * @version 1.1 + */ +OH_NN_ReturnCode OH_NNModel_BuildFromMetaGraph(OH_NNModel *model, const void *metaGraph, + const OH_NN_Extension *extensions, size_t extensionSize); + #ifdef __cplusplus } #endif // __cpluscplus