nGraph Transformations refactoring (#931)
This PR introduces next changes: 1. Transformations *_tbl.hpp files were replaced with direct registration in cpp files. 2. Plugins use pass::Manager to call conversion passes. 3. Transformations callback was moved to PassBase class as there is no more need to keep it in separate class 4. All pattern based transformations must be inherited from MatcherPass class. GraphRewrite class will be used only for matchers registration and execution on function. MatcherPass class adds new features to pattern-based transformations approach: * Allows to run matcher pass on a single node. * Operations that were created inside transformation callback can be added to execution list to be available for pattern matching within single GraphRewrite. 5. GraphRewrite MatchClosure was replaced with MatcherPass. So all matchers will be registered as a MatcherPass. 6. Added pass::Manager::clear_state() method to avoid dependency with nodes that no longer belongs to function after replacement. 7. Some representative transformations were updated to use MatcherPass as an example. 8. Mul->Add sequence fusion transformation was replaced with LinOpSequenceFusion. 9. Pattern and callback registration code was moved to class c-tors (will be finished for remaining passes in other PR) . 10. Updated pass::Manager to get pass names only when NGRAPH_PROFILE_PASS_ENABLE enabled. 11. Moving towards removing PassProperty. 12. Added ngraph::pattern::wrap_type<T>(inputs, pred) to simplify pattern creation. 13. GraphRewrite was updated to execute MatcherPass more efficient.
This commit is contained in:
@@ -86,7 +86,8 @@ void TemplatePlugin::ExecutableNetwork::CompileGraph(const std::shared_ptr<const
|
||||
// Example: register CommonOptimizations transformation from transformations library
|
||||
passManager.register_pass<ngraph::pass::CommonOptimizations>();
|
||||
// Example: register plugin specific transformation
|
||||
passManager.register_pass<ngraph::pass::MyPatternBasedTransformation>();
|
||||
passManager.register_pass<ngraph::pass::DecomposeDivideMatcher>();
|
||||
passManager.register_pass<ngraph::pass::ReluReluFusionMatcher>();
|
||||
// Register any other transformations
|
||||
// ..
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using namespace ngraph;
|
||||
|
||||
// ! [function_pass:template_transformation_cpp]
|
||||
// template_function_transformation.cpp
|
||||
bool MyFunctionTransformation::run_on_function(std::shared_ptr<ngraph::Function> f) {
|
||||
bool pass::MyFunctionTransformation::run_on_function(std::shared_ptr<ngraph::Function> f) {
|
||||
// Example transformation code
|
||||
std::vector<std::shared_ptr<Node> > nodes;
|
||||
|
||||
|
||||
@@ -9,9 +9,17 @@
|
||||
|
||||
#include <ngraph/ngraph.hpp>
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
|
||||
class MyFunctionTransformation;
|
||||
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
||||
// ! [function_pass:template_transformation_hpp]
|
||||
// template_function_transformation.hpp
|
||||
class MyFunctionTransformation: public ngraph::pass::FunctionPass {
|
||||
class ngraph::pass::MyFunctionTransformation: public ngraph::pass::FunctionPass {
|
||||
public:
|
||||
MyFunctionTransformation() : FunctionPass() {}
|
||||
|
||||
|
||||
@@ -3,21 +3,23 @@
|
||||
//
|
||||
|
||||
#include "template_pattern_transformation.hpp"
|
||||
#include "template_function_transformation.hpp"
|
||||
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
#include <ngraph/pattern/op/wrap_type.hpp>
|
||||
|
||||
using namespace ngraph;
|
||||
|
||||
// ! [graph_rewrite:template_transformation_cpp]
|
||||
// template_pattern_transformation.cpp
|
||||
void ngraph::pass::MyPatternBasedTransformation::transform() {
|
||||
ngraph::pass::DecomposeDivideMatcher::DecomposeDivideMatcher() {
|
||||
// Pattern example
|
||||
auto input0 = std::make_shared<pattern::op::Label>(element::i64, Shape{1, 1, 1, 1});
|
||||
auto input1 = std::make_shared<pattern::op::Label>(element::i64, Shape{1, 1, 1, 1});
|
||||
auto input0 = std::make_shared<pattern::op::Label>(element::f32, Shape{});
|
||||
auto input1 = std::make_shared<pattern::op::Label>(element::f32, Shape{});
|
||||
auto div = std::make_shared<ngraph::opset3::Divide>(input0, input1);
|
||||
|
||||
ngraph::graph_rewrite_callback callback = [](pattern::Matcher& m) {
|
||||
ngraph::matcher_pass_callback callback = [](pattern::Matcher& m) {
|
||||
auto div = std::dynamic_pointer_cast<ngraph::opset3::Divide> (m.get_match_root());
|
||||
// We can not apply this transformation in case with integer input data type
|
||||
if (!div || div->input(0).get_element_type().is_integral()) {
|
||||
@@ -43,9 +45,94 @@ void ngraph::pass::MyPatternBasedTransformation::transform() {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Register pattern with divide operaiton as a pattern root node
|
||||
// Register pattern with Divide operation as a pattern root node
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(div, "ConvertDivide");
|
||||
// Register Matcher
|
||||
this->add_matcher(m, callback, ngraph::pass::PassProperty::CHANGE_DYNAMIC_STATE);
|
||||
this->register_matcher(m, callback);
|
||||
}
|
||||
// ! [graph_rewrite:template_transformation_cpp]
|
||||
|
||||
// ! [matcher_pass:relu_fusion]
|
||||
ngraph::pass::ReluReluFusionMatcher::ReluReluFusionMatcher() {
|
||||
auto m_relu1 = ngraph::pattern::wrap_type<ngraph::opset3::Relu>(pattern::consumers_count(1));
|
||||
auto m_relu2 = ngraph::pattern::wrap_type<ngraph::opset3::Relu>({m_relu1});
|
||||
|
||||
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
|
||||
// Map that helps to connect labels with matched outputs
|
||||
auto& node_to_output = m.get_pattern_value_map();
|
||||
|
||||
// Create new Relu operation and add register it for additional execution
|
||||
auto new_relu = register_new_node<ngraph::opset3::Relu>(
|
||||
node_to_output.at(m_relu1).get_node_shared_ptr()->input_value(0));
|
||||
|
||||
// Copy runtime info attributes to newly created operation
|
||||
ngraph::copy_runtime_info(m.get_matched_nodes(), new_relu);
|
||||
|
||||
// Save last Relu name to new Relu operation
|
||||
new_relu->set_friendly_name(m.get_match_root()->get_friendly_name());
|
||||
|
||||
// Replace Relu->Relu with Relu
|
||||
ngraph::replace_node(m.get_match_root(), new_relu);
|
||||
|
||||
// Return true as the root node was changed
|
||||
return true;
|
||||
};
|
||||
|
||||
// Register pattern with Relu operation as a pattern root node
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(m_relu2, "ReluReluFusion");
|
||||
// Register Matcher
|
||||
this->register_matcher(m, callback);
|
||||
}
|
||||
// ! [matcher_pass:relu_fusion]
|
||||
|
||||
void run_matcher_on_node(std::shared_ptr<ngraph::Node> node) {
|
||||
// ! [matcher_pass:run_on_node]
|
||||
if (ngraph::pass::DecomposeDivideMatcher().apply(node)) {
|
||||
// successful execution (root node was replaced)
|
||||
}
|
||||
// ! [matcher_pass:run_on_node]
|
||||
}
|
||||
|
||||
void run_matcher_with_manager(std::shared_ptr<ngraph::Function> f) {
|
||||
// ! [matcher_pass:manager]
|
||||
// Two matchers will run independently (two independent graph traversals)
|
||||
// pass::Manager automatically creates GraphRewrite container for each MatcherPass
|
||||
pass::Manager manager;
|
||||
manager.register_pass<ngraph::pass::DecomposeDivideMatcher>();
|
||||
manager.register_pass<ngraph::pass::ReluReluFusionMatcher>();
|
||||
manager.run_passes(f);
|
||||
// ! [matcher_pass:manager]
|
||||
}
|
||||
|
||||
void run_matcher_with_manager2(std::shared_ptr<ngraph::Function> f) {
|
||||
// ! [matcher_pass:manager2]
|
||||
// Register anchor GraphRewrite pass inside manager that will execute two matchers simultaneously
|
||||
pass::Manager manager;
|
||||
auto anchor = manager.register_pass<ngraph::pass::GraphRewrite>();
|
||||
anchor->add_matcher<ngraph::pass::DecomposeDivideMatcher>();
|
||||
anchor->add_matcher<ngraph::pass::ReluReluFusionMatcher>();
|
||||
manager.run_passes(f);
|
||||
// ! [matcher_pass:manager2]
|
||||
}
|
||||
|
||||
void run_matcher_with_manager3(std::shared_ptr<ngraph::Function> f) {
|
||||
// ! [matcher_pass:manager3]
|
||||
pass::Manager manager;
|
||||
manager.register_pass<ngraph::pass::MyFunctionTransformation>();
|
||||
// Two matchers will run independently (two independent graph traversals)
|
||||
// pass::Manager automatically creates GraphRewrite container for each MatcherPass
|
||||
manager.register_pass<ngraph::pass::DecomposeDivideMatcher>();
|
||||
manager.register_pass<ngraph::pass::ReluReluFusionMatcher>();
|
||||
manager.run_passes(f);
|
||||
// ! [matcher_pass:manager3]
|
||||
}
|
||||
|
||||
void run_matcher_with_gr(std::shared_ptr<ngraph::Function> f) {
|
||||
// ! [matcher_pass:graph_rewrite]
|
||||
// Two matcher passes will run simultaneously in a single graph traversal
|
||||
ngraph::pass::GraphRewrite pass;
|
||||
pass.add_matcher<ngraph::pass::DecomposeDivideMatcher>();
|
||||
pass.add_matcher<ngraph::pass::ReluReluFusionMatcher>();
|
||||
pass.run_on_function(f);
|
||||
// ! [matcher_pass:graph_rewrite]
|
||||
}
|
||||
|
||||
@@ -12,20 +12,21 @@
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
|
||||
class MyPatternBasedTransformation;
|
||||
class DecomposeDivideMatcher;
|
||||
class ReluReluFusionMatcher;
|
||||
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
||||
// ! [graph_rewrite:template_transformation_hpp]
|
||||
// template_pattern_transformation.hpp
|
||||
class ngraph::pass::MyPatternBasedTransformation: public ngraph::pass::GraphRewrite {
|
||||
class ngraph::pass::DecomposeDivideMatcher: public ngraph::pass::MatcherPass {
|
||||
public:
|
||||
MyPatternBasedTransformation() : GraphRewrite() {
|
||||
transform();
|
||||
}
|
||||
|
||||
private:
|
||||
void transform();
|
||||
DecomposeDivideMatcher();
|
||||
};
|
||||
// ! [graph_rewrite:template_transformation_hpp]
|
||||
|
||||
class ngraph::pass::ReluReluFusionMatcher: public ngraph::pass::MatcherPass {
|
||||
public:
|
||||
ReluReluFusionMatcher();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user