const ngraph::NodeVector& nodes = graph->get_ops();
bool keep_constants = keep_constant_inputs || ::ngraph::op::util::has_op_with_type<::ngraph::op::FakeQuantize>(graph);
+ std::unordered_map<std::string, std::shared_ptr<ngraph::Node>> unique_names;
+ auto can_change_name = [](const std::shared_ptr<ngraph::Node> & node) -> bool {
+ if (ngraph::as_type_ptr<ngraph::op::Parameter>(node) ||
+ ngraph::as_type_ptr<ngraph::op::Result>(node)) {
+ return false;
+ }
+ for (const auto & output : node->outputs()) {
+ for (const auto & consumer : output.get_target_inputs()) {
+ if (ngraph::is_type<ngraph::op::Result>(consumer.get_node())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ auto generate_unique_name = [&unique_names](std::string name) -> std::string {
+ size_t suffix = 1;
+ while(unique_names.count(name + "/" + std::to_string(suffix))) {
+ ++suffix;
+ }
+ return name + "/" + std::to_string(suffix);
+ };
+
+ // normalize nodes names to be unique
+ for (auto & node : nodes) {
+ // skip Result operations as they have the same friendly name as their parent
+ if (ngraph::is_type<ngraph::op::Result>(node.get())) {
+ continue;
+ }
+
+ auto & duplicate = unique_names[node->get_friendly_name()];
+ if (!duplicate) {
+ duplicate = node;
+ continue;
+ }
+
+ if (!can_change_name(duplicate) && !can_change_name(node)) {
+ THROW_IE_EXCEPTION << "Detected two output operations with the same name: " << duplicate << " and " << node;
+ }
+
+ auto & renamed = can_change_name(duplicate) ? duplicate : node;
+ renamed->set_friendly_name(generate_unique_name(renamed->get_friendly_name()));
+
+ unique_names[duplicate->get_friendly_name()] = duplicate;
+ unique_names[node->get_friendly_name()] = node;
+ }
+
// Create layers and output data
for (const auto &layer : nodes) {
if (isInternalLayer(layer, keep_constants)) continue;
CNNLayerPtr cnnLayer;
ret = cnnNetworkImpl->getLayerByName(layer->get_friendly_name().c_str(), cnnLayer, nullptr);
- if (ret != OK) THROW_IE_EXCEPTION << "Cannot find layer with name: " << layer->get_friendly_name();
+ if (ret != OK)
+ THROW_IE_EXCEPTION << "Cannot find layer with name: " << layer->get_friendly_name();
auto inIndex = layer->input(i).get_index();
if (cnnLayer->insData.size() <= (inIndex - count_of_skipped) ||
"v3::NonZero non_zero (relu[0]:f32?) -> (i64{?,?})\n"
"v0::Result result (non_zero[0]:i64{?,?}) -> (i64{?,?})")));
}
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesAllInternal) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ {
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ end->set_friendly_name(begin->get_name());
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{ss}, ngraph::ParameterVector{input});
+ }
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ nGraphImpl = CNNNetwork(InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl));
+ ASSERT_EQ(nGraphImpl.layerCount(), 5);
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesHasResult1) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ {
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ end->set_friendly_name(begin->get_name());
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{ss, begin}, ngraph::ParameterVector{input});
+ }
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ nGraphImpl = CNNNetwork(InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl));
+ ASSERT_EQ(nGraphImpl.layerCount(), 5);
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesHasResult2) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ {
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ begin->set_friendly_name("const");
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ end->set_friendly_name("const");
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ stride->set_friendly_name("const");
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{ss, begin}, ngraph::ParameterVector{input});
+ }
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ nGraphImpl = CNNNetwork(InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl));
+ ASSERT_EQ(nGraphImpl.layerCount(), 5);
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesHasResult3) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ {
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ begin->set_friendly_name("const");
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ end->set_friendly_name("const");
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ stride->set_friendly_name("const");
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+ ss->set_friendly_name("node");
+ auto squeeze = std::make_shared<ngraph::opset1::Squeeze>(ss, ngraph::opset1::Constant::create(ngraph::element::i64, {1}, {0}));
+ squeeze->set_friendly_name("node");
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{squeeze, begin}, ngraph::ParameterVector{input});
+ }
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ nGraphImpl = CNNNetwork(InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl));
+ ASSERT_EQ(nGraphImpl.layerCount(), 7);
+ auto outputs_info = nGraphImpl.getOutputsInfo();
+ ASSERT_TRUE(outputs_info.count("node"));
+ ASSERT_TRUE(outputs_info.count("const"));
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesNegative) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ {
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ begin->set_friendly_name("const");
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ end->set_friendly_name("const");
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{ss, begin, end}, ngraph::ParameterVector{input});
+ }
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ try {
+ InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl);
+ FAIL() << "InferenceEngineException must be thrown";
+ } catch(InferenceEngine::details::InferenceEngineException & e) {
+ EXPECT_THAT(e.what(), testing::HasSubstr(std::string("Detected two output operations with the same name:")));
+ }
+}
+
+TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesParametersNegative) {
+ std::shared_ptr<ngraph::Function> f(nullptr);
+ auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ input->set_friendly_name("param");
+ auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ auto end = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {0, 0});
+ auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, {2}, {1, 1});
+ auto ss = std::make_shared<ngraph::opset1::StridedSlice>(
+ input,
+ begin,
+ end,
+ stride,
+ std::vector<int64_t>{1, 1}, std::vector<int64_t>{1, 1});
+ auto input2 = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3});
+ auto concat = std::make_shared<ngraph::opset1::Concat>(ngraph::NodeVector{ss, input2}, 0);
+
+ f = std::make_shared<ngraph::Function>(ngraph::NodeVector{concat}, ngraph::ParameterVector{input, input2});
+
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+ try {
+ input2->set_friendly_name("param");
+ InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl);
+ FAIL() << "InferenceEngineException must be thrown";
+ } catch(InferenceEngine::details::InferenceEngineException & e) {
+ EXPECT_THAT(e.what(), testing::HasSubstr(std::string("Detected two output operations with the same name:")));
+ }
}
\ No newline at end of file