diff options
author | Inki Dae <inki.dae@samsung.com> | 2021-03-18 21:04:25 +0900 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2021-03-24 12:41:28 +0900 |
commit | d0d92d064e3b2ddccf66eb1e4f6913ccacc7d10c (patch) | |
tree | 8d280e653aedead74d9cc68867eedc56713d90ce | |
parent | c1b6cab12c8cbf6b4292d3b6be814214f54bba0f (diff) | |
download | inference-engine-interface-d0d92d064e3b2ddccf66eb1e4f6913ccacc7d10c.tar.gz inference-engine-interface-d0d92d064e3b2ddccf66eb1e4f6913ccacc7d10c.tar.bz2 inference-engine-interface-d0d92d064e3b2ddccf66eb1e4f6913ccacc7d10c.zip |
Apply a new policy for inference engine backend path
This patch applies a new policy for inference engine backend path.
Inference engine interface framework has a role to decide which inference
engine API framework - internal or ML Single API - will be used according
to user desired inference requests.
In runtime, inference engine interface framework loads ini file -
/etc/inference/inference_engine_backend_path.ini - and parse it
to check which API framework current Platform wants to use for a given
backend.
So this patch applies below role according to user desired inference requests.
User INI configuration file API framework
---------------------------------------------------------------
ONE - MLAPI
MLAPI - MLAPI
CUSTOM device(NPU) - MLAPI
ARMNN - Internal
ARMNN MLAPI MLAPI
TFLITE - Internal
TFLITE MLAPI MLAPI
OPENCV - Internal
--------------------------------------------------------------
Legends
-------
- : nothing declared.
Internal : internal plugin will be used.
MLAPI : ML Single API will be used.
Change-Id: If2f310171671e911717792538cc6977c46f2bcd8
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | include/inference_engine_common_impl.h | 7 | ||||
-rw-r--r-- | src/inference_engine_common_impl.cpp | 178 |
2 files changed, 126 insertions, 59 deletions
diff --git a/include/inference_engine_common_impl.h b/include/inference_engine_common_impl.h index c927ee6..3c09b02 100644 --- a/include/inference_engine_common_impl.h +++ b/include/inference_engine_common_impl.h @@ -23,6 +23,7 @@ #include "inference_engine_common.h" #include "inference_engine_type.h" #include "inference_engine_common_profiler.h" +#include <iniparser.h> using namespace InferenceEngineInterface::Profiler; @@ -245,6 +246,9 @@ namespace Common int DumpProfileToFile(const std::string filename = "dump.txt"); private: + int UseMLAPI(const int backend_type, const int device_type); + int GetApiFrameworkType(dictionary *dict, const char *section_name); + int GetNpuBackendType(dictionary *dict, const char *section_name); int InitBackendEngine(const std::string &backend_path, int backend_type, int device_type); int CheckTensorBuffers( @@ -258,9 +262,6 @@ namespace Common // In default, we use profiler. bool mUseProfiler; unsigned int mProfilerDumpType; - // 0 : default tensor filter type for MLAPI with CPU and GPU. - // 1 : default tensor filter type for MLAPI with NPU. - uint32_t mDefault_MLAPI_Backend[2]; protected: void *mBackendModule; diff --git a/src/inference_engine_common_impl.cpp b/src/inference_engine_common_impl.cpp index d1997a9..9eee40f 100644 --- a/src/inference_engine_common_impl.cpp +++ b/src/inference_engine_common_impl.cpp @@ -24,7 +24,6 @@ #include <time.h> #include <dlfcn.h> #include <experimental/filesystem> -#include <iniparser.h> extern "C" { @@ -48,8 +47,29 @@ namespace InferenceEngineInterface { namespace Common { - const char *INFERENCE_MLAPI_INI_FILENAME = - "/etc/inference/inference_engine_mlapi_backend.ini"; + const char *BACKEND_PATH_INI_FILENAME = + "/etc/inference/inference_engine_backend_path.ini"; + std::map<std::string, inference_backend_type_e> sApiFw = + { + { "MLAPI", INFERENCE_BACKEND_MLAPI } + }; + + std::map<std::string, inference_backend_type_e> sBackend = + { + { "TFLITE", INFERENCE_BACKEND_TFLITE }, + { "ARMNN", INFERENCE_BACKEND_ARMNN }, + { "ONE", INFERENCE_BACKEND_ONE }, + { "OPENCV", INFERENCE_BACKEND_OPENCV } + }; + + std::map<std::string, inference_backend_npu_type_e> sNpuBackend = + { + { "VIVANTE", INFERENCE_BACKEND_NPU_VIVANTE }, + { "TRIV2", INFERENCE_BACKEND_NPU_TRIV2} + }; + + int sApiFwForTFLITE = -1, sApiFwForARMNN = -1, sApiFwForOPENCV = -1; + int sBackendForNpu = -1; InferenceEngineCommon::InferenceEngineCommon() : mSelectedBackendEngine(INFERENCE_BACKEND_NONE), @@ -74,71 +94,98 @@ namespace Common LOGW("LEAVE"); } + int InferenceEngineCommon::UseMLAPI(const int backend_type, const int device_type) + { + if (backend_type == INFERENCE_BACKEND_MLAPI || + device_type == INFERENCE_TARGET_CUSTOM || + backend_type == INFERENCE_BACKEND_ONE || + (backend_type == INFERENCE_BACKEND_TFLITE && sApiFwForTFLITE == INFERENCE_BACKEND_MLAPI) || + (backend_type == INFERENCE_BACKEND_ARMNN && sApiFwForARMNN == INFERENCE_BACKEND_MLAPI)) + return 1; + + return 0; + } + + int InferenceEngineCommon::GetNpuBackendType(dictionary *dict, const char *section_name) + { + // Parse a backend path for NPU device. + const char *parsed_str = iniparser_getstring(dict, section_name, NULL); + if (parsed_str == NULL) { + LOGI("No type parsed for %s section name.", section_name); + return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; + } + + std::map<std::string, inference_backend_npu_type_e>::iterator it = sNpuBackend.find(parsed_str); + if (it == sNpuBackend.end()) { + LOGE("Invalid NPU backend name."); + return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; + } + + return it->second; + } + + int InferenceEngineCommon::GetApiFrameworkType(dictionary *dict, const char *section_name) + { + // Parse a backend path for NPU device. + const char *parsed_str = iniparser_getstring(dict, section_name, NULL); + if (parsed_str == NULL) { + LOGI("No type parsed for %s section name.", section_name); + return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; + } + + std::map<std::string, inference_backend_type_e>::iterator it = sApiFw.find(parsed_str); + if (it == sApiFw.end()) { + LOGE("Invalid API framework name."); + return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; + } + + return it->second; + } + int InferenceEngineCommon::LoadConfigFile(std::string ini_file_path) { int ret = INFERENCE_ENGINE_ERROR_NONE; - int npu_type = -1, cpu_and_gpu_type = -1; - char *default_type_for_npu = NULL, *default_type_for_cpu_gpu = NULL; + std::string strNpuBackend = "", strApiFwName = ""; if (ini_file_path.empty()) - ini_file_path = INFERENCE_MLAPI_INI_FILENAME; + ini_file_path = BACKEND_PATH_INI_FILENAME; LOGI("%s configuration file will be used.\n", ini_file_path.c_str()); dictionary *dict = iniparser_load(ini_file_path.c_str()); if (dict == NULL) { - LOGE("Fail to load %s file.\n", ini_file_path.c_str()); + LOGW("Fail to load %s file.\n", ini_file_path.c_str()); + LOGW("so it will not use default backend path.\n"); return INFERENCE_ENGINE_ERROR_INVALID_OPERATION; } - default_type_for_npu = (char *)iniparser_getstring(dict, - "inference mlapi npu backend:default tensor filter type", - NULL); - if (default_type_for_npu == NULL) { - LOGE("Fail to load default tensor filter type for MLAPI with NPU."); - ret = INFERENCE_ENGINE_ERROR_INVALID_OPERATION; - goto out; + sBackendForNpu = GetNpuBackendType(dict, "NPU backend:type"); + if (sBackendForNpu < 0) { + LOGI("No NPU backend type from ini file."); + LOGI("This platform cannot use NPU acceleration for inference."); } - default_type_for_cpu_gpu = (char *)iniparser_getstring(dict, - "inference mlapi cpu and gpu backend:default tensor filter type", - NULL); - if (default_type_for_cpu_gpu == NULL) { - LOGE("Fail to load default tensor filter type for MLAPI with CPU and GPU."); - ret = INFERENCE_ENGINE_ERROR_INVALID_OPERATION; - goto out; - } + LOGI("API FW = %s, NPU = %d", sBackendForNpu > 0 ? "MLAPI" : "Internal", sBackendForNpu); - npu_type = atoi(default_type_for_npu); - cpu_and_gpu_type = atoi(default_type_for_cpu_gpu); - - // Check if loaded configuration value is valid or not. - if (npu_type != INFERENCE_BACKEND_NPU_VIVANTE && - npu_type != INFERENCE_BACKEND_NPU_TRIV2) { - LOGE("Invalid tensor filter type for MLAPI with NPU."); - ret = INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; - goto out; + sApiFwForTFLITE = GetApiFrameworkType(dict, "TFLITE:API framework"); + if (sApiFwForTFLITE < 0) { + LOGI("No API framework type from ini file."); + LOGI("So in default, internal API will be used for TFLITE."); } - if (cpu_and_gpu_type != INFERENCE_BACKEND_TFLITE) { - LOGE("Invalid tensor filter type for MLAPI with CPU and GPU."); - ret = INFERENCE_ENGINE_ERROR_INVALID_PARAMETER; - goto out; - } + LOGI("API FW = %s for TFLITE.", sApiFwForTFLITE > 0 ? "MLAPI" : "Internal"); - LOGI("npu = %d, gpu = %d", npu_type, cpu_and_gpu_type); + sApiFwForARMNN = GetApiFrameworkType(dict, "ARMNN:API framework"); + if (sApiFwForARMNN < 0) { + LOGI("No API framework type from ini file."); + LOGI("So in default, internal API will be used for ARMNN."); + } - // TODO. Update mDefault_MLAPI_Backend type using ini config file. - // 0 : default tensor filter type for MLAPI with CPU and GPU. - // 1 : default tensor filter type for MLAPI with NPU. - mDefault_MLAPI_Backend[0] = cpu_and_gpu_type; - mDefault_MLAPI_Backend[1] = npu_type; + LOGI("API FW = %s for ARMNN.", sApiFwForARMNN > 0 ? "MLAPI" : "Internal"); -out: iniparser_freedict(dict); return ret; - } int InferenceEngineCommon::CheckTensorBuffers( @@ -281,16 +328,20 @@ out: LOGI("backend_type = %d, device_type = %d", backend_type, device_type); - // Update tensor filter type for MLAPI if a given backend type is MLAPI. - if (backend_type == INFERENCE_BACKEND_MLAPI) { - if (device_type & (INFERENCE_TARGET_CPU | INFERENCE_TARGET_GPU)) - backend_type = mDefault_MLAPI_Backend[0]; - if (device_type & INFERENCE_TARGET_CUSTOM) - backend_type = mDefault_MLAPI_Backend[1]; - - LOGI("tensor filter type is %d\n", backend_type); + // If user set MLAPI type as backend type and device type is CPU or GPU + // then TFLITE tensor filter of NNStreamer will be used in default. + if (backend_type == INFERENCE_BACKEND_MLAPI && + (device_type & INFERENCE_TARGET_CPU || device_type & INFERENCE_TARGET_GPU)) { + backend_type = INFERENCE_BACKEND_TFLITE; + LOGI("API framework is MLAPI with TFLITE tensor filter.\n"); } + // If NPU type is declared in ini file then pass the type to + // a given inference engine backend. + if (backend_type == INFERENCE_BACKEND_MLAPI && + device_type == INFERENCE_TARGET_CUSTOM && sBackendForNpu > 0) + backend_type = sBackendForNpu; + int ret = mBackendHandle->SetPrivateData(&backend_type); if (ret != INFERENCE_ENGINE_ERROR_NONE) { LOGE("Failed to set a tensor filter plugin type for MLAPI."); @@ -325,9 +376,6 @@ out: mProfiler.Start(IE_PROFILER_MEMORY); } - std::string backendLibName = - "libinference-engine-" + config->backend_name + ".so"; - // If backend_type of config is -1 then update it according to backend_name. if (config->backend_type == -1) { std::map<std::string,int> BackendTable; @@ -340,6 +388,15 @@ out: config->backend_type = BackendTable.find(config->backend_name)->second; } + std::string backendLibName; + + // For two backend types - MLAPI and ONE, MLAPI will be used as API framework in default. + // And for all NPU devices passed with INFERENCE_TARGET_CUSTOM type, MLAPI will be used as API framework in default. + if (UseMLAPI(config->backend_type, config->target_devices)) + backendLibName = "libinference-engine-mlapi.so"; + else + backendLibName = "libinference-engine-" + config->backend_name + ".so"; + int ret = InitBackendEngine(backendLibName, config->backend_type, config->target_devices); if (ret != INFERENCE_ENGINE_ERROR_NONE) { return ret; @@ -387,8 +444,17 @@ out: [INFERENCE_BACKEND_ONE] = "mlapi" }; + int api_fw_type; + + // For two backend types - MLAPI and ONE, MLAPI will be used as API framework in default. + // And for all NPU devices passed with INFERENCE_TARGET_CUSTOM type, MLAPI will be used as API framework in default. + if (UseMLAPI(backend_type, device_type)) + api_fw_type = INFERENCE_BACKEND_MLAPI; + else + api_fw_type = backend_type; + std::string backendLibName = - "libinference-engine-" + backendNameTable[backend_type] + ".so"; + "libinference-engine-" + backendNameTable[api_fw_type] + ".so"; int ret = InitBackendEngine(backendLibName, backend_type, device_type); if (ret != INFERENCE_ENGINE_ERROR_NONE) { |