Skip to content

Commit a49c19a

Browse files
evkotovmsmykx-intel
authored andcommitted
Revise Transformation docs: python API (openvinotoolkit#26008)
### Details: - MatcherPass doc - ModelPass doc ### Tickets: - CVS-76333 --------- Co-authored-by: Maciej Smyk <maciejx.smyk@intel.com>
1 parent 13cd315 commit a49c19a

File tree

4 files changed

+171
-6
lines changed

4 files changed

+171
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# ! [matcher_pass:ov_matcher_pass_py]
2+
'''
3+
``MatcherPass`` is used for pattern-based transformations.
4+
To create transformation you need:
5+
6+
1. Create a pattern
7+
2. Implement a callback
8+
3. Register the pattern and Matcher
9+
10+
In the next example we define transformation that searches for ``Relu`` layer and inserts after it another
11+
``Relu`` layer.
12+
'''
13+
14+
from openvino.runtime.passes import MatcherPass
15+
from snippets import get_model
16+
17+
class PatternReplacement(MatcherPass):
18+
def __init__(self):
19+
MatcherPass.__init__(self)
20+
relu = WrapType("opset13::Relu")
21+
22+
def callback(matcher: Matcher) -> bool:
23+
root = matcher.get_match_root()
24+
new_relu = ops.relu(root.input(0).get_source_output())
25+
26+
"""Use new operation for additional matching
27+
self.register_new_node(new_relu)
28+
29+
Input->Relu->Result => Input->Relu->Relu->Result
30+
"""
31+
root.input(0).replace_source_output(new_relu.output(0))
32+
return True
33+
34+
self.register_matcher(Matcher(relu, "PatternReplacement"), callback)
35+
36+
37+
'''
38+
After running this code you will see the next:
39+
40+
model ops :
41+
parameter
42+
result
43+
relu
44+
45+
model ops :
46+
parameter
47+
result
48+
relu
49+
new_relu
50+
51+
In oder to run this script you need to export PYTHONPATH as the path to binary OpenVINO python models.
52+
'''
53+
from openvino.runtime.passes import Manager, GraphRewrite, BackwardGraphRewrite, Serialize
54+
from openvino import Model, PartialShape
55+
from openvino.runtime import opset13 as ops
56+
from openvino.runtime.passes import ModelPass, Matcher, MatcherPass, WrapType
57+
58+
class PatternReplacement(MatcherPass):
59+
def __init__(self):
60+
MatcherPass.__init__(self)
61+
relu = WrapType("opset13::Relu")
62+
63+
def callback(matcher: Matcher) -> bool:
64+
root = matcher.get_match_root()
65+
new_relu = ops.relu(root.input(0).get_source_output())
66+
new_relu.set_friendly_name('new_relu')
67+
68+
"""Use new operation for additional matching
69+
self.register_new_node(new_relu)
70+
71+
Input->Relu->Result => Input->Relu->Relu->Result
72+
"""
73+
root.input(0).replace_source_output(new_relu.output(0))
74+
return True
75+
76+
self.register_matcher(Matcher(relu, "PatternReplacement"), callback)
77+
78+
79+
def print_model_ops(model):
80+
print('model ops : ')
81+
for op in model.get_ops():
82+
print(op.get_friendly_name())
83+
print('')
84+
85+
86+
manager = Manager()
87+
manager.register_pass(PatternReplacement())
88+
89+
90+
model = get_model()
91+
print_model_ops(model)
92+
manager.run_passes(model)
93+
print_model_ops(model)
94+
95+
# ! [matcher_pass:ov_matcher_pass_py]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ! [model_pass:ov_model_pass_py]
2+
3+
'''
4+
``ModelPass`` can be used as base class for transformation classes that take entire ``Model`` and proceed it.
5+
To create transformation you need:
6+
1. Define class with ``ModelPass`` as a parent
7+
2. Redefine run_on_model method that will receive ``Model`` as an argument
8+
'''
9+
10+
from openvino.runtime.passes import ModelPass
11+
from snippets import get_model
12+
13+
class MyModelPass(ModelPass):
14+
def __init__(self):
15+
super().__init__()
16+
17+
def run_on_model(self, model):
18+
for op in model.get_ops():
19+
print(op.get_friendly_name())
20+
21+
22+
'''
23+
In this example we define transformation that prints all model operation names.
24+
The next example shows ModelPass-based transformation usage.
25+
We create Model with Relu, Parameter and Result nodes. After running this code you will see names of these three nodes.
26+
In oder to run this script you need to export PYTHONPATH as the path to binary OpenVINO python models.
27+
'''
28+
29+
from openvino.runtime.passes import Manager, GraphRewrite, BackwardGraphRewrite, Serialize
30+
from openvino import Model, PartialShape
31+
from openvino.runtime import opset13 as ops
32+
from openvino.runtime.passes import ModelPass, Matcher, MatcherPass, WrapType
33+
34+
35+
class MyModelPass(ModelPass):
36+
def __init__(self):
37+
super().__init__()
38+
39+
def run_on_model(self, model):
40+
for op in model.get_ops():
41+
print(op.get_friendly_name())
42+
43+
44+
manager = Manager()
45+
manager.register_pass(MyModelPass())
46+
manager.run_passes(get_model())
47+
# ! [model_pass:ov_model_pass_py]

docs/articles_en/documentation/openvino-extensibility/transformation-api/matcher-pass.rst

+14-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,21 @@ Template for MatcherPass transformation class
1717
:language: cpp
1818
:fragment: [graph_rewrite:template_transformation_hpp]
1919

20-
.. doxygensnippet:: docs/articles_en/assets/snippets/template_pattern_transformation.cpp
21-
:language: cpp
22-
:fragment: [graph_rewrite:template_transformation_cpp]
20+
.. tab-set::
21+
22+
.. tab-item:: C++
23+
:sync: cpp
24+
25+
.. doxygensnippet:: docs/articles_en/assets/snippets/template_pattern_transformation.cpp
26+
:language: cpp
27+
:fragment: [graph_rewrite:template_transformation_cpp]
2328

29+
.. tab-item:: Python
30+
:sync: py
31+
32+
.. doxygensnippet:: docs/articles_en/assets/snippets/ov_matcher_pass.py
33+
:language: py
34+
:fragment: [matcher_pass:ov_matcher_pass_py]
2435

2536
To use ``ov::pass::MatcherPass``, you need to complete these steps:
2637

docs/articles_en/documentation/openvino-extensibility/transformation-api/model-pass.rst

+15-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,21 @@ Template for ModelPass transformation class
1717
:language: cpp
1818
:fragment: [model_pass:template_transformation_hpp]
1919

20-
.. doxygensnippet:: docs/articles_en/assets/snippets/template_model_transformation.cpp
21-
:language: cpp
22-
:fragment: [model_pass:template_transformation_cpp]
20+
.. tab-set::
21+
22+
.. tab-item:: C++
23+
:sync: cpp
24+
25+
.. doxygensnippet:: docs/articles_en/assets/snippets/template_model_transformation.cpp
26+
:language: cpp
27+
:fragment: [model_pass:template_transformation_cpp]
28+
29+
.. tab-item:: Python
30+
:sync: py
31+
32+
.. doxygensnippet:: docs/articles_en/assets/snippets/ov_model_pass.py
33+
:language: py
34+
:fragment: [model_pass:ov_model_pass_py]
2335

2436
Using ``ov::pass::ModelPass``, you need to override the ``run_on_model`` method where you will write the transformation code.
2537
Return value is ``true`` if the original model has changed during transformation (new operation was added, or operations replacement was made, or node attributes were changed); otherwise, it is ``false``.

0 commit comments

Comments
 (0)