diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index a671501749..0cc53926e8 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1082,17 +1082,26 @@ static Ptr wrapMat(int backendId, int targetId, cv::Mat& m) static int g_networkId = 0; -struct Net::Impl +detail::NetImplBase::NetImplBase() + : networkId(CV_XADD(&g_networkId, 1)) + , networkDumpCounter(0) + , dumpLevel(DNN_NETWORK_DUMP) +{ + // nothing +} + +std::string detail::NetImplBase::getDumpFileNameBase() +{ + std::string dumpFileNameBase = cv::format("ocv_dnn_net_%05d_%02d", networkId, networkDumpCounter++); + return dumpFileNameBase; +} + +struct Net::Impl : public detail::NetImplBase { typedef std::map LayersShapesMap; typedef std::map MapIdToLayerData; - const int networkId; // network global identifier - int networkDumpCounter; // dump counter - Impl() - : networkId(CV_XADD(&g_networkId, 1)) - , networkDumpCounter(0) { //allocate fake net input layer netInputLayer = Ptr(new DataLayer()); @@ -1256,7 +1265,7 @@ struct Net::Impl { CV_TRACE_FUNCTION(); - if (DNN_NETWORK_DUMP > 0 && networkDumpCounter == 0) + if (dumpLevel && networkDumpCounter == 0) { dumpNetworkToFile(); } @@ -1339,7 +1348,7 @@ struct Net::Impl netWasAllocated = true; - if (DNN_NETWORK_DUMP > 0) + if (dumpLevel) { dumpNetworkToFile(); } @@ -2043,7 +2052,7 @@ struct Net::Impl } if (net.empty()) { - net = Ptr(new InfEngineNgraphNet()); + net = Ptr(new InfEngineNgraphNet(*this)); } if (!fused) { @@ -2087,7 +2096,7 @@ struct Net::Impl } } else { - net = Ptr(new InfEngineNgraphNet()); + net = Ptr(new InfEngineNgraphNet(*this)); } if (!fused) @@ -3126,7 +3135,8 @@ struct Net::Impl void dumpNetworkToFile() { #ifndef OPENCV_DNN_DISABLE_NETWORK_AUTO_DUMP - String dumpFileName = cv::format("ocv_dnn_net_%05d_%02d.dot", networkId, networkDumpCounter++); + string dumpFileNameBase = getDumpFileNameBase(); + string dumpFileName = dumpFileNameBase + ".dot"; try { string dumpStr = dump(); @@ -3185,7 +3195,7 @@ Net Net::Impl::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNe { auto fake_node = std::make_shared(ngraph::element::f32, ngraph::Shape{}); Ptr backendNodeNGraph(new InfEngineNgraphNode(fake_node)); - backendNodeNGraph->net = Ptr(new InfEngineNgraphNet(ieNet)); + backendNodeNGraph->net = Ptr(new InfEngineNgraphNet(*(cvNet.impl), ieNet)); backendNode = backendNodeNGraph; } else diff --git a/modules/dnn/src/dnn_common.hpp b/modules/dnn/src/dnn_common.hpp new file mode 100644 index 0000000000..cd6cea0c6b --- /dev/null +++ b/modules/dnn/src/dnn_common.hpp @@ -0,0 +1,34 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef __OPENCV_DNN_COMMON_HPP__ +#define __OPENCV_DNN_COMMON_HPP__ + +#include + +namespace cv { namespace dnn { +CV__DNN_EXPERIMENTAL_NS_BEGIN +#define IS_DNN_OPENCL_TARGET(id) (id == DNN_TARGET_OPENCL || id == DNN_TARGET_OPENCL_FP16) +Mutex& getInitializationMutex(); +void initializeLayerFactory(); + +namespace detail { + +struct NetImplBase +{ + const int networkId; // network global identifier + int networkDumpCounter; // dump counter + int dumpLevel; // level of information dumps (initialized through OPENCV_DNN_NETWORK_DUMP parameter) + + NetImplBase(); + + std::string getDumpFileNameBase(); +}; + +} // namespace detail + +CV__DNN_EXPERIMENTAL_NS_END +}} // namespace + +#endif // __OPENCV_DNN_COMMON_HPP__ diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index 05e8205251..cf94500a8c 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -6,6 +6,9 @@ // Third party copyrights are property of their respective owners. #include "precomp.hpp" + +#include + #include "ie_ngraph.hpp" #include @@ -22,6 +25,8 @@ namespace cv { namespace dnn { #ifdef HAVE_DNN_NGRAPH +static bool DNN_IE_SERIALIZE = utils::getConfigurationParameterBool("OPENCV_DNN_IE_SERIALIZE", false); + // For networks with input layer which has an empty name, IE generates a name id[some_number]. // OpenCV lets users use an empty input name and to prevent unexpected naming, // we can use some predefined name. @@ -295,13 +300,16 @@ void InfEngineNgraphNode::setName(const std::string& name) { node->set_friendly_name(name); } -InfEngineNgraphNet::InfEngineNgraphNet() +InfEngineNgraphNet::InfEngineNgraphNet(detail::NetImplBase& netImpl) + : netImpl_(netImpl) { hasNetOwner = false; device_name = "CPU"; } -InfEngineNgraphNet::InfEngineNgraphNet(InferenceEngine::CNNNetwork& net) : cnn(net) +InfEngineNgraphNet::InfEngineNgraphNet(detail::NetImplBase& netImpl, InferenceEngine::CNNNetwork& net) + : netImpl_(netImpl) + , cnn(net) { hasNetOwner = true; device_name = "CPU"; @@ -440,9 +448,27 @@ void InfEngineNgraphNet::init(Target targetId) ngraph_function->validate_nodes_and_infer_types(); } cnn = InferenceEngine::CNNNetwork(ngraph_function); -#ifdef _DEBUG // TODO - //cnn.serialize("/tmp/cnn.xml", "/tmp/cnn.bin"); + + if (DNN_IE_SERIALIZE) + { +#ifndef OPENCV_DNN_DISABLE_NETWORK_AUTO_DUMP + std::string dumpFileNameBase = netImpl_.getDumpFileNameBase(); + try + { + cnn.serialize(dumpFileNameBase + "_ngraph.xml", dumpFileNameBase + "_ngraph.bin"); + } + catch (const std::exception& e) + { + std::ofstream out((dumpFileNameBase + "_ngraph.error").c_str(), std::ios::out); + out << "Exception: " << e.what() << std::endl; + } + catch (...) + { + std::ofstream out((dumpFileNameBase + "_ngraph.error").c_str(), std::ios::out); + out << "Can't dump: unknown exception" << std::endl; + } #endif + } } switch (targetId) diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index efbdafa7d9..7a8c4bef8d 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -34,8 +34,8 @@ class InfEngineNgraphNode; class InfEngineNgraphNet { public: - InfEngineNgraphNet(); - InfEngineNgraphNet(InferenceEngine::CNNNetwork& net); + InfEngineNgraphNet(detail::NetImplBase& netImpl); + InfEngineNgraphNet(detail::NetImplBase& netImpl, InferenceEngine::CNNNetwork& net); void addOutput(const std::string& name); @@ -55,6 +55,8 @@ public: void reset(); private: + detail::NetImplBase& netImpl_; + void release(); int getNumComponents(); void dfs(std::shared_ptr& node, std::vector>& comp, diff --git a/modules/dnn/src/precomp.hpp b/modules/dnn/src/precomp.hpp index f6230c4c6d..62f8714af1 100644 --- a/modules/dnn/src/precomp.hpp +++ b/modules/dnn/src/precomp.hpp @@ -61,11 +61,4 @@ #include #include - -namespace cv { namespace dnn { -CV__DNN_EXPERIMENTAL_NS_BEGIN -#define IS_DNN_OPENCL_TARGET(id) (id == DNN_TARGET_OPENCL || id == DNN_TARGET_OPENCL_FP16) -Mutex& getInitializationMutex(); -void initializeLayerFactory(); -CV__DNN_EXPERIMENTAL_NS_END -}} // namespace +#include "dnn_common.hpp"