Save Parameters order during IR deserialization (#9286)
* Save Parameters order during IR deserialization * Add test to check inputs/outputs in IR
This commit is contained in:
committed by
GitHub
parent
b5238e55e1
commit
cf15cbd301
@@ -423,6 +423,9 @@ std::shared_ptr<ngraph::Function> XmlDeserializer::parse_function(
|
||||
std::vector<size_t /*layer-id*/> outputs;
|
||||
std::unordered_set<std::string> opName;
|
||||
|
||||
std::vector<size_t> order;
|
||||
std::set<size_t> dfs_used_nodes;
|
||||
std::map<size_t /*to-layer-id*/, std::vector<edge>> edges;
|
||||
// Read all layers and store their parameters in params map
|
||||
FOREACH_CHILD (node, root.child("layers"), "layer") {
|
||||
auto node_param = parseGenericParams(node);
|
||||
@@ -433,11 +436,15 @@ std::shared_ptr<ngraph::Function> XmlDeserializer::parse_function(
|
||||
if (node_param.type == "Result" || node_param.type == "Assign") {
|
||||
outputs.push_back(node_param.layerId);
|
||||
}
|
||||
if (node_param.type == "Parameter") {
|
||||
// Save Parameters order according to order in XML.
|
||||
// To do so, handle nodes manually and ignore during DFS
|
||||
dfs_used_nodes.insert(node_param.layerId);
|
||||
order.push_back(node_param.layerId);
|
||||
edges[node_param.layerId] = {};
|
||||
}
|
||||
}
|
||||
|
||||
std::map<size_t /*to-layer-id*/, std::vector<edge>> edges;
|
||||
std::map<size_t, std::shared_ptr<ngraph::Node>> id_to_node;
|
||||
|
||||
// Read all edges and store them for further usage
|
||||
FOREACH_CHILD (_ec, root.child("edges"), "edge") {
|
||||
size_t fromLayer = XMLParseUtils::GetUIntAttr(_ec, "from-layer");
|
||||
@@ -448,12 +455,10 @@ std::shared_ptr<ngraph::Function> XmlDeserializer::parse_function(
|
||||
}
|
||||
|
||||
// Run DFS starting from outputs to get nodes topological order
|
||||
std::set<size_t> used;
|
||||
std::vector<size_t> order;
|
||||
std::function<void(size_t)> dfs = [&edges, &order, &used, &dfs](const size_t id) {
|
||||
if (used.count(id))
|
||||
std::function<void(size_t)> dfs = [&edges, &order, &dfs_used_nodes, &dfs](const size_t id) {
|
||||
if (dfs_used_nodes.count(id))
|
||||
return;
|
||||
used.insert(id);
|
||||
dfs_used_nodes.insert(id);
|
||||
for (auto& edge : edges[id]) {
|
||||
dfs(edge.fromLayerId);
|
||||
}
|
||||
@@ -464,7 +469,7 @@ std::shared_ptr<ngraph::Function> XmlDeserializer::parse_function(
|
||||
// OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "ConstructNgraphNodes");
|
||||
|
||||
FunctionNodes func_nodes;
|
||||
|
||||
std::map<size_t, std::shared_ptr<ngraph::Node>> id_to_node;
|
||||
std::map<std::string, std::shared_ptr<ngraph::Node>> variable_id_to_read_value;
|
||||
|
||||
// Following topological order create nGraph operations
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "ie_core.hpp"
|
||||
|
||||
#include <openvino/runtime/runtime.hpp>
|
||||
#include <ngraph/function.hpp>
|
||||
#include <ngraph/opsets/opset5.hpp>
|
||||
|
||||
using namespace ngraph;
|
||||
|
||||
#ifndef IR_SERIALIZATION_MODELS_PATH // should be already defined by cmake
|
||||
# error "IR_SERIALIZATION_MODELS_PATH is not defined"
|
||||
#endif
|
||||
@@ -92,3 +98,74 @@ TEST_F(SerializationDeterministicityTest, SerializeToBlob) {
|
||||
ASSERT_TRUE(expected.layerCount() == result.layerCount());
|
||||
ASSERT_TRUE(expected.getInputShapes() == result.getInputShapes());
|
||||
}
|
||||
|
||||
class DeterministicityTest : public ::testing::Test {
|
||||
protected:
|
||||
std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
|
||||
std::string m_out_xml_path = test_name + ".xml";
|
||||
std::string m_out_bin_path = test_name + ".bin";
|
||||
|
||||
void TearDown() override {
|
||||
std::remove(m_out_xml_path.c_str());
|
||||
std::remove(m_out_bin_path.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DeterministicityTest, IRInputsOrder) {
|
||||
const std::vector<std::string> friend_names = {"A", "B", "C"};
|
||||
|
||||
auto a = std::make_shared<opset5::Parameter>(element::f32, Shape{2, 2});
|
||||
auto b = std::make_shared<opset5::Parameter>(element::f32, Shape{2, 2});
|
||||
auto add = std::make_shared<opset5::Add>(a, b);
|
||||
auto c = std::make_shared<opset5::Parameter>(element::f32, Shape{2, 2});
|
||||
auto relu = std::make_shared<opset5::Relu>(c);
|
||||
auto add2 = std::make_shared<opset5::Add>(add, relu);
|
||||
auto res = std::make_shared<opset5::Result>(add2);
|
||||
|
||||
a->set_friendly_name(friend_names[0]);
|
||||
b->set_friendly_name(friend_names[1]);
|
||||
c->set_friendly_name(friend_names[2]);
|
||||
|
||||
auto model = std::make_shared<ov::Model>(NodeVector{res}, ParameterVector{a, b, c});
|
||||
|
||||
ov::runtime::Core core;
|
||||
auto serialize = ov::pass::Serialize(m_out_xml_path, m_out_bin_path);
|
||||
serialize.run_on_function(model);
|
||||
auto serialized_func = core.read_model(m_out_xml_path);
|
||||
|
||||
for (size_t i = 0; i < friend_names.size(); i++) {
|
||||
auto param = serialized_func->get_parameters()[i];
|
||||
ASSERT_EQ(i, serialized_func->get_parameter_index(param));
|
||||
ASSERT_STREQ(friend_names[i].c_str(), param->get_friendly_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DeterministicityTest, IROutputsOrder) {
|
||||
const std::vector<std::string> friend_names = {"D", "E", "F"};
|
||||
|
||||
auto a = std::make_shared<opset5::Parameter>(element::f32, Shape{4, 4});
|
||||
auto axis_1 = ngraph::opset5::Constant::create(element::i64, Shape{}, {1});
|
||||
auto split1 = std::make_shared<opset5::Split>(a, axis_1, 2);
|
||||
auto res1 = std::make_shared<opset5::Result>(split1->output(0));
|
||||
auto relu = std::make_shared<opset5::Relu>(split1->output(1));
|
||||
auto split2 = std::make_shared<opset5::Split>(relu, axis_1, 2);
|
||||
auto res2 = std::make_shared<opset5::Result>(split2->output(0));
|
||||
auto res3 = std::make_shared<opset5::Result>(split2->output(1));
|
||||
|
||||
res1->set_friendly_name(friend_names[0]);
|
||||
res2->set_friendly_name(friend_names[1]);
|
||||
res3->set_friendly_name(friend_names[2]);
|
||||
|
||||
auto model = std::make_shared<ov::Model>(NodeVector{res1, res2, res3}, ParameterVector{a});
|
||||
|
||||
ov::runtime::Core core;
|
||||
auto serialize = ov::pass::Serialize(m_out_xml_path, m_out_bin_path);
|
||||
serialize.run_on_function(model);
|
||||
auto serialized_func = core.read_model(m_out_xml_path);
|
||||
|
||||
for (size_t i = 0; i < friend_names.size(); i++) {
|
||||
auto out = serialized_func->get_results()[i];
|
||||
ASSERT_EQ(i, serialized_func->get_result_index(out));
|
||||
ASSERT_STREQ(friend_names[i].c_str(), out->get_friendly_name().c_str());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user