diff --git a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp index 4681680db3b..62c79ecd3ca 100644 --- a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp @@ -94,6 +94,28 @@ void CNNNetworkNGraphImpl::createDataForResult(const ::ngraph::Output<::ngraph:: } } +void CNNNetworkNGraphImpl::validateFunctionNames() const { + // nGraph function parameters and pre-Results operations should have unique names + std::unordered_set unique_names; + for (const auto& param : _ngraph_function->get_parameters()) { + if (unique_names.count(param->get_friendly_name())) { + IE_THROW() << "Function contains several inputs with one friendly name!"; + } + unique_names.insert(param->get_friendly_name()); + } + for (const auto& result : _ngraph_function->get_results()) { + const auto& parent = result->get_input_node_shared_ptr(0); + auto name = parent->get_friendly_name(); + if (parent->get_output_size() > 1) { + name += "." + std::to_string(result->get_input_source_output(0).get_index()); + } + if (unique_names.count(name) && !ngraph::op::is_parameter(parent)) { + IE_THROW() << "Function contains several inputs and outputs with one friendly name!"; + } + unique_names.insert(name); + } +} + CNNNetworkNGraphImpl::CNNNetworkNGraphImpl( const std::shared_ptr& nGraph, const std::vector& exts) @@ -113,6 +135,8 @@ CNNNetworkNGraphImpl::CNNNetworkNGraphImpl( network.setInputInfo(info); }; + validateFunctionNames(); + reshape(); for (const auto& layer : _ngraph_function->get_parameters()) { std::string outName = layer->get_friendly_name(); @@ -148,6 +172,7 @@ CNNNetworkNGraphImpl::CNNNetworkNGraphImpl(const CNNNetwork& network) { } _ngraph_function = copyFunction(network.getFunction(), false); + validateFunctionNames(); InputsDataMap inputs = network.getInputsInfo(); OutputsDataMap outputs = network.getOutputsInfo(); @@ -231,6 +256,13 @@ StatusCode CNNNetworkNGraphImpl::addOutput(const std::string& layerName, size_t auto result = make_shared<::ngraph::op::Result>(layer->output(outputIndex)); result->set_friendly_name(outputName); _ngraph_function->add_results({result}); + // Check that we cannot add Result to layer with non unique friendly name + try { + validateFunctionNames(); + } catch (...) { + _ngraph_function->remove_result(result); + throw; + } if (_outputData.count(outputName) == 0) { reshape(); diff --git a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp index 9d0bc076dd7..a0300b11fa5 100644 --- a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp +++ b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp @@ -105,6 +105,7 @@ private: */ void reshape(); void reshape(const std::map>& inputShapes); + void validateFunctionNames() const; }; } // namespace details } // namespace InferenceEngine diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp index ac041eb1a35..a75822720ac 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp @@ -1678,4 +1678,110 @@ TEST(CNNNGraphImplTests, SaveOriginalResultNameForMultiOutputOpOpset6) { ASSERT_NE(outputs.find("text_features"), outputs.end()); } } + +TEST(CNNNGraphImplTests, CheckUniqueNames) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("boxes"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_NO_THROW(InferenceEngine::CNNNetwork{f}); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueParameterName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("boxes"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("boxes"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueResultName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("nms.1"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueNewResultName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("nms.1"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result3}, ngraph::ParameterVector{boxes, scores}); + } + + + CNNNetwork cnnNet; + ASSERT_NO_THROW(cnnNet = InferenceEngine::CNNNetwork{f}); + ASSERT_THROW(cnnNet.addOutput("nms", 1), InferenceEngine::Exception); +} + IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp index 5e5944583fc..5a298ed4f41 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp @@ -355,13 +355,7 @@ TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesNegative) { f = std::make_shared(ngraph::NodeVector{ss, begin, end}, ngraph::ParameterVector{input}); } - InferenceEngine::CNNNetwork nGraphImpl(f); - try { - InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl); - FAIL() << "InferenceEngine::Exception must be thrown"; - } catch(InferenceEngine::Exception & e) { - EXPECT_THAT(e.what(), testing::HasSubstr(std::string("Detected two output operations with the same name:"))); - } + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); } TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesParametersNegative) {