From 9b64eadcb6f007f7cc17b228b87a852ca9771342 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 13 Mar 2020 18:33:27 +0300 Subject: [PATCH] dnn(ie): separate IECore for different devices - HETERO plugin doesn't switch well between devices --- modules/dnn/src/dnn.cpp | 6 ++-- modules/dnn/src/ie_ngraph.cpp | 2 +- modules/dnn/src/op_inf_engine.cpp | 46 ++++++++++++++++++++----------- modules/dnn/src/op_inf_engine.hpp | 2 +- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 67ca61d9bb..0f8dacad35 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -108,7 +108,7 @@ public: { #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R3) // Lightweight detection - const std::vector devices = getCore().GetAvailableDevices(); + const std::vector devices = getCore("").GetAvailableDevices(); for (std::vector::const_iterator i = devices.begin(); i != devices.end(); ++i) { if (std::string::npos != i->find("MYRIAD") && target == DNN_TARGET_MYRIAD) @@ -3253,7 +3253,7 @@ Net Net::readFromModelOptimizer(const String& xml, const String& bin) InferenceEngine::CNNNetwork ieNet = reader.getNetwork(); #else - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore(""); InferenceEngine::CNNNetwork ieNet = ie.ReadNetwork(xml, bin); #endif @@ -3302,7 +3302,7 @@ Net Net::readFromModelOptimizer( InferenceEngine::CNNNetwork ieNet = reader.getNetwork(); #else - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore(""); std::string model; model.assign((char*)bufferModelConfigPtr, bufferModelConfigSize); diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index 55ba9377a0..f0975d05a0 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -524,7 +524,7 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) try { AutoLock lock(getInitializationMutex()); - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore(device_name); { isInit = true; std::vector candidates; diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index 9c74032a33..047292fda8 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -604,18 +604,31 @@ static bool init_IE_plugins() (void)init_core->GetAvailableDevices(); return true; } -static InferenceEngine::Core& create_IE_Core_instance() +static InferenceEngine::Core& retrieveIECore(const std::string& id, std::map >& cores) { - static InferenceEngine::Core core; - return core; + AutoLock lock(getInitializationMutex()); + std::map >::iterator i = cores.find(id); + if (i == cores.end()) + { + std::shared_ptr core = std::make_shared(); + cores[id] = core; + return *core.get(); + } + return *(i->second).get(); } -static InferenceEngine::Core& create_IE_Core_pointer() +static InferenceEngine::Core& create_IE_Core_instance(const std::string& id) +{ + static std::map > cores; + return retrieveIECore(id, cores); +} +static InferenceEngine::Core& create_IE_Core_pointer(const std::string& id) { // load and hold IE plugins - static InferenceEngine::Core* core = new InferenceEngine::Core(); // 'delete' is never called - return *core; + static std::map >* cores = + new std::map >(); + return retrieveIECore(id, *cores); } -InferenceEngine::Core& getCore() +InferenceEngine::Core& getCore(const std::string& id) { // to make happy memory leak tools use: // - OPENCV_DNN_INFERENCE_ENGINE_HOLD_PLUGINS=0 @@ -631,9 +644,10 @@ InferenceEngine::Core& getCore() false #endif ); - static InferenceEngine::Core& core = param_DNN_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND - ? create_IE_Core_pointer() - : create_IE_Core_instance(); + + InferenceEngine::Core& core = param_DNN_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND + ? create_IE_Core_pointer(id) + : create_IE_Core_instance(id); return core; } #endif @@ -641,9 +655,10 @@ InferenceEngine::Core& getCore() #if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT) static bool detectMyriadX_() { + AutoLock lock(getInitializationMutex()); #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R3) // Lightweight detection - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore("MYRIAD"); const std::vector devices = ie.GetAvailableDevices(); for (std::vector::const_iterator i = devices.begin(); i != devices.end(); ++i) { @@ -687,7 +702,6 @@ static bool detectMyriadX_() #if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1) InferenceEngine::InferenceEnginePluginPtr enginePtr; { - AutoLock lock(getInitializationMutex()); auto& sharedPlugins = getSharedPlugins(); auto pluginIt = sharedPlugins.find("MYRIAD"); if (pluginIt != sharedPlugins.end()) { @@ -706,9 +720,9 @@ static bool detectMyriadX_() try { #if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3) - auto netExec = getCore().LoadNetwork(cnn, "MYRIAD", {{"VPU_PLATFORM", "VPU_2480"}}); + auto netExec = getCore("MYRIAD").LoadNetwork(cnn, "MYRIAD", {{"VPU_PLATFORM", "VPU_2480"}}); #else - auto netExec = getCore().LoadNetwork(cnn, "MYRIAD", {{"VPU_MYRIAD_PLATFORM", "VPU_MYRIAD_2480"}}); + auto netExec = getCore("MYRIAD").LoadNetwork(cnn, "MYRIAD", {{"VPU_MYRIAD_PLATFORM", "VPU_MYRIAD_2480"}}); #endif #endif auto infRequest = netExec.CreateInferRequest(); @@ -739,7 +753,7 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net) } else #else - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore(device_name); #endif { #if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1) @@ -1124,7 +1138,7 @@ void resetMyriadDevice() getSharedPlugins().erase("MYRIAD"); #else // Unregister both "MYRIAD" and "HETERO:MYRIAD,CPU" plugins - InferenceEngine::Core& ie = getCore(); + InferenceEngine::Core& ie = getCore("MYRIAD"); try { ie.UnregisterPlugin("MYRIAD"); diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index 5b37c4dbf0..54bc76941b 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -245,7 +245,7 @@ bool isMyriadX(); CV__DNN_EXPERIMENTAL_NS_END -InferenceEngine::Core& getCore(); +InferenceEngine::Core& getCore(const std::string& id); template static inline std::vector getShape(const Mat& mat)