diff --git a/modules/gapi/samples/pipeline_modeling_tool.cpp b/modules/gapi/samples/pipeline_modeling_tool.cpp index 07934756cc..ca6187e1ca 100644 --- a/modules/gapi/samples/pipeline_modeling_tool.cpp +++ b/modules/gapi/samples/pipeline_modeling_tool.cpp @@ -379,10 +379,15 @@ int main(int argc, char* argv[]) { } // NB: Execute pipelines + std::vector eptrs(pipelines.size(), nullptr); std::vector threads(pipelines.size()); for (size_t i = 0; i < pipelines.size(); ++i) { threads[i] = std::thread([&, i]() { - pipelines[i]->run(work_time_ms); + try { + pipelines[i]->run(work_time_ms); + } catch (...) { + eptrs[i] = std::current_exception(); + } }); } @@ -393,12 +398,22 @@ int main(int argc, char* argv[]) { for (size_t i = 0; i < threads.size(); ++i) { threads[i].join(); + } + + for (size_t i = 0; i < threads.size(); ++i) { + if (eptrs[i] != nullptr) { + try { + std::rethrow_exception(eptrs[i]); + } catch (std::exception& e) { + throw std::logic_error(pipelines[i]->name() + " failed: " + e.what()); + } + } if (file.is_open()) { file << pipelines[i]->report().toStr(true) << std::endl; } std::cout << pipelines[i]->report().toStr() << std::endl; } - } catch (std::exception& e) { + } catch (const std::exception& e) { std::cout << e.what() << std::endl; throw; } diff --git a/modules/gapi/samples/pipeline_modeling_tool/pipeline.hpp b/modules/gapi/samples/pipeline_modeling_tool/pipeline.hpp index c0f2c02948..2951d45610 100644 --- a/modules/gapi/samples/pipeline_modeling_tool/pipeline.hpp +++ b/modules/gapi/samples/pipeline_modeling_tool/pipeline.hpp @@ -46,6 +46,7 @@ public: void compile(); void run(double work_time_ms); const PerfReport& report() const; + const std::string& name() const { return m_name;} virtual ~Pipeline() = default; diff --git a/modules/gapi/src/backends/ie/giebackend.cpp b/modules/gapi/src/backends/ie/giebackend.cpp index 39ba9a4041..b155ff0aea 100644 --- a/modules/gapi/src/backends/ie/giebackend.cpp +++ b/modules/gapi/src/backends/ie/giebackend.cpp @@ -2,7 +2,7 @@ // 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. // -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2018-2022 Intel Corporation #include "precomp.hpp" @@ -216,6 +216,39 @@ inline void copyFromIE(const IE::Blob::Ptr &blob, MatType &mat) { } } +template +void checkLayerNames(const MapT& network_map, + const std::vector& layer_names, + const std::string& layer_type) { + for (const auto& layer_name : layer_names) { + const auto it = network_map.find(layer_name); + if (it == network_map.end()) { + std::stringstream ss; + ss << "Failed to find " << layer_type << " layer with name: " + << "\"" << layer_name << "\"" << std::endl; + ss << "Network " << layer_type << " layers: " << std::endl; + for (const auto& p : network_map) { + const auto& desc = p.second->getTensorDesc(); + ss << p.first << " : " << desc.getPrecision() + << " / " << desc.getLayout() << std::endl; + } + throw std::logic_error(ss.str()); + } + } +} + +template +void checkInputLayerNames(const MapT& network_map, + const std::vector& layer_names) { + checkLayerNames(network_map, layer_names, "input"); +} + +template +void checkOutputLayerNames(const MapT& network_map, + const std::vector& layer_names) { + checkLayerNames(network_map, layer_names, "output"); +} + // IE-specific metadata, represents a network with its parameters struct IEUnit { static const char *name() { return "IEModelConfig"; } @@ -293,6 +326,16 @@ struct IEUnit { params.num_in && "Number of layers to reshape must be less than or equal to number of inputs"); } + + if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) { + checkInputLayerNames(net.getInputsInfo(), params.input_names); + checkOutputLayerNames(net.getOutputsInfo(), params.output_names); + } else if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import) { + checkInputLayerNames(this_network.GetInputsInfo(), params.input_names); + checkOutputLayerNames(this_network.GetOutputsInfo(), params.output_names); + } else { + cv::util::throw_error(std::logic_error("Unsupported ParamDesc::Kind")); + } } // This method is [supposed to be] called at Island compilation stage @@ -627,7 +670,10 @@ public: void waitAll(); private: - void callback(Task task, InferenceEngine::InferRequest& request, size_t id); + void callback(Task task, + size_t id, + IE::InferRequest request, + IE::StatusCode code); void setup(); QueueClass m_idle_ids; @@ -652,21 +698,38 @@ void cv::gimpl::ie::RequestPool::execute(cv::gimpl::ie::RequestPool::Task&& t) { auto& request = m_requests[id]; + using namespace std::placeholders; + using callback_t = std::function; request.SetCompletionCallback( - std::bind(&cv::gimpl::ie::RequestPool::callback, this, t, std::ref(request), id)); + static_cast( + std::bind(&cv::gimpl::ie::RequestPool::callback, this, + t, id, _1, _2))); t.run(request); } void cv::gimpl::ie::RequestPool::callback(cv::gimpl::ie::RequestPool::Task task, - InferenceEngine::InferRequest& request, - size_t id) { - task.callback(request); - // NB: IE::InferRequest keeps the callback until the new one is set. - // Since user's callback might keep resources that should be released, - // need to destroy its after execution. - // Let's set the empty one to cause the destruction of a callback. - request.SetCompletionCallback([](){}); - m_idle_ids.push(id); + size_t id, + IE::InferRequest request, + IE::StatusCode code) { + // FIXME: Any exception which is arrised here must not leave this callback, + // because it won't be handled. + try { + if (code != IE::StatusCode::OK) { + throw std::logic_error("IE::InferRequest finished with not OK status"); + } + task.callback(request); + // NB: IE::InferRequest keeps the callback until the new one is set. + // Since user's callback might keep resources that should be released, + // need to destroy its after execution. + // Let's set the empty one to cause the destruction of a callback. + request.SetCompletionCallback([](){}); + m_idle_ids.push(id); + } catch (const std::exception& e) { + GAPI_LOG_FATAL(NULL, "Callback failed with error: " << e.what()); + //FIXME: Exception CAN't be rethrown here, since this callback works + // in separate IE thread and such scenarios aren't handled properly in + // G-API so far. + } } // NB: Not thread-safe. diff --git a/modules/gapi/src/logger.hpp b/modules/gapi/src/logger.hpp index cb169bf4be..7ac3c983fc 100644 --- a/modules/gapi/src/logger.hpp +++ b/modules/gapi/src/logger.hpp @@ -14,10 +14,12 @@ # define GAPI_LOG_INFO(tag, ...) CV_LOG_INFO(tag, __VA_ARGS__) # define GAPI_LOG_WARNING(tag, ...) CV_LOG_WARNING(tag, __VA_ARGS__) # define GAPI_LOG_DEBUG(tag, ...) CV_LOG_DEBUG(tag, __VA_ARGS__) +# define GAPI_LOG_FATAL(tag, ...) CV_LOG_FATAL(tag, __VA_ARGS__) #else # define GAPI_LOG_INFO(tag, ...) # define GAPI_LOG_WARNING(tag, ...) # define GAPI_LOG_DEBUG(tag, ...) +# define GAPI_LOG_FATAL(tag, ...) #endif // !defined(GAPI_STANDALONE)