diff --git a/docs/template_plugin/src/template_executable_network.cpp b/docs/template_plugin/src/template_executable_network.cpp index 1231f4970c2..98c6b53ef3e 100644 --- a/docs/template_plugin/src/template_executable_network.cpp +++ b/docs/template_plugin/src/template_executable_network.cpp @@ -203,7 +203,7 @@ void TemplatePlugin::ExecutableNetwork::Export(std::ostream& modelStream) { // Note: custom ngraph extensions are not supported std::map custom_opsets; std::stringstream xmlFile, binFile; - ngraph::pass::Serialize serializer(xmlFile, binFile, ngraph::pass::Serialize::Version::IR_V10, custom_opsets); + ngraph::pass::Serialize serializer(xmlFile, binFile, custom_opsets); serializer.run_on_function(_function); auto m_constants = binFile.str(); diff --git a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp index f3d7c2a34a4..90dd4608de7 100644 --- a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp @@ -497,8 +497,8 @@ StatusCode CNNNetworkNGraphImpl::serialize(const std::string& xmlPath, ngraph::pass::Manager manager; manager.register_pass(xmlPath, binPath, - ngraph::pass::Serialize::Version::IR_V10, - custom_opsets); + custom_opsets, + ngraph::pass::Serialize::Version::IR_V10); manager.run_passes(_ngraph_function); } catch (const Exception& e) { return DescriptionBuffer(GENERAL_ERROR, resp) << e.what(); @@ -521,8 +521,8 @@ StatusCode CNNNetworkNGraphImpl::serialize(std::ostream& xmlBuf, std::ostream& b ngraph::pass::Manager manager; manager.register_pass(xmlBuf, binBuf, - ngraph::pass::Serialize::Version::IR_V10, - custom_opsets); + custom_opsets, + ngraph::pass::Serialize::Version::IR_V10); manager.run_passes(_ngraph_function); } catch (const Exception& e) { return DescriptionBuffer(GENERAL_ERROR, resp) << e.what(); @@ -547,8 +547,8 @@ StatusCode CNNNetworkNGraphImpl::serialize(std::ostream& xmlBuf, Blob::Ptr& binB ngraph::pass::Manager manager; manager.register_pass(xmlBuf, binBuf, - ngraph::pass::Serialize::Version::IR_V10, - custom_opsets); + custom_opsets, + ngraph::pass::Serialize::Version::IR_V10); manager.run_passes(_ngraph_function); std::streambuf* pbuf = binBuf.rdbuf(); diff --git a/inference-engine/src/inference_engine/src/compilation_context.cpp b/inference-engine/src/inference_engine/src/compilation_context.cpp index 56d2580f464..b1a7c74ec4a 100644 --- a/inference-engine/src/inference_engine/src/compilation_context.cpp +++ b/inference-engine/src/inference_engine/src/compilation_context.cpp @@ -97,7 +97,7 @@ std::string NetworkCompilationContext::computeHash(const CNNNetwork& network, // 1. Serialize CNNNetwork net(network); - ngraph::pass::Serialize serializer(xml, bin, ngraph::pass::Serialize::Version::IR_V10); + ngraph::pass::Serialize serializer(xml, bin); serializer.run_on_function(net.getFunction()); // 2. Compute hash on serialized data and options diff --git a/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp b/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp index 47e11b59359..9b6904c0233 100644 --- a/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp +++ b/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp @@ -46,4 +46,4 @@ private: ngraph::FactoryRegistry m_factory_registry; }; } // namespace pass -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/inference-engine/src/transformations/include/transformations/serialize.hpp b/inference-engine/src/transformations/include/transformations/serialize.hpp index f69467726b6..a043225a9eb 100644 --- a/inference-engine/src/transformations/include/transformations/serialize.hpp +++ b/inference-engine/src/transformations/include/transformations/serialize.hpp @@ -18,7 +18,6 @@ class TRANSFORMATIONS_API Serialize; class TRANSFORMATIONS_API StreamSerialize; } // namespace pass - } // namespace ngraph /** @@ -32,17 +31,24 @@ class TRANSFORMATIONS_API StreamSerialize; */ class ngraph::pass::Serialize : public ngraph::pass::FunctionPass { public: - enum class Version { IR_V10 }; + enum class Version : uint8_t { + IR_V10 = 10, // v10 IR + IR_V11 = 11 // v11 IR + }; NGRAPH_RTTI_DECLARATION; bool run_on_function(std::shared_ptr f) override; - Serialize(std::ostream & xmlFile, std::ostream & binFile, - Version version = Version::IR_V10, - std::map custom_opsets = {}); + Serialize(std::ostream& xmlFile, std::ostream& binFile, + std::map custom_opsets, + Version version = Version::IR_V11); + Serialize(std::ostream& xmlFile, std::ostream& binFile, + Version version = Version::IR_V11); Serialize(const std::string& xmlPath, const std::string& binPath, - Version version = Version::IR_V10, - std::map custom_opsets = {}); + std::map custom_opsets, + Version version = Version::IR_V11); + Serialize(const std::string& xmlPath, const std::string& binPath, + Version version = Version::IR_V11); private: std::ostream * m_xmlFile; @@ -74,13 +80,14 @@ public: bool run_on_function(std::shared_ptr f) override; - StreamSerialize(std::ostream & stream, + StreamSerialize(std::ostream& stream, std::map && custom_opsets = {}, const std::function & custom_data_serializer = {}, - Serialize::Version version = Serialize::Version::IR_V10); + Serialize::Version version = Serialize::Version::IR_V11); private: std::ostream & m_stream; std::map m_custom_opsets; std::function m_custom_data_serializer; + const Serialize::Version m_version; }; diff --git a/inference-engine/src/transformations/src/transformations/serialize.cpp b/inference-engine/src/transformations/src/transformations/serialize.cpp index 2608c2b7352..dea722a6364 100644 --- a/inference-engine/src/transformations/src/transformations/serialize.cpp +++ b/inference-engine/src/transformations/src/transformations/serialize.cpp @@ -123,10 +123,11 @@ private: FilePosition m_blob_offset; // blob offset inside output stream }; -void ngfunction_2_irv10(pugi::xml_node& node, - const ngraph::Function& f, - const std::map& custom_opsets, - ConstantWriter& constant_write_handler); +void ngfunction_2_ir(pugi::xml_node& node, + const ngraph::Function& f, + const std::map& custom_opsets, + ConstantWriter& constant_write_handler, + int64_t version); // Some of the operators were added to wrong opsets. This is a mapping // that allows such operators to be serialized with proper opsets. @@ -260,6 +261,7 @@ class XmlSerializer : public ngraph::AttributeVisitor { const std::string& m_node_type_name; const std::map& m_custom_opsets; ConstantWriter& m_constant_write_handler; + int64_t m_version; template std::string create_atribute_list( @@ -367,11 +369,13 @@ public: XmlSerializer(pugi::xml_node& data, const std::string& node_type_name, const std::map& custom_opsets, - ConstantWriter& constant_write_handler) + ConstantWriter& constant_write_handler, + int64_t version) : m_xml_node(data) , m_node_type_name(node_type_name) , m_custom_opsets(custom_opsets) - , m_constant_write_handler(constant_write_handler) { + , m_constant_write_handler(constant_write_handler) + , m_version(version) { } void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { @@ -382,7 +386,7 @@ public: NGRAPH_CHECK(!parameter_mapping.empty() || !result_mapping.empty(), "No parameters or results found in body Function."); // TI, Loop do not have attributtes as regular ops, it is necessary to append "port_map" and - // "back_edges" to layer above (m_xml_node.parent()) as in ngfunction_2_irv10() layer (here "m_xml_node") + // "back_edges" to layer above (m_xml_node.parent()) as in ngfunction_2_ir() layer (here "m_xml_node") // with empty attributes is removed. if (const auto& a = ngraph::as_type>>>(&adapter)) { @@ -489,14 +493,16 @@ public: ngraph::ValueAccessor>& adapter) override { if (name == "body") { // TI, Loop do not have attributtes as regular ops, it is necessary to append "body" - // to layer above (m_xml_node.parent()) as in ngfunction_2_irv10() layer (m_xml_node) with empty attributes + // to layer above (m_xml_node.parent()) as in ngfunction_2_ir() layer (m_xml_node) with empty attributes // is removed. pugi::xml_node xml_body = m_xml_node.parent().append_child(name.c_str()); - ngfunction_2_irv10(xml_body, *adapter.get(), m_custom_opsets, m_constant_write_handler); + // FIXME: the issue with TensorIteratorTest.Serialize doesn't allow to use v11 order of operations + // Need to use m_version instead of 10 + ngfunction_2_ir(xml_body, *adapter.get(), m_custom_opsets, m_constant_write_handler, 10); xml_body.remove_attribute("name"); xml_body.remove_attribute("version"); } else if (name == "net") { - ngfunction_2_irv10(m_xml_node, *adapter.get(), m_custom_opsets, m_constant_write_handler); + ngfunction_2_ir(m_xml_node, *adapter.get(), m_custom_opsets, m_constant_write_handler, m_version); } else { NGRAPH_CHECK(false, "Unsupported Function name."); } @@ -645,7 +651,7 @@ std::string escape_delim(const std::string& name, const char delim = ',') { } std::string generate_unique_name( - const std::unordered_set& unique_names, std::string base_name, + const std::unordered_set& unique_names, const std::string& base_name, int suffix) { std::string new_name = base_name + std::to_string(suffix); if (unique_names.find(new_name) == unique_names.end()) { @@ -695,7 +701,7 @@ bool is_exec_graph(const ngraph::Function& f) { return false; } -bool has_dynamic_output(std::shared_ptr n) { +bool has_dynamic_output(const std::shared_ptr& n) { for (size_t i = 0; i < n->get_output_size(); i++) { if (n->get_output_partial_shape(i).is_dynamic()) { return true; @@ -707,7 +713,7 @@ bool has_dynamic_output(std::shared_ptr n) { bool resolve_dynamic_shapes(const ngraph::Function& f) { const auto & f_ops = f.get_ordered_ops(); if (std::all_of(f_ops.begin(), f_ops.end(), - [](std::shared_ptr results) { + [](const std::shared_ptr& results) { return !results->is_dynamic() && !has_dynamic_output(results); })) { return false; } @@ -818,12 +824,13 @@ void auto_pad_resolving(ov::Node* node) { } } -void ngfunction_2_irv10(pugi::xml_node& netXml, - const ngraph::Function& f, - const std::map& custom_opsets, - ConstantWriter& constant_node_write_handler) { +void ngfunction_2_ir(pugi::xml_node& netXml, + const ngraph::Function& f, + const std::map& custom_opsets, + ConstantWriter& constant_node_write_handler, + int64_t version) { netXml.append_attribute("name").set_value(f.get_friendly_name().c_str()); - netXml.append_attribute("version").set_value("10"); + netXml.append_attribute("version").set_value(version); pugi::xml_node layers = netXml.append_child("layers"); const std::unordered_map layer_ids = @@ -835,7 +842,30 @@ void ngfunction_2_irv10(pugi::xml_node& netXml, const bool exec_graph = is_exec_graph(f); - for (const auto& n : f.get_ordered_ops()) { + // change the order for parameters/results/sinks + // It should be a part of get_ordered_ops method + // FIXME: TensorIteratorTest.Serialize tests + auto sorted_ops = f.get_ordered_ops(); + if (version >= 11) { + std::vector> result; + result.reserve(sorted_ops.size()); + for (const auto& param : f.get_parameters()) { + result.emplace_back(param); + } + for (auto&& node : sorted_ops) { + if (!ov::op::util::is_parameter(node) && !ov::op::util::is_output(node) && !ov::op::util::is_sink(node)) + result.emplace_back(node); + } + for (const auto& sink : f.get_sinks()) { + result.emplace_back(sink); + } + for (const auto& res : f.get_results()) { + result.emplace_back(res); + } + sorted_ops = result; + } + + for (const auto& n : sorted_ops) { ngraph::Node* node = n.get(); const std::string & node_type_name{node->get_type_name()}; @@ -871,7 +901,9 @@ void ngfunction_2_irv10(pugi::xml_node& netXml, } }; - append_runtime_info(layer, node->get_rt_info()); + if (version >= 11) { + append_runtime_info(layer, node->get_rt_info()); + } int port_id = 0; // @@ -897,7 +929,8 @@ void ngfunction_2_irv10(pugi::xml_node& netXml, .set_value(std::to_string(d.get_length()).c_str()); } } - append_runtime_info(port, i.get_rt_info()); + if (version >= 11) + append_runtime_info(port, i.get_rt_info()); } if (node_type_name == "TensorIterator" || node_type_name == "Loop") { @@ -948,7 +981,8 @@ void ngfunction_2_irv10(pugi::xml_node& netXml, .set_value(std::to_string(d.get_length()).c_str()); } } - append_runtime_info(port, o.get_rt_info()); + if (version >= 11) + append_runtime_info(port, o.get_rt_info()); } if (node_type_name == "TensorIterator" || node_type_name == "Loop") { layer.insert_move_after(output, layer.first_child()); @@ -957,7 +991,7 @@ void ngfunction_2_irv10(pugi::xml_node& netXml, // fill general attributes auto_pad_resolving(node); // Backward compatibility: clear padding values for nodes with auto_pad - XmlSerializer visitor(data, node_type_name, custom_opsets, constant_node_write_handler); + XmlSerializer visitor(data, node_type_name, custom_opsets, constant_node_write_handler, version); NGRAPH_CHECK(node->visit_attributes(visitor), "Visitor API is not supported in ", node); rt_info::XmlSerializer{data}.serialize(node->get_rt_info()); @@ -1024,25 +1058,22 @@ bool pass::Serialize::run_on_function(std::shared_ptr f) { RUN_ON_FUNCTION_SCOPE(Serialize); auto serializeFunc = [&] (std::ostream & xml_file, std::ostream & bin_file) { - switch (m_version) { - case Version::IR_V10: - { - std::string name = "net"; - pugi::xml_document xml_doc; - pugi::xml_node net_node = xml_doc.append_child(name.c_str()); - ConstantWriter constant_write_handler(bin_file); - XmlSerializer visitor(net_node, name, m_custom_opsets, constant_write_handler); - visitor.on_attribute(name, f); + auto version = static_cast(m_version); - xml_doc.save(xml_file); - xml_file.flush(); - bin_file.flush(); - } - break; - default: - NGRAPH_UNREACHABLE("Unsupported version"); - break; + if (version != static_cast(Serialize::Version::IR_V10) && + version != static_cast(Serialize::Version::IR_V11)) { + throw ngraph_error("Unsupported version"); } + std::string name = "net"; + pugi::xml_document xml_doc; + pugi::xml_node net_node = xml_doc.append_child(name.c_str()); + ConstantWriter constant_write_handler(bin_file); + XmlSerializer visitor(net_node, name, m_custom_opsets, constant_write_handler, version); + visitor.on_attribute(name, f); + + xml_doc.save(xml_file); + xml_file.flush(); + bin_file.flush(); }; if (m_xmlFile && m_binFile) { @@ -1075,8 +1106,8 @@ bool pass::Serialize::run_on_function(std::shared_ptr f) { pass::Serialize::Serialize(std::ostream& xmlFile, std::ostream& binFile, - pass::Serialize::Version version, - std::map custom_opsets) + std::map custom_opsets, + pass::Serialize::Version version) : m_xmlFile{&xmlFile} , m_binFile{&binFile} , m_xmlPath{} @@ -1085,11 +1116,15 @@ pass::Serialize::Serialize(std::ostream& xmlFile, , m_custom_opsets{custom_opsets} { } +pass::Serialize::Serialize(std::ostream& xmlFile, + std::ostream& binFile, + pass::Serialize::Version version) + : pass::Serialize::Serialize(xmlFile, binFile, std::map{}, version) {} pass::Serialize::Serialize(const std::string& xmlPath, const std::string& binPath, - pass::Serialize::Version version, - std::map custom_opsets) + std::map custom_opsets, + pass::Serialize::Version version) : m_xmlFile{nullptr} , m_binFile{nullptr} , m_xmlPath{valid_xml_path(xmlPath)} @@ -1098,6 +1133,10 @@ pass::Serialize::Serialize(const std::string& xmlPath, , m_custom_opsets{custom_opsets} { } +pass::Serialize::Serialize(const std::string& xmlPath, + const std::string& binPath, + pass::Serialize::Version version) + : pass::Serialize::Serialize(xmlPath, binPath, std::map{}, version) {} ngraph::pass::StreamSerialize::StreamSerialize(std::ostream & stream, std::map && custom_opsets, @@ -1105,8 +1144,10 @@ ngraph::pass::StreamSerialize::StreamSerialize(std::ostream & stream, Serialize::Version version) : m_stream(stream) , m_custom_opsets(std::move(custom_opsets)) - , m_custom_data_serializer(custom_data_serializer) { - if (version != Serialize::Version::IR_V10) { + , m_custom_data_serializer(custom_data_serializer) + , m_version(version) { + if (version != Serialize::Version::IR_V10 && + version != Serialize::Version::IR_V11) { throw ngraph_error("Unsupported version"); } } @@ -1124,6 +1165,7 @@ bool ngraph::pass::StreamSerialize::run_on_function(std::shared_ptr(m_version); // Header const size_t header_offset = m_stream.tellp(); @@ -1141,7 +1183,7 @@ bool ngraph::pass::StreamSerialize::run_on_function(std::shared_ptr( - m_out_xml_path, m_out_bin_path, - ngraph::pass::Serialize::Version::IR_V10, extension->getOpSets()); + m_out_xml_path, m_out_bin_path, extension->getOpSets(), + ngraph::pass::Serialize::Version::IR_V10); manager.run_passes(expected.getFunction()); auto result = ie.ReadNetwork(m_out_xml_path, m_out_bin_path); @@ -140,8 +140,8 @@ TEST_F(CustomOpsSerializationTest, CustomOpNoExtensions) { auto expected = ie.ReadNetwork(model); ngraph::pass::Manager manager; manager.register_pass( - m_out_xml_path, m_out_bin_path, - ngraph::pass::Serialize::Version::IR_V10, extension->getOpSets()); + m_out_xml_path, m_out_bin_path, extension->getOpSets(), + ngraph::pass::Serialize::Version::IR_V10); manager.run_passes(expected.getFunction()); auto result = ie.ReadNetwork(m_out_xml_path, m_out_bin_path); diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp index 6f196509332..41493ccd6c0 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp @@ -12,7 +12,7 @@ using namespace ngraph; -TEST(RTInfoDeserialization, Node) { +TEST(RTInfoDeserialization, NodeV10) { std::string model = R"V0G0N( @@ -30,8 +30,193 @@ TEST(RTInfoDeserialization, Node) { - - + + + + + + + + 1 + 3 + 22 + 22 + + + + + 1 + 3 + 22 + 22 + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + +)V0G0N"; + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(model, InferenceEngine::Blob::Ptr()); + auto f = net.getFunction(); + + auto check_rt_info = [](const RTMap & info) { + const std::string & key = VariantWrapper::get_type_info_static(); + ASSERT_FALSE(info.count(key)); + }; + + auto check_version = [](const std::shared_ptr& f) { + auto& rt_info = f->get_rt_info(); + ASSERT_TRUE(rt_info.count("version")); + auto version = std::dynamic_pointer_cast>(rt_info.at("version")); + ASSERT_NE(version, nullptr); + ASSERT_EQ(version->get(), 10); + }; + check_version(f); + + auto param = f->get_parameters()[0]; + check_rt_info(param->get_rt_info()); + + auto result = f->get_results()[0]; + auto round = result->get_input_node_ptr(0); + check_rt_info(round->get_rt_info()); +} + +TEST(RTInfoDeserialization, InputAndOutputV10) { + std::string model = R"V0G0N( + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + + 1 + 3 + 22 + 22 + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + +)V0G0N"; + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(model, InferenceEngine::Blob::Ptr()); + auto f = net.getFunction(); + + auto check_rt_info = [](const RTMap & info) { + const std::string & key = VariantWrapper::get_type_info_static(); + ASSERT_FALSE(info.count(key)); + }; + + auto check_version = [](const std::shared_ptr& f) { + auto& rt_info = f->get_rt_info(); + ASSERT_TRUE(rt_info.count("version")); + auto version = std::dynamic_pointer_cast>(rt_info.at("version")); + ASSERT_NE(version, nullptr); + ASSERT_EQ(version->get(), 10); + }; + check_version(f); + + auto param = f->get_parameters()[0]; + check_rt_info(param->output(0).get_rt_info()); + + auto result = f->get_results()[0]; + check_rt_info(result->input(0).get_rt_info()); + + auto add = result->get_input_node_ptr(0); + check_rt_info(add->input(0).get_rt_info()); + check_rt_info(add->input(1).get_rt_info()); + check_rt_info(add->output(0).get_rt_info()); +} + +TEST(RTInfoDeserialization, NodeV11) { + std::string model = R"V0G0N( + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + @@ -81,6 +266,15 @@ TEST(RTInfoDeserialization, Node) { ASSERT_EQ(fused_names_attr->get().getNames(), names); }; + auto check_version = [](const std::shared_ptr& f) { + auto& rt_info = f->get_rt_info(); + ASSERT_TRUE(rt_info.count("version")); + auto version = std::dynamic_pointer_cast>(rt_info.at("version")); + ASSERT_NE(version, nullptr); + ASSERT_EQ(version->get(), 11); + }; + check_version(f); + auto param = f->get_parameters()[0]; check_fused_names(param->get_rt_info(), "in1"); @@ -89,9 +283,9 @@ TEST(RTInfoDeserialization, Node) { check_fused_names(round->get_rt_info(), "Round1,Round2"); } -TEST(RTInfoDeserialization, InputAndOutput) { +TEST(RTInfoDeserialization, InputAndOutputV11) { std::string model = R"V0G0N( - + @@ -107,9 +301,9 @@ TEST(RTInfoDeserialization, InputAndOutput) { - - - + + + @@ -117,8 +311,8 @@ TEST(RTInfoDeserialization, InputAndOutput) { 3 22 22 - - + + @@ -126,10 +320,10 @@ TEST(RTInfoDeserialization, InputAndOutput) { 3 22 22 - - - - + + + + @@ -137,9 +331,9 @@ TEST(RTInfoDeserialization, InputAndOutput) { 3 22 22 - - - + + + @@ -165,6 +359,15 @@ TEST(RTInfoDeserialization, InputAndOutput) { auto net = core.ReadNetwork(model, InferenceEngine::Blob::Ptr()); auto f = net.getFunction(); + auto check_version = [](const std::shared_ptr& f) { + auto& rt_info = f->get_rt_info(); + ASSERT_TRUE(rt_info.count("version")); + auto version = std::dynamic_pointer_cast>(rt_info.at("version")); + ASSERT_NE(version, nullptr); + ASSERT_EQ(version->get(), 11); + }; + check_version(f); + auto check_fused_names = [](const RTMap & info, const std::string & names) { const std::string & key = VariantWrapper::get_type_info_static(); ASSERT_TRUE(info.count(key)); @@ -184,3 +387,123 @@ TEST(RTInfoDeserialization, InputAndOutput) { check_fused_names(add->input(1).get_rt_info(), "test3,test4"); check_fused_names(add->output(0).get_rt_info(), "test4,test5"); } + +TEST(RTInfoDeserialization, IndexesInputAndOutputV11) { + std::string model = R"V0G0N( + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + 1 + 3 + 22 + 22 + + + 1 + 3 + 22 + 22 + + + + + 1 + 3 + 22 + 22 + + + + + + + 1 + 3 + 22 + 22 + + + + + 1 + 3 + 22 + 22 + + + + + + + 1 + 3 + 22 + 22 + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + + + +)V0G0N"; + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(model, InferenceEngine::Blob::Ptr()); + auto f = net.getFunction(); + + auto check_version = [](const std::shared_ptr& f) { + auto& rt_info = f->get_rt_info(); + ASSERT_TRUE(rt_info.count("version")); + auto version = std::dynamic_pointer_cast>(rt_info.at("version")); + ASSERT_NE(version, nullptr); + ASSERT_EQ(version->get(), 11); + }; + check_version(f); + + ASSERT_EQ(2, f->get_parameters().size()); + ASSERT_EQ(f->get_parameters()[0]->get_friendly_name(), "in1"); + ASSERT_EQ(f->get_parameters()[1]->get_friendly_name(), "in2"); + + ASSERT_EQ(2, f->get_results().size()); + ASSERT_EQ(f->get_results()[0]->get_friendly_name(), "output2"); + ASSERT_EQ(f->get_results()[1]->get_friendly_name(), "output1"); +} diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp index 306af550700..9187eb0c01f 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp @@ -11,7 +11,7 @@ #include "ie_core.hpp" #include "ngraph/ngraph.hpp" #include "transformations/serialize.hpp" -#include +#include #include using namespace ngraph; @@ -28,7 +28,7 @@ protected: } }; -TEST_F(RTInfoSerializationTest, all_attributes) { +TEST_F(RTInfoSerializationTest, all_attributes_latest) { auto init_info = [](RTMap & info) { info[VariantWrapper::get_type_info_static()] = std::make_shared>(ngraph::FusedNames("add")); @@ -38,8 +38,8 @@ TEST_F(RTInfoSerializationTest, all_attributes) { std::shared_ptr function; { - auto data = std::make_shared(ngraph::element::Type_t::f32, ngraph::Shape{1, 3, 10, 10}); - auto add = std::make_shared(data, data); + auto data = std::make_shared(ngraph::element::Type_t::f32, ngraph::Shape{1, 3, 10, 10}); + auto add = std::make_shared(data, data); init_info(add->get_rt_info()); init_info(add->input(0).get_rt_info()); init_info(add->input(1).get_rt_info()); @@ -75,3 +75,132 @@ TEST_F(RTInfoSerializationTest, all_attributes) { check_info(add->input(1).get_rt_info()); check_info(add->output(0).get_rt_info()); } + +TEST_F(RTInfoSerializationTest, all_attributes_v10) { + auto init_info = [](RTMap & info) { + info[VariantWrapper::get_type_info_static()] = + std::make_shared>(ngraph::FusedNames("add")); + info[ov::PrimitivesPriority::get_type_info_static()] = + std::make_shared("priority"); + }; + + std::shared_ptr function; + { + auto data = std::make_shared(ngraph::element::Type_t::f32, ngraph::Shape{1, 3, 10, 10}); + auto add = std::make_shared(data, data); + init_info(add->get_rt_info()); + init_info(add->input(0).get_rt_info()); + init_info(add->input(1).get_rt_info()); + init_info(add->output(0).get_rt_info()); + function = std::make_shared(OutputVector{add}, ParameterVector{data}); + } + + pass::Manager m; + m.register_pass(m_out_xml_path, m_out_bin_path, pass::Serialize::Version::IR_V10); + m.run_passes(function); + + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(m_out_xml_path, m_out_bin_path); + auto f = net.getFunction(); + + auto check_info = [](const RTMap & info) { + const std::string & key = VariantWrapper::get_type_info_static(); + ASSERT_FALSE(info.count(key)); + }; + + auto add = f->get_results()[0]->get_input_node_ptr(0); + check_info(add->get_rt_info()); + check_info(add->input(0).get_rt_info()); + check_info(add->input(1).get_rt_info()); + check_info(add->output(0).get_rt_info()); +} + +TEST_F(RTInfoSerializationTest, all_attributes_v11) { + auto init_info = [](RTMap & info) { + info[VariantWrapper::get_type_info_static()] = + std::make_shared>(ngraph::FusedNames("add")); + info[ov::PrimitivesPriority::get_type_info_static()] = + std::make_shared("priority"); + }; + + std::shared_ptr function; + { + auto data = std::make_shared(ngraph::element::Type_t::f32, ngraph::Shape{1, 3, 10, 10}); + auto add = std::make_shared(data, data); + init_info(add->get_rt_info()); + init_info(add->input(0).get_rt_info()); + init_info(add->input(1).get_rt_info()); + init_info(add->output(0).get_rt_info()); + function = std::make_shared(OutputVector{add}, ParameterVector{data}); + } + + pass::Manager m; + m.register_pass(m_out_xml_path, m_out_bin_path); + m.run_passes(function); + + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(m_out_xml_path, m_out_bin_path); + auto f = net.getFunction(); + + auto check_info = [](const RTMap & info) { + const std::string & key = VariantWrapper::get_type_info_static(); + ASSERT_TRUE(info.count(key)); + auto fused_names_attr = std::dynamic_pointer_cast>(info.at(key)); + ASSERT_TRUE(fused_names_attr); + ASSERT_EQ(fused_names_attr->get().getNames(), "add"); + + const std::string & pkey = ov::PrimitivesPriority::get_type_info_static(); + ASSERT_TRUE(info.count(pkey)); + auto primitives_priority_attr = std::dynamic_pointer_cast(info.at(pkey)); + ASSERT_TRUE(primitives_priority_attr); + ASSERT_EQ(primitives_priority_attr->get(), "priority"); + }; + + auto add = f->get_results()[0]->get_input_node_ptr(0); + check_info(add->get_rt_info()); + check_info(add->input(0).get_rt_info()); + check_info(add->input(1).get_rt_info()); + check_info(add->output(0).get_rt_info()); +} + +TEST_F(RTInfoSerializationTest, parameter_result_v11) { + std::shared_ptr function; + { + auto param1 = std::make_shared(ov::element::f32, ngraph::Shape({1, 3, 24, 24})); + param1->set_friendly_name("param1"); + param1->output(0).get_tensor().set_names({"data1"}); + auto param2 = std::make_shared(ov::element::f32, ngraph::Shape({1, 3, 24, 24})); + param2->set_friendly_name("param2"); + param2->output(0).get_tensor().set_names({"data2"}); + auto relu = std::make_shared(param1); + relu->set_friendly_name("relu_op"); + relu->output(0).get_tensor().set_names({"relu"}); + auto result1 = std::make_shared(relu); + result1->set_friendly_name("result1"); + auto concat = std::make_shared(OutputVector{relu, param2}, 1); + concat->set_friendly_name("concat_op"); + concat->output(0).get_tensor().set_names({"concat"}); + auto result2 = std::make_shared(concat); + result2->set_friendly_name("result2"); + function = std::make_shared(ngraph::ResultVector{result1, result2}, + ngraph::ParameterVector{param1, param2}); + function->set_friendly_name("SingleRuLU"); + } + + pass::Manager m; + m.register_pass(m_out_xml_path, m_out_bin_path, pass::Serialize::Version::IR_V11); + m.run_passes(function); + + auto core = InferenceEngine::Core(); + auto net = core.ReadNetwork(m_out_xml_path, m_out_bin_path); + auto f = net.getFunction(); + + ASSERT_EQ(function->get_results().size(), f->get_results().size()); + ASSERT_EQ(function->get_parameters().size(), f->get_parameters().size()); + for (size_t i = 0; i < f->get_parameters().size(); i++) { + ASSERT_EQ(function->get_parameters()[i]->get_friendly_name(), f->get_parameters()[i]->get_friendly_name()); + } + for (size_t i = 0; i < f->get_results().size(); i++) { + ASSERT_EQ(function->get_results()[i]->get_friendly_name(), f->get_results()[i]->get_friendly_name()); + } +} diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/src/test_model/test_model.cpp b/inference-engine/tests/ie_test_utils/functional_test_utils/src/test_model/test_model.cpp index ad553897062..f9c908e8913 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/src/test_model/test_model.cpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/src/test_model/test_model.cpp @@ -31,9 +31,7 @@ void generateTestModel(const std::string &modelPath, const InferenceEngine::Precision &netPrc, const InferenceEngine::SizeVector &inputDims) { ngraph::pass::Manager manager; - manager.register_pass( - modelPath, weightsPath, - ngraph::pass::Serialize::Version::IR_V10); + manager.register_pass(modelPath, weightsPath); manager.run_passes(ngraph::builder::subgraph::makeConvPoolRelu( inputDims, InferenceEngine::details::convertPrecision(netPrc))); } diff --git a/ngraph/core/include/openvino/core/function.hpp b/ngraph/core/include/openvino/core/function.hpp index e7e24e6ed35..88451692b1d 100644 --- a/ngraph/core/include/openvino/core/function.hpp +++ b/ngraph/core/include/openvino/core/function.hpp @@ -20,6 +20,7 @@ #include "openvino/core/core_visibility.hpp" #include "openvino/core/node.hpp" #include "openvino/core/rtti.hpp" +#include "openvino/core/variant.hpp" namespace ov { /// A user-defined function. @@ -263,6 +264,12 @@ public: /// \brief Return a variable by specified variable_id. ngraph::VariablePtr get_variable_by_id(const std::string& variable_id) const; + RTMap& get_rt_info() { + return m_rt_info; + } + const RTMap& get_rt_info() const { + return m_rt_info; + } private: Function(const Function&) = delete; @@ -290,6 +297,7 @@ private: ngraph::SinkVector m_sinks; ngraph::ParameterVector m_parameters; ngraph::VariableVector m_variables; + RTMap m_rt_info; }; template <> diff --git a/ngraph/core/src/graph_util.cpp b/ngraph/core/src/graph_util.cpp index a6436d1f8f2..43694aa7a98 100644 --- a/ngraph/core/src/graph_util.cpp +++ b/ngraph/core/src/graph_util.cpp @@ -389,6 +389,7 @@ std::shared_ptr ov::clone_function(const ngraph::Function& fun cloned_params, cloned_vars, func.get_friendly_name()); + result->get_rt_info() = func.get_rt_info(); return result; } diff --git a/ngraph/core/src/variant.cpp b/ngraph/core/src/variant.cpp index 694d8158fb5..b718b7994cc 100644 --- a/ngraph/core/src/variant.cpp +++ b/ngraph/core/src/variant.cpp @@ -5,6 +5,7 @@ #include "ngraph/variant.hpp" #include "ngraph/node.hpp" +#include "openvino/core/attribute_visitor.hpp" using namespace ngraph; diff --git a/ngraph/frontend/ir/src/frontend.cpp b/ngraph/frontend/ir/src/frontend.cpp index a8f80709f9f..78d143f3f67 100644 --- a/ngraph/frontend/ir/src/frontend.cpp +++ b/ngraph/frontend/ir/src/frontend.cpp @@ -89,7 +89,7 @@ bool FrontEndIR::supported_impl(const std::vector>& var return false; } - return version == 10; + return version >= 10 && version <= 11; } InputModel::Ptr FrontEndIR::load_impl(const std::vector>& variants) const { diff --git a/ngraph/frontend/ir/src/ir_deserializer.cpp b/ngraph/frontend/ir/src/ir_deserializer.cpp index 1c540d6875e..fdfebedf647 100644 --- a/ngraph/frontend/ir/src/ir_deserializer.cpp +++ b/ngraph/frontend/ir/src/ir_deserializer.cpp @@ -531,7 +531,7 @@ GenericLayerParams XmlDeserializer::parseGenericParams(const pugi::xml_node& nod IE_THROW() << "dimension (" << dimVal << ") in node " << node.name() << " must be greater or equal to -1: at offset " << node.offset_debug(); } - port.dims.push_back(dim); + port.dims.emplace_back(dim); } ngraph::element::Type type(ngraph::element::Type_t::undefined); @@ -639,7 +639,7 @@ std::shared_ptr XmlDeserializer::createNode(const std::vectoralloc_buffer_on_visit_attributes(false); } ngraphNode->set_arguments(inputs); - XmlDeserializer visitor(node, weights, m_opsets, m_variables); + XmlDeserializer visitor(node, weights, m_opsets, m_variables, m_version); if (ngraphNode->visit_attributes(visitor)) { ngraphNode->constructor_validate_and_infer_types(); @@ -651,7 +651,7 @@ std::shared_ptr XmlDeserializer::createNode(const std::vector(inputs); - XmlDeserializer visitor(node, weights, m_opsets, m_variables); + XmlDeserializer visitor(node, weights, m_opsets, m_variables, m_version); ngraphNode->visit_attributes(visitor); size_t index{0}; @@ -712,26 +712,29 @@ std::shared_ptr XmlDeserializer::createNode(const std::vectorget_rt_info(), node.child("rt_info")); + // read runtime info only for IR v11+ + if (m_version > 10) { + // set node runtime info attributes + set_runtime_info(ngraphNode->get_rt_info(), node.child("rt_info")); - // set output ports runtime info attributes - auto out_node = node.child("output"); - if (!out_node.empty()) { - size_t index{0}; - FOREACH_CHILD (rt_node, out_node, "port") { - set_runtime_info(ngraphNode->output(index).get_rt_info(), rt_node.child("rt_info")); - ++index; + // set output ports runtime info attributes + auto out_node = node.child("output"); + if (!out_node.empty()) { + size_t index{0}; + FOREACH_CHILD (rt_node, out_node, "port") { + set_runtime_info(ngraphNode->output(index).get_rt_info(), rt_node.child("rt_info")); + ++index; + } } - } - // set input ports runtime info attributes - auto in_node = node.child("input"); - if (!in_node.empty()) { - size_t index{0}; - FOREACH_CHILD (rt_node, in_node, "port") { - set_runtime_info(ngraphNode->input(index).get_rt_info(), rt_node.child("rt_info")); - ++index; + // set input ports runtime info attributes + auto in_node = node.child("input"); + if (!in_node.empty()) { + size_t index{0}; + FOREACH_CHILD (rt_node, in_node, "port") { + set_runtime_info(ngraphNode->input(index).get_rt_info(), rt_node.child("rt_info")); + ++index; + } } } diff --git a/ngraph/frontend/ir/src/ir_deserializer.hpp b/ngraph/frontend/ir/src/ir_deserializer.hpp index 9ebef0b9062..7f96c723b13 100644 --- a/ngraph/frontend/ir/src/ir_deserializer.hpp +++ b/ngraph/frontend/ir/src/ir_deserializer.hpp @@ -57,11 +57,13 @@ public: explicit XmlDeserializer(const pugi::xml_node& node, const ov::Weights& weights, const std::unordered_map& opsets, - std::unordered_map>& variables) + std::unordered_map>& variables, + size_t version) : m_node(node), m_weights(weights), m_opsets(opsets), - m_variables(variables) {} + m_variables(variables), + m_version(version) {} void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { std::string val; @@ -187,5 +189,6 @@ private: IoMap io_map; bool m_use_framework_node{false}; + int64_t m_version; }; -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/ir/src/model.cpp b/ngraph/frontend/ir/src/model.cpp index d10568b816b..be9326b3385 100644 --- a/ngraph/frontend/ir/src/model.cpp +++ b/ngraph/frontend/ir/src/model.cpp @@ -231,11 +231,12 @@ std::shared_ptr InputModelIR::InputModelIRImpl::convert() { opsets[it.first] = it.second; } - ov::XmlDeserializer visitor(m_root, m_weights, opsets, variables); + size_t version = XMLParseUtils::GetUIntAttr(m_root, "version", 0); + ov::XmlDeserializer visitor(m_root, m_weights, opsets, variables, version); visitor.use_framework_node(opsets.count("framework_node_ext")); std::shared_ptr function; visitor.on_attribute("net", function); - + function->get_rt_info()["version"] = std::make_shared>(version); ParsePreProcess(m_root, m_weights, function); return function; diff --git a/ngraph/test/util.cpp b/ngraph/test/util.cpp index b8f2117eeff..97bad47039d 100644 --- a/ngraph/test/util.cpp +++ b/ngraph/test/util.cpp @@ -183,6 +183,7 @@ public: nodes.push_back(A); nodes.push_back(B); nodes.push_back(C); + func->get_rt_info()["version"] = std::make_shared>(10); } bool CompareNodeVector(const std::vector>& orig, @@ -234,6 +235,11 @@ TEST_F(CloneTest, clone_nodes_partial) { TEST_F(CloneTest, clone_function_full) { auto cloned_func = clone_function(*func, node_map); ASSERT_TRUE(CompareNodeVector(func->get_ops(), cloned_func->get_ops(), node_map)); + ASSERT_EQ(cloned_func->get_rt_info().size(), func->get_rt_info().size()); + ASSERT_TRUE(cloned_func->get_rt_info().count("version")); + auto ver = std::dynamic_pointer_cast>(cloned_func->get_rt_info().at("version")); + ASSERT_NE(nullptr, ver); + ASSERT_EQ(10, ver->get()); } TEST(graph_util, clone_multiple_results) {