diff --git a/bundle.json b/bundle.json index 8146cfc588a22589d34c113472cac102423cb3ef..faf9d9167784f95d86299a726b4052376e0c6b7f 100644 --- a/bundle.json +++ b/bundle.json @@ -33,7 +33,8 @@ "init", "json", "jsoncpp", - "eventhandler" + "eventhandler", + "openssl" ], "third_party": [] }, diff --git a/frameworks/native/neural_network_core/BUILD.gn b/frameworks/native/neural_network_core/BUILD.gn index 02ece699b29a14fb92b268d381d60f36318c202c..e15a4a3a2e6460c5bee59746789251d3bcb6a99c 100644 --- a/frameworks/native/neural_network_core/BUILD.gn +++ b/frameworks/native/neural_network_core/BUILD.gn @@ -59,6 +59,7 @@ ohos_shared_library("libneural_network_core") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "openssl:libcrypto_shared", ] subsystem_name = "ai" diff --git a/frameworks/native/neural_network_core/compiler.h b/frameworks/native/neural_network_core/compiler.h index 6d62c9abc90c47145b5ffa63eeb4b4975c58016c..256da44ea1f27973e06a9a94a8e90dc970013e0b 100644 --- a/frameworks/native/neural_network_core/compiler.h +++ b/frameworks/native/neural_network_core/compiler.h @@ -47,6 +47,8 @@ public: 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 GetModelName(std::string& modelName) = 0; + virtual size_t GetModelSize() = 0; + virtual size_t GetOnlineModelID() = 0; }; } // namespace NeuralNetworkRuntime } // namespace OHOS diff --git a/frameworks/native/neural_network_core/neural_network_core.cpp b/frameworks/native/neural_network_core/neural_network_core.cpp index ebf666ed0457fcc708c3c2d3b0496b72eef9bde0..30e5c6332b2182e547b21f81889c0e00e032bfc7 100644 --- a/frameworks/native/neural_network_core/neural_network_core.cpp +++ b/frameworks/native/neural_network_core/neural_network_core.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "log.h" #include "executor.h" @@ -32,46 +33,109 @@ using namespace OHOS::NeuralNetworkRuntime; #define NNRT_API __attribute__((visibility("default"))) -const size_t INPUT_OUTPUT_MAX_INDICES = 200; +constexpr size_t INPUT_OUTPUT_MAX_INDICES = 200; +constexpr size_t MODEL_MAX_LIMIT = 200 * 1024 * 1024; // 200MB +constexpr size_t CACHE_ID_CALCULATE_SIZE = 512 * 1024; // 0.5MB +constexpr size_t WIDTH = 4; +constexpr size_t TWO = 2; +constexpr size_t END = 1; +constexpr unsigned char MASK = 0x0F; namespace { -OH_NN_ReturnCode GetNnrtModelId(Compilation* compilationImpl, NNRtServiceApi& nnrtService) +std::string Sha256(const std::vector& dataList, const std::vector& sizeList, bool isUpper) { - std::string modelName; - compilationImpl->compiler->GetModelName(modelName); + unsigned char hash[SHA256_DIGEST_LENGTH * TWO + END] = ""; + + SHA256_CTX ctx; + SHA256_Init(&ctx); + for (size_t index = 0; index < dataList.size(); ++index) { + SHA256_Update(&ctx, dataList[index], sizeList[index]); + } + SHA256_Final(&hash[SHA256_DIGEST_LENGTH], &ctx); + + // here we translate sha256 hash to hexadecimal. + // each 8-bit char will be presented by two characters([0-9a-f]) + const char* hexCode = isUpper ? "0123456789ABCDEF" : "0123456789abcdef"; + for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) { + unsigned char value = hash[SHA256_DIGEST_LENGTH + i]; + // uint8_t is 2 digits in hexadecimal. + hash[i * TWO] = hexCode[(value >> WIDTH) & MASK]; + hash[i * TWO + END] = hexCode[value & MASK]; + } + hash[SHA256_DIGEST_LENGTH * TWO] = 0; + return reinterpret_cast(hash); +} + +std::string GetBufferId(const void* buffer, size_t size) +{ + std::vector dataList; + std::vector sizeList; + + // 模型buffer小于等于1MB,整个模型cache用于计算cache的ID + if (size <= (CACHE_ID_CALCULATE_SIZE + CACHE_ID_CALCULATE_SIZE)) { + dataList.emplace_back(const_cast(buffer)); + sizeList.emplace_back(size); + } else { // 模型buffer大于1M,分别取模型buffer的前0.5MB 和 后0.5MB计算buffer的ID + dataList.emplace_back(const_cast(buffer)); + sizeList.emplace_back(CACHE_ID_CALCULATE_SIZE); + + size_t offset = size - CACHE_ID_CALCULATE_SIZE; + const char* convertBuffer = static_cast(buffer); + char* convertConstBuffer = const_cast(convertBuffer); + dataList.emplace_back(reinterpret_cast(convertConstBuffer + offset)); + sizeList.emplace_back(CACHE_ID_CALCULATE_SIZE); + } + + return Sha256(dataList, sizeList, false); +} + +OH_NN_ReturnCode GetNnrtModelId(Compilation* compilationImpl) +{ + // 模型在线构图场景获取modelID + if (compilationImpl->nnModel != nullptr) { + compilationImpl->nnrtModelID = compilationImpl->compiler->GetOnlineModelID(); + return OH_NN_SUCCESS; + } + + // omc路径加载场景获取modelID + if (compilationImpl->offlineModelPath != nullptr) { + std::string pathStr{compilationImpl->offlineModelPath}; + compilationImpl->nnrtModelID = std::hash{}(pathStr); + return OH_NN_SUCCESS; + } + + // 模型缓存路径加载场景获取modelID if (compilationImpl->cachePath != nullptr) { struct stat buffer; if (stat(compilationImpl->cachePath, &buffer) != 0) { LOGE("GetModelId failed, cachePath is not exit or permission."); return OH_NN_INVALID_PARAMETER; } + + compilationImpl->nnrtModelID = compilationImpl->compiler->GetOnlineModelID(); + return OH_NN_SUCCESS; } - if (compilationImpl->nnModel != nullptr) { - compilationImpl->nnrtModelID = nnrtService.GetNNRtModelIDFromCache(compilationImpl->cachePath, - modelName.c_str()); - if (compilationImpl->nnrtModelID == 1) { - compilationImpl->nnrtModelID = nnrtService.GetNNRtModelIDFromModel(compilationImpl->nnModel); - } - } else if (compilationImpl->offlineModelPath != nullptr) { - compilationImpl->nnrtModelID = nnrtService.GetNNRtModelIDFromPath(compilationImpl->offlineModelPath); - } else if (compilationImpl->cachePath != nullptr) { - compilationImpl->nnrtModelID = - nnrtService.GetNNRtModelIDFromCache(compilationImpl->cachePath, modelName.c_str()); - } else if ((compilationImpl->offlineModelBuffer.first != nullptr) && \ - (compilationImpl->offlineModelBuffer.second != size_t(0))) { - compilationImpl->nnrtModelID = nnrtService.GetNNRtModelIDFromBuffer( - compilationImpl->offlineModelBuffer.first, compilationImpl->offlineModelBuffer.second); - } else if ((compilationImpl->cacheBuffer.first != nullptr) && \ - (compilationImpl->cacheBuffer.second != size_t(0))) { - compilationImpl->nnrtModelID = nnrtService.GetNNRtModelIDFromBuffer( - compilationImpl->cacheBuffer.first, compilationImpl->cacheBuffer.second); - } else { - LOGE("GetModelId failed, no available model to set modelId, please check."); - return OH_NN_INVALID_PARAMETER; + // omc buffer加载场景获取modelID + if ((compilationImpl->offlineModelBuffer.first != nullptr) && + (compilationImpl->offlineModelBuffer.second != size_t(0))) { + std::string bufferSha = GetBufferId(compilationImpl->offlineModelBuffer.first, + compilationImpl->offlineModelBuffer.second); + compilationImpl->nnrtModelID = std::hash{}(bufferSha); + return OH_NN_SUCCESS; } - return OH_NN_SUCCESS; + // 模型缓存buffer场景获取modelID + if ((compilationImpl->cacheBuffer.first != nullptr) && + (compilationImpl->cacheBuffer.second != size_t(0))) { + std::string bufferSha = GetBufferId(compilationImpl->cacheBuffer.first, + compilationImpl->cacheBuffer.second); + compilationImpl->nnrtModelID = std::hash{}(bufferSha); + return OH_NN_SUCCESS; + } + + LOGE("GetModelId failed, no available model to set modelId, please check."); + return OH_NN_INVALID_PARAMETER; } OH_NN_ReturnCode IsCompilationAvaliable(Compilation* compilationImpl) @@ -101,42 +165,48 @@ OH_NN_ReturnCode IsCompilationAvaliable(Compilation* compilationImpl) return OH_NN_SUCCESS; } -OH_NN_ReturnCode CheckModelSize(const Compilation* compilation, NNRtServiceApi& nnrtService, bool& isExceedRamLimit) +OH_NN_ReturnCode GetModelSize(const Compilation* compilation, size_t& modelSize) { - int ret = static_cast(OH_NN_SUCCESS); + // 模型在线构图场景获取modelSize if (compilation->nnModel != nullptr) { - ret = nnrtService.CheckModelSizeFromModel(compilation->nnModel, isExceedRamLimit); - } else if (compilation->offlineModelPath != nullptr) { - ret = nnrtService.CheckModelSizeFromPath(compilation->offlineModelPath, isExceedRamLimit); - } else if (compilation->cachePath != nullptr) { + modelSize = compilation->compiler->GetModelSize(); + return OH_NN_SUCCESS; + } + + // omc路径加载场景获取modelSize + if (compilation->offlineModelPath != nullptr) { + modelSize = compilation->compiler->GetModelSize(); + return OH_NN_SUCCESS; + } + + // 模型缓存路径加载场景获取modelSize + if (compilation->cachePath != nullptr) { struct stat buffer; if (stat(compilation->cachePath, &buffer) != 0) { LOGE("CheckExceedRamLimit failed, cachePath is not exit or permission."); return OH_NN_INVALID_PARAMETER; } - std::string modelName; - compilation->compiler->GetModelName(modelName); - ret = nnrtService.CheckModelSizeFromCache(compilation->cachePath, modelName, isExceedRamLimit); - } else if ((compilation->offlineModelBuffer.first != nullptr) && \ + modelSize = compilation->compiler->GetModelSize(); + return OH_NN_SUCCESS; + } + + // omc buffer加载场景获取modelSize + if ((compilation->offlineModelBuffer.first != nullptr) && (compilation->offlineModelBuffer.second != size_t(0))) { - ret = nnrtService.CheckModelSizeFromBuffer( - compilation->offlineModelBuffer.first, compilation->offlineModelBuffer.second, isExceedRamLimit); - } else if ((compilation->cacheBuffer.first != nullptr) && \ - (compilation->cacheBuffer.second != size_t(0))) { - ret = nnrtService.CheckModelSizeFromBuffer( - compilation->cacheBuffer.first, compilation->cacheBuffer.second, isExceedRamLimit); - } else { - LOGE("CheckExceedRamLimit failed, no available model to check."); - return OH_NN_INVALID_PARAMETER; + modelSize = compilation->offlineModelBuffer.second; + return OH_NN_SUCCESS; } - if (ret != static_cast(OH_NN_SUCCESS)) { - LOGE("CheckExceedRamLimit failed, some error happened when check if model exceed ram limit."); - return OH_NN_INVALID_PARAMETER; + // 模型缓存buffer场景获取modelSize + if ((compilation->cacheBuffer.first != nullptr) && + (compilation->cacheBuffer.second != size_t(0))) { + modelSize = compilation->cacheBuffer.second; + return OH_NN_SUCCESS; } - return OH_NN_SUCCESS; + LOGE("CheckExceedRamLimit failed, no available model to check."); + return OH_NN_INVALID_PARAMETER; } } @@ -591,32 +661,19 @@ OH_NN_ReturnCode CheckExceedRamLimit(const Compilation* compilation, bool& isExc return OH_NN_INVALID_PARAMETER; } - NNRtServiceApi& nnrtService = NNRtServiceApi::GetInstance(); - if (!nnrtService.IsServiceAvaliable()) { - LOGW("CheckExceedRamLimit failed, fail to get nnrt service, skip check exceed ram limit."); - return OH_NN_SUCCESS; - } - - if (nnrtService.CheckModelSizeFromBuffer == nullptr) { - LOGE("CheckExceedRamLimit failed, nnrtService CheckModelSizeFromBuffer func is nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (nnrtService.CheckModelSizeFromModel == nullptr) { - LOGE("CheckExceedRamLimit failed, nnrtService CheckModelSizeFromModel func is nullptr."); + size_t modelSize = 0; + OH_NN_ReturnCode ret = GetModelSize(compilation, modelSize); + if (ret != OH_NN_SUCCESS) { + LOGE("CheckExceedRamLimit failed, fail to get model size."); return OH_NN_INVALID_PARAMETER; } - if (nnrtService.CheckModelSizeFromPath == nullptr) { - LOGE("CheckExceedRamLimit failed, nnrtService CheckModelSizeFromPath func is nullptr."); + if (modelSize == 0) { + LOGE("CheckExceedRamLimit failed, modelSize is 0."); return OH_NN_INVALID_PARAMETER; } - OH_NN_ReturnCode ret = CheckModelSize(compilation, nnrtService, isExceedRamLimit); - if (ret != OH_NN_SUCCESS) { - LOGE("CheckExceedRamLimit failed, fail to check model size."); - return OH_NN_INVALID_PARAMETER; - } + isExceedRamLimit = modelSize > MODEL_MAX_LIMIT ? true : false; return OH_NN_SUCCESS; } @@ -710,28 +767,7 @@ OH_NN_ReturnCode GetModelId(Compilation** compilation) return OH_NN_INVALID_PARAMETER; } - NNRtServiceApi& nnrtService = NNRtServiceApi::GetInstance(); - if (!nnrtService.IsServiceAvaliable()) { - LOGW("GetModelId failed, fail to get nnrt service, skip get modelId."); - return OH_NN_SUCCESS; - } - - if (nnrtService.GetNNRtModelIDFromPath == nullptr) { - LOGE("GetModelId failed, nnrtService GetNNRtModelIDFromPath func is nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (nnrtService.GetNNRtModelIDFromBuffer == nullptr) { - LOGE("GetModelId failed, nnrtService GetNNRtModelIDFromBuffer func is nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - if (nnrtService.GetNNRtModelIDFromModel == nullptr) { - LOGE("GetModelId failed, nnrtService GetNNRtModelIDFromModel func is nullptr."); - return OH_NN_INVALID_PARAMETER; - } - - auto ret = GetNnrtModelId(compilationImpl, nnrtService); + auto ret = GetNnrtModelId(compilationImpl); if (ret != OH_NN_SUCCESS) { LOGE("GetNnrtModelId is failed."); return ret; diff --git a/frameworks/native/neural_network_core/nnrt_client.cpp b/frameworks/native/neural_network_core/nnrt_client.cpp index 94a1338d28ba52ddbe52cd75d747767e884ab7d8..50ef35590fbd12dadad6b1ccac8baa4ad4dee5b0 100644 --- a/frameworks/native/neural_network_core/nnrt_client.cpp +++ b/frameworks/native/neural_network_core/nnrt_client.cpp @@ -57,14 +57,6 @@ NNRtServiceApi& NNRtServiceApi::GetInstance() } } - LoadFunction(libNNRtService, "CheckModelSizeFromPath", &nnrtService.CheckModelSizeFromPath); - LoadFunction(libNNRtService, "CheckModelSizeFromCache", &nnrtService.CheckModelSizeFromCache); - LoadFunction(libNNRtService, "CheckModelSizeFromBuffer", &nnrtService.CheckModelSizeFromBuffer); - LoadFunction(libNNRtService, "CheckModelSizeFromModel", &nnrtService.CheckModelSizeFromModel); - LoadFunction(libNNRtService, "GetNNRtModelIDFromPath", &nnrtService.GetNNRtModelIDFromPath); - LoadFunction(libNNRtService, "GetNNRtModelIDFromCache", &nnrtService.GetNNRtModelIDFromCache); - LoadFunction(libNNRtService, "GetNNRtModelIDFromBuffer", &nnrtService.GetNNRtModelIDFromBuffer); - LoadFunction(libNNRtService, "GetNNRtModelIDFromModel", &nnrtService.GetNNRtModelIDFromModel); LoadFunction(libNNRtService, "SetModelID", &nnrtService.SetModelID); LoadFunction(libNNRtService, "IsSupportAuthentication", &nnrtService.IsSupportAuthentication); LoadFunction(libNNRtService, "IsSupportScheduling", &nnrtService.IsSupportScheduling); diff --git a/frameworks/native/neural_network_core/nnrt_client.h b/frameworks/native/neural_network_core/nnrt_client.h index d39c90d2f60c06ea2a9f70fd75a289e35e67eb2d..68d2cd028090ce7d9e8840e7555467794dc3091b 100644 --- a/frameworks/native/neural_network_core/nnrt_client.h +++ b/frameworks/native/neural_network_core/nnrt_client.h @@ -26,14 +26,6 @@ public: static NNRtServiceApi& GetInstance(); bool IsServiceAvaliable() const; - int (*CheckModelSizeFromPath)(const char* path, bool& exceedLimit) = nullptr; - int (*CheckModelSizeFromCache)(const char* path, const std::string& modelName, bool& exceedLimit) = nullptr; - int (*CheckModelSizeFromBuffer)(const void* buffer, size_t size, bool& exceedLimit) = nullptr; - int (*CheckModelSizeFromModel)(void* model, bool& exceedLimit) = nullptr; - size_t (*GetNNRtModelIDFromPath)(const char*) = nullptr; - size_t (*GetNNRtModelIDFromCache)(const char* path, const char* modelName) = nullptr; - size_t (*GetNNRtModelIDFromBuffer)(const void* buffer, size_t size) = nullptr; - size_t (*GetNNRtModelIDFromModel)(void* model) = nullptr; int (*SetModelID)(uint32_t hiaimodelID, size_t nnrtModelID) = nullptr; int (*IsSupportAuthentication)(bool* supportStat) = nullptr; int (*IsSupportScheduling)(bool* supportStat) = nullptr; diff --git a/frameworks/native/neural_network_runtime/nncompiler.cpp b/frameworks/native/neural_network_runtime/nncompiler.cpp index 0300a8f3daadb6ffc4857e0d615a4d40810328f1..d5d625ee17638003a424a6d6a3e35e8e59547e86 100644 --- a/frameworks/native/neural_network_runtime/nncompiler.cpp +++ b/frameworks/native/neural_network_runtime/nncompiler.cpp @@ -37,6 +37,13 @@ const std::string EXTENSION_KEY_MODEL_NAME = "ModelName"; const std::string EXTENSION_KEY_FM_SHARED = "NPU_FM_SHARED"; const std::string EXTENSION_KEY_IS_EXCEED_RAMLIMIT = "isExceedRamLimit"; constexpr size_t INPUT_OUTPUT_MAX_NUM = 200; +constexpr size_t MORE_MODEL_MAX_LIMIT = 201 * 1024 * 1024; // 201MB +constexpr size_t MODEL_MAX_LIMIT = 200 * 1024 * 1024; // 200MB +constexpr size_t CHECK_SUM_ZERO = 0; +constexpr size_t CHECK_SUM_ONE = 1; +constexpr size_t CHECK_SUM_TWO = 2; +constexpr size_t EXTRACT_NODE_LAYER = 3; +constexpr int32_t MINDSPORE_CONST_NODE_TYPE = 0; struct SerializedTensorDesc { public: @@ -981,5 +988,313 @@ OH_NN_ReturnCode NNCompiler::DeserializedTensorsFromBuffer( ReleaseDescShape(immediateTensorDescs); return ret; } + +size_t NNCompiler::DataTypeSize(mindspore::lite::DataType dataType) +{ + switch (dataType) { + case mindspore::lite::DATA_TYPE_BOOL: + return sizeof(bool); + case mindspore::lite::DATA_TYPE_INT8: + return sizeof(int8_t); + case mindspore::lite::DATA_TYPE_UINT8: + return sizeof(uint8_t); + case mindspore::lite::DATA_TYPE_INT16: + return sizeof(int16_t); + case mindspore::lite::DATA_TYPE_UINT16: + case mindspore::lite::DATA_TYPE_FLOAT16: + return sizeof(uint16_t); + case mindspore::lite::DATA_TYPE_INT32: + return sizeof(int32_t); + case mindspore::lite::DATA_TYPE_UINT32: + return sizeof(uint32_t); + case mindspore::lite::DATA_TYPE_INT64: + return sizeof(int64_t); + case mindspore::lite::DATA_TYPE_UINT64: + return sizeof(uint64_t); + case mindspore::lite::DATA_TYPE_FLOAT32: + return sizeof(float); + case mindspore::lite::DATA_TYPE_FLOAT64: + return sizeof(double); + case mindspore::lite::DATA_TYPE_UNKNOWN: + return 0; + default: + LOGE("Not support the type: %{public}d", dataType); + return 0; + } +} + +size_t NNCompiler::GetFileSize(const char* fileName) +{ + if (fileName == nullptr) { + return 0; + } + + // 这是一个存储文件(夹)信息的结构体,其中有文件大小和创建时间、访问时间、修改时间等 + struct stat statbuf; + + // 提供文件名字符串, 获得文件属性结构体 + stat(fileName, &statbuf); + + // 获取文件大小 + size_t fileSize = static_cast(statbuf.st_size); + + return fileSize; +} + +size_t NNCompiler::GetModelSizeFromModel(InnerModel* innerModel) +{ + auto liteGraph = innerModel->GetLiteGraphs(); + if (liteGraph == nullptr) { + LOGE("GetModelSizeFromModel failed, failed to get liteGraph"); + return 0; + } + + size_t modelSize = 0; + std::vector shape; + mindspore::lite::DataType dtype = mindspore::lite::DATA_TYPE_UNKNOWN; + size_t num = 1; + LOGD("GetOnlineModelSize, all_tensors_size: %{public}zu.", liteGraph->all_tensors_.size()); + for (const auto& tensor : liteGraph->all_tensors_) { + if (tensor == nullptr) { + LOGE("GetmodelSizeFromModel failed, failed to nullptr in model tensor"); + return 0; + } + + // non-const node type, skip + if (mindspore::lite::MindIR_Tensor_GetNodeType(tensor) != MINDSPORE_CONST_NODE_TYPE) { + continue; + } + + shape = mindspore::lite::MindIR_Tensor_GetDims(tensor); + dtype = mindspore::lite::MindIR_Tensor_GetDataType(tensor); + size_t tensorSize = std::accumulate(shape.begin(), shape.end(), num, std::multiplies()); + if ((std::numeric_limits::max() - modelSize) <= tensorSize) { + LOGE("model size exceed max limit size, please check."); + return 0; + } + modelSize += (tensorSize * DataTypeSize(dtype)); + } + + LOGD("GetModelSizeFromModel, modelSize: %{public}zu.", modelSize); + return modelSize; +} + +size_t NNCompiler::GetModelSizeFromFile(std::string& path) +{ + // 读取omc文件大小 + if (path.empty()) { + LOGE("[GetModelSizeFromFile] failed, path is empty."); + return 0; + } + + // 获取模型文件大小 + size_t modelSize = GetFileSize(path.c_str()); + + // 获取权重文件大小 + const std::string& weightPath = path; + struct stat buffer; + if (stat(weightPath.c_str(), &buffer) == 0) { + modelSize += static_cast(buffer.st_size); + } else { + LOGD("[GetModelSizeFromFile] weight file not exists: %{public}s.", weightPath.c_str()); + } + + LOGD("GetModelSizeFromFile, modelSize: %{public}zu.", modelSize); + return modelSize; +} + +size_t NNCompiler::GetModelSizeFromCache(std::string& path, const std::string& modelName) +{ + size_t modelSize = 0; + if (std::filesystem::is_directory(path)) { + if (path.empty()) { + LOGE("GetModelSizeFromCache failed, path is nullptr"); + return 0; + } + + std::string modelPath = path + "/" + modelName + "cache_info.nncache"; + char modelCachePath[PATH_MAX]; + if (realpath(modelPath.c_str(), modelCachePath) == nullptr) { + LOGE("GetModelSizeFromCache failed to get the real path of cacheDir."); + return 0; + } + + std::string cacheInfoPath(modelCachePath); + + // cacheInfoPath is validated outside. + std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary); + if (!infoCacheFile) { + LOGE("[GetModelSizeFromCache] checkCacheInfo failed, error happened when opening cache info file."); + return 0; + } + + std::string content((std::istreambuf_iterator(infoCacheFile)), std::istreambuf_iterator()); + infoCacheFile.close(); + + if (!nlohmann::json::accept(content)) { + LOGE("[GetModelSizeFromCache] checkCacheInfo JSON parse error."); + return 0; + } + + // parse the JSON string + nlohmann::json j = nlohmann::json::parse(content); + + int64_t isExceedRamLimit = -1; + if (j["data"].find("isExceedRamLimit") == j["data"].end()) { + LOGW("[GetModelSizeFromCache] checkCacheInfo read cache isExceedRamLimit failed."); + } + + isExceedRamLimit = j["data"]["isExceedRamLimit"].get(); + modelSize = isExceedRamLimit == 1 ? MORE_MODEL_MAX_LIMIT : MODEL_MAX_LIMIT; + } else { + modelSize = GetModelSizeFromFile(path); + } + return modelSize; +} + +size_t NNCompiler::GetModelSize() +{ + size_t modelSize = 0; + if (m_innerModel != nullptr) { + modelSize = GetModelSizeFromModel(m_innerModel); + } else { + modelSize = GetModelSizeFromCache(m_cachePath, m_extensionConfig.modelName); + } + + return modelSize; +} + +std::vector NNCompiler::GetNodeIndices( + const std::shared_ptr& liteGraph, size_t layer) +{ + std::vector nodes; + size_t inputTensorSize = liteGraph->input_indices_.size(); + size_t outputTensorSize = liteGraph->output_indices_.size(); + + size_t allnodeSize = liteGraph->all_nodes_.size(); + if (((inputTensorSize + outputTensorSize) * layer) >= allnodeSize) { + LOGI("The all node size in model is too small, return all nodes."); + return liteGraph->all_nodes_; + } + + for (size_t i = 0; i < inputTensorSize * layer; ++i) { + nodes.emplace_back(liteGraph->all_nodes_[i]); + } + + for (size_t j = allnodeSize - 1; j >= (allnodeSize - (outputTensorSize * layer)); --j) { + nodes.emplace_back(liteGraph->all_nodes_[j]); + } + + LOGD("nodes size : %{public}zu.", nodes.size()); + return nodes; +} + +size_t NNCompiler::GetOnlineModelID(const std::shared_ptr& liteGraph) +{ + size_t inputSize = liteGraph->input_indices_.size(); + size_t outputSize = liteGraph->output_indices_.size(); + size_t allTensorSize = liteGraph->all_tensors_.size(); + size_t allNodesSize = liteGraph->all_nodes_.size(); + + std::string onlineModelId = ""; + onlineModelId.append(std::to_string(inputSize)); + onlineModelId.append(std::to_string(outputSize)); + onlineModelId.append(std::to_string(allTensorSize)); + onlineModelId.append(std::to_string(allNodesSize)); + + std::vector nodes = GetNodeIndices(liteGraph, EXTRACT_NODE_LAYER); + + for (auto node : nodes) { + onlineModelId.append(node->name_); + } + + return std::hash{}(onlineModelId); +} + +OH_NN_ReturnCode NNCompiler::GetNNRtModelIDFromModel(InnerModel* innerModel, size_t& nnrtModelID) +{ + if (innerModel == nullptr) { + LOGE("GetNNRtModelIDFromModel failed, model is nullptr."); + return OH_NN_INVALID_PARAMETER; + } + + auto liteGraph = innerModel->GetLiteGraphs(); + if (liteGraph == nullptr) { + LOGE("GetNNRtModelIDFromModel failed, failed to get liteGraph."); + return OH_NN_INVALID_PARAMETER; + } + + nnrtModelID = GetOnlineModelID(liteGraph); + return OH_NN_SUCCESS; +} + +OH_NN_ReturnCode NNCompiler::GetNNRtModelIDFromCache(const std::string& path, const std::string& modelName, + size_t& nnrtModelID) +{ + if (path.empty()) { + LOGE("GetNNRtModelIDFromCache failed, path is empty"); + return OH_NN_INVALID_PARAMETER; + } + + if (modelName.empty()) { + LOGE("GetNNRtModelIDFromCache failed, modelName is empty"); + return OH_NN_INVALID_PARAMETER; + } + + if (!std::filesystem::is_directory(path)) { + LOGW("GetNNRtModelIDFromCache cvache path is not directory."); + nnrtModelID = std::hash{}(path); + return OH_NN_SUCCESS; + } + + std::string modelPath = path + "/" + modelName + "cache_info.nncache"; + char modelCachePath[PATH_MAX]; + if (realpath(modelPath.c_str(), modelCachePath) == nullptr) { + LOGE("GetNNRtModelIDFromCache fail to get real path of cacheDir."); + return OH_NN_INVALID_PARAMETER; + } + + NNCompiledCache compiledCache; + NNCompiledCacheInfo cacheInfo; + OH_NN_ReturnCode retCode = compiledCache.SetBackend(m_backendID); + if (retCode != OH_NN_SUCCESS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to set backend."); + return retCode; + } + + retCode = compiledCache.CheckCacheInfo(cacheInfo, modelCachePath); + if (retCode != OH_NN_SUCCESS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to CheckCacheInfo."); + return retCode; + } + + if (cacheInfo.modelCheckSum.size() != NUMBER_CACHE_INFO_MEMBERS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to modelCheckSum."); + return OH_NN_INVALID_PARAMETER; + } + + std::string cacheStr = std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_ZERO]) + + std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_ONE]) + + std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_TWO]); + nnrtModelID = std::hash{}(cacheStr); + + return OH_NN_SUCCESS; +} + +size_t NNCompiler::GetOnlineModelID() +{ + size_t nnrtModeId = 0; + OH_NN_ReturnCode ret = GetNNRtModelIDFromCache(m_cachePath, m_extensionConfig.modelName, nnrtModeId); + if (ret != OH_NN_SUCCESS && m_innerModel != nullptr) { + ret = GetNNRtModelIDFromModel(m_innerModel, nnrtModeId); + } + + if (ret != OH_NN_SUCCESS) { + LOGE("[NNCompiler] GetOnlineModelID failed."); + return 0; + } + + return nnrtModeId; +} } // NeuralNetworkRuntime } // OHOS diff --git a/frameworks/native/neural_network_runtime/nncompiler.h b/frameworks/native/neural_network_runtime/nncompiler.h index e280359fb3a2fa27ce818affa7e585da2ab80d49..3c95f9ed75c5981823a678c54a567a8976eb2080 100644 --- a/frameworks/native/neural_network_runtime/nncompiler.h +++ b/frameworks/native/neural_network_runtime/nncompiler.h @@ -52,6 +52,8 @@ public: OH_NN_ReturnCode SetExtensionConfig(const std::unordered_map>& configs) override; OH_NN_ReturnCode SetOptions(const std::vector>& options) override; OH_NN_ReturnCode GetModelName(std::string& modelName) override; + size_t GetModelSize() override; + size_t GetOnlineModelID() override; NNExecutor* CreateExecutor(); @@ -72,6 +74,18 @@ private: OH_NN_ReturnCode IsSupportedModel(const std::shared_ptr& liteGraph, bool& isSupportedModel) const; + size_t GetModelSizeFromCache(std::string& path, const std::string& modelName); + size_t GetModelSizeFromFile(std::string& path); + size_t GetModelSizeFromModel(InnerModel* innerModel); + OH_NN_ReturnCode GetNNRtModelIDFromCache(const std::string& path, const std::string& modelName, + size_t& nnrtModelID); + OH_NN_ReturnCode GetNNRtModelIDFromModel(InnerModel* innerModel, size_t& nnrtModelID); + size_t GetOnlineModelID(const std::shared_ptr& liteGraph); + std::vector GetNodeIndices( + const std::shared_ptr& liteGraph, size_t layer); + size_t DataTypeSize(mindspore::lite::DataType dataType); + size_t GetFileSize(const char* fileName); + private: bool m_isBuild {false}; bool m_enableFp16 {false}; diff --git a/frameworks/native/neural_network_runtime/nnexecutor.cpp b/frameworks/native/neural_network_runtime/nnexecutor.cpp index 4adb72875739827a8e8bbed8890ddf6edf32fca9..eaae366475074432f2131d57ba55cda7bd42f00b 100644 --- a/frameworks/native/neural_network_runtime/nnexecutor.cpp +++ b/frameworks/native/neural_network_runtime/nnexecutor.cpp @@ -34,6 +34,11 @@ constexpr int AUTOUNLOAD_TIME = 15 * 60 * 1000; namespace NeuralNetworkRuntime { constexpr int CACHE_INPUT_TENSORDESC_OFFSET = 2; constexpr int CACHE_OUTPUT_TENSORDESC_OFFSET = 1; +constexpr size_t CHECK_SUM_ZERO = 0; +constexpr size_t CHECK_SUM_ONE = 1; +constexpr size_t CHECK_SUM_TWO = 2; +constexpr int32_t NUMBER_CACHE_INFO_MEMBERS = 3; + struct SerializedTensorDesc { public: SerializedTensorDesc() = default; @@ -544,8 +549,6 @@ OH_NN_ReturnCode NNExecutor::RunSync(NN_Tensor* inputTensors[], size_t inputSize { uint32_t modelId; GetModelID(modelId); - LOGI("NNExecutor::RunSync pid=%{public}d originHiaiModelId=%{public}d hiaiModelId=%{public}d", - getpid(), m_originHiaiModelId, modelId); m_autoUnloadHandler->RemoveTask("nnexecutor_autounload" + std::to_string(m_executorid)); if (m_inputTensorDescs.size() != inputSize) { LOGE("NNExecutor::RunSync failed, inputSize:%{public}zu is not equal to model input size:%{public}zu", @@ -1508,6 +1511,59 @@ OH_NN_ReturnCode NNExecutor::UnSetDeinitModelCallBack() return OH_NN_SUCCESS; } +OH_NN_ReturnCode NNExecutor::GetNNRtModelIDFromCache(const std::string& path, const std::string& modelName, + size_t& nnrtModelID) +{ + if (path.empty()) { + LOGE("GetNNRtmodelIDFromCache failed, path is empty"); + return OH_NN_INVALID_PARAMETER; + } + + if (modelName.empty()) { + LOGE("GetNNRtmodelIDFromCache failed, modelName is empty"); + return OH_NN_INVALID_PARAMETER; + } + + if (!std::filesystem::is_directory(path)) { + LOGW("GetNNRtmodelIDFromCache cvache path is not directory."); + nnrtModelID = std::hash{}(path); + return OH_NN_SUCCESS; + } + + std::string modelPath = path + "/" + modelName + "cache_info.nncache"; + char modelCachePath[PATH_MAX]; + if (realpath(modelPath.c_str(), modelCachePath) == nullptr) { + LOGE("GetNNRtmodelIDFromCache fail to get real path of cacheDir."); + return OH_NN_INVALID_PARAMETER; + } + + NNCompiledCache compiledCache; + NNCompiledCacheInfo cacheInfo; + OH_NN_ReturnCode retCode = compiledCache.SetBackend(m_backendID); + if (retCode != OH_NN_SUCCESS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to set backend."); + return retCode; + } + + retCode = compiledCache.CheckCacheInfo(cacheInfo, modelCachePath); + if (retCode != OH_NN_SUCCESS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to CheckCacheInfo."); + return retCode; + } + + if (cacheInfo.modelCheckSum.size() != NUMBER_CACHE_INFO_MEMBERS) { + LOGE("GetNNRtmodelIDFromCache failed, fail to modelCheckSum."); + return OH_NN_INVALID_PARAMETER; + } + + std::string cacheStr = std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_ZERO]) + + std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_ONE]) + + std::to_string(cacheInfo.modelCheckSum[CHECK_SUM_TWO]); + nnrtModelID = std::hash{}(cacheStr); + + return OH_NN_SUCCESS; +} + OH_NN_ReturnCode NNExecutor::ReinitScheduling(uint32_t hiaimodelID, bool* needModelLatency, const char* cachePath) { NNRtServiceApi& nnrtService = NNRtServiceApi::GetInstance(); @@ -1521,9 +1577,10 @@ OH_NN_ReturnCode NNExecutor::ReinitScheduling(uint32_t hiaimodelID, bool* needMo return OH_NN_INVALID_PARAMETER; } - size_t nnrtmodelID = nnrtService.GetNNRtModelIDFromCache(m_cachePath.c_str(), m_extensionConfig.modelName.c_str()); - if (nnrtmodelID == 0) { - LOGE("[HiaiExecutorImpl] ReinitScheduling is failed."); + size_t nnrtmodelID = 0; + OH_NN_ReturnCode retCode = GetNNRtModelIDFromCache(m_cachePath, m_extensionConfig.modelName, nnrtmodelID); + if ((retCode != OH_NN_SUCCESS) || (nnrtmodelID == 0)) { + LOGE("[HiaiExecutorImpl] ReinitScheduling is failedm fail to GetNNRtModelIDFromCache."); return OH_NN_INVALID_PARAMETER; } diff --git a/frameworks/native/neural_network_runtime/nnexecutor.h b/frameworks/native/neural_network_runtime/nnexecutor.h index 3ec2799b83715f9e305cca370b8a034151d31435..a04e9b0d23f61c5bf3c1fdef850316a5cfd7fe8e 100644 --- a/frameworks/native/neural_network_runtime/nnexecutor.h +++ b/frameworks/native/neural_network_runtime/nnexecutor.h @@ -108,6 +108,8 @@ private: OH_NN_ReturnCode Reload(); OH_NN_ReturnCode ReinitScheduling(uint32_t hiaimodelID, bool* needModelLatency, const char* cachePath); OH_NN_ReturnCode DeinitScheduling(uint32_t hiaimodelID); + OH_NN_ReturnCode GetNNRtModelIDFromCache(const std::string& path, const std::string& modelName, + size_t& nnrtModelID); private: size_t m_backendID {0};