Skip to content

Commit

Permalink
Gkazanta/update doc master (openvinotoolkit#3413)
Browse files Browse the repository at this point in the history
* Updated transformations docs

* Added RTTI to examples

* Fixed grammar mistakes

* Mention Sinks in NG docs
  • Loading branch information
Gleb Kazantaev authored and mryzhov committed Dec 15, 2020
1 parent 31ac9ac commit 7e47060
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 40 deletions.
67 changes: 30 additions & 37 deletions docs/nGraph_DG/nGraphTransformation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ Transformation library is independent from Inference Engine target library named
and is located in the `inference-engine/src/transformations` directory.

Transformations root directory contains two folders:
* `ngraph_ops` - Contains legacy opset operations needed for nGraph to CNNNetwork conversion.
> **NOTE**: This operation is prohibited inside new plugins until they are not moved to a separate directory with allowed operations.
* `ngraph_ops` - Contains internal opset operations that are common for plugins.
* `transformations` - Includes all transformations, utils, runtime info attributes, and pass managers.
> **NOTE**: Do not use transformation that belongs to `ngraph::pass::ConvertOpSet1ToLegacy` transformations until they are not moved to a separate directory with allowed transformations.

All internal operations and transformations located inside the [Transformation Library](group__ie__transformation__api.html) can be used inside plugins.
All legacy operations and transformations were moved to a legacy library and are not recommended to be used.

### Transformation Flow Layers
Transformation flow in the transformation library has several layers:
Expand All @@ -32,15 +33,15 @@ But if some transformation parts can potentially be reused in other transformati
To decide where to store your transformation code, please follow these rules:

1. If it is a plugin-specific transformation and cannot be reused by other plugins, keep source code inside plugin.
2. If this transformation relates to the OpSetXToOpSetY conversion or it is common optimization, keep sources inside the transformation library.
2. If this transformation relates to opset operation conversion or optimization, keep sources inside the transformation library.

After you decide where to store your transformation code, you can start developing your own nGraph transformation.

## ngraph::Function and graph representation <a name="ngraph_function"></a>

An nGraph function is a simple thing: it stores shared pointers to `ngraph::op::Result` and `ngraph::op::Parameter` operations that are inputs and outputs of the graph.
All other operations hold each other via shared pointers: child operation holds its parent (hard link). If the operation has no consumers and it is not a Result operation
(shared pointer counter is zero), it is destructed and is not accessible anymore. Each operation in `ngraph::Function` has a `std::shared_ptr<ngraph::Node>` type.
nGraph function is a very simple thing: it stores shared pointers to `ngraph::op::Parameter`, `ngraph::op::Result` and `ngraph::op::Sink` operations that are inputs, outputs and sinks of the graph.
Sinks of the graph have no consumers and not included into results vector. All other operations hold each other via shared pointers: child operation holds its parent (hard link). If operation has no consumers and it's not Result or Sink operation
(shared pointer counter is zero) then it will be destructed and won't be accessible anymore. Each operation in `ngraph::Function` has a `std::shared_ptr<ngraph::Node>` type.

For examples of how to build an nGraph function, see the [Build nGraph Function](./build_function.md) page.

Expand All @@ -50,7 +51,7 @@ nGraph has three main transformation types:

* `ngraph::pass::FunctionPass` - straightforward way to work with `ngraph::Function` directly
* `ngraph::pass::MatcherPass` - pattern-based transformation approach
* `ngraph::pass::GraphRewrite` - container for matcher passes
* `ngraph::pass::GraphRewrite` - container for matcher passes needed for efficient execution

![transformations_structure]

Expand Down Expand Up @@ -87,14 +88,15 @@ To use `ngraph::pass::MatcherPass`, you need to complete these steps:
So let's go through each of these steps.

### Create a pattern
Pattern is a single root `ngraph::Function`. But the only difference is that you do not need to create a function object, you just need to create and connect nGraph or special pattern operations. Then you need to take the last created operation and put it as a root of the pattern. This root node will be used as a root node in pattern matching.
Pattern is a single root `ngraph::Function`. But the only difference is that you do not need to create a function object, you just need to create and connect opset or special pattern operations.
Then you need to take the last created operation and put it as a root of the pattern. This root node will be used as a root node in pattern matching.
> **NOTE**: Any nodes in a pattern that have no consumers and are not registered as root will not be used in pattern matching.
@snippet example_ngraph_utils.cpp pattern:simple_example

The `Parameter` operation in the example above has type and shape specified. These attributes are needed only to create Parameter operation class and will not be used in pattern matching.

For instructions on how to match a pattern where `ShapeOf` takes any operation as an input, follow the [pattern matching](#pattern_matching) section.
For more pattern examples, refer to the [pattern matching](#pattern_matching) section.

### Implement callback
Callback is an action applied to every pattern entrance. In general, callback is the lambda function that takes Matcher object with detected subgraph.
Expand Down Expand Up @@ -153,6 +155,8 @@ And then creates map from registered MatcherPasses. That helps to avoid addition
![graph_rewrite_efficient_search]
> **NOTE**: GraphRewrite execution algorithm cannot be set manually and depends only on root nodes registered inside MatcherPasses.
## Pattern Matching <a name="pattern_matching"></a>
Sometimes patterns cannot be expressed via regular nGraph operations or it is too complicated.
Expand Down Expand Up @@ -255,7 +259,7 @@ When developing a transformation, you need to follow these transformation rules:
###1. Operation Set (OpSet)
Use the latest version of OpSet in your transformation. An exception is ConvertOpSetXToOpSetY transformations, where you must use operations from OpSetX and OpSetY.
Use the latest version of OpSet in your transformation. An exception is op_conversion transformations, where different opsets can be used.
@snippet example_ngraph_utils.cpp ngraph:include
Expand Down Expand Up @@ -399,33 +403,22 @@ NGRAPH_ENABLE_VISUALIZE_TRACING=1 - enables visualization after each transforma
## Disabling/Enabling specific transformations for plugin X <a name="disabling_transformation"></a>
This topic is mostly related to conversion to legacy opset and plugins that are based on CNNNetwork. But this mechanism still can be applied for other cases.
Let's suppose that plugin X enabled the `opset3::StridedSlice` operation support and you want to disable the `ngraph::pass::ConvertStridedSliceToCrop` transformation for plugin X.
To do this, you need to create a callback on plugin side and pass it to transformation. And also you need to update particular transformation to use this callback.
In transformation library, we provide plugins transformations like CommonOptimizations, which contains predefined sequence of transformations.
We also provide a tool that helps to disable or partially disable particular transformations in a transformation pipeline.
For example, if a plugin uses the CommonOptimization transformation and needs to disable the ConvertGELU transformation, then inside the plugin we have to take the PassConfig instance
from pass::Manger and call disable method.
```cpp
// Update callback to be able to use m_transformation_callback if this transformation based on GraphRewrite.
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher &m) {
...
}
// Use transformation_callback not to execute transformation if callback returns true for given node
if (m_transformation_callback(node)) {
return false;
}
// Implement transformation callback and pass it directly to transformation or pass::Manager
const auto transformations_callback = [](const std::shared_ptr<const ::ngraph::Node> &node) -> bool {
return std::dynamic_pointer_cast<const ::ngraph::opset3::StridedSlice>(node) != nullptr;
};
// Register transformation and pass callback to pass::Manager
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::ConvertStridedSliceToCrop>();
// pass::Manager will set callback to all reistered transformations automatically
manager.set_callback(transformations_callback);
manager.run_passes(f);
```
@snippet example_ngraph_utils.cpp ngraph:disable_gelu
In some cases, we need to disable transformation for some condition:
@snippet example_ngraph_utils.cpp ngraph:disable_callback
In some cases, pass::Manager pipelines inside transformations may have transformations disabled by default but enabled inside plugins.
@snippet example_ngraph_utils.cpp ngraph:disabled_by_default
PassConfig instance taken from pass::Manager is shared across all registered transformations including nested transformations. So it does not matter where we work with this object (before passes registration or after).
## Transformations testing <a name="transformations_testing"></a>
Expand Down
4 changes: 2 additions & 2 deletions docs/nGraph_DG/nGraph_basic_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ The nGraph represents neural networks in uniform format. User can create differe

## nGraph Function and Graph Representation <a name="ngraph_function"></a>

nGraph function is a very simple thing: it stores shared pointers to `ngraph::op::Result` and `ngraph::op::Parameter` operations that are inputs and outputs of the graph.
All other operations hold each other via shared pointers: child operation holds its parent (hard link). If operation has no consumers and it's not Result operation
nGraph function is a very simple thing: it stores shared pointers to `ngraph::op::Parameter`, `ngraph::op::Result` and `ngraph::op::Sink` operations that are inputs, outputs and sinks of the graph.
Sinks of the graph have no consumers and not included into results vector. All other operations hold each other via shared pointers: child operation holds its parent (hard link). If operation has no consumers and it's not Result or Sink operation
(shared pointer counter is zero) then it will be destructed and won't be accessible anymore. Each operation in `ngraph::Function` has a `std::shared_ptr<ngraph::Node>` type.

For details on how to build an nGraph Function, see the [Build nGraph Function](./build_function.md) page.
Expand Down
2 changes: 1 addition & 1 deletion docs/snippets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ if(NGRAPH_ONNX_IMPORT_ENABLE)
target_link_libraries(${TARGET_NAME} PRIVATE onnx_importer)
endif()

target_link_libraries(${TARGET_NAME} PRIVATE inference_engine_plugin_api ngraph)
target_link_libraries(${TARGET_NAME} PRIVATE inference_engine_plugin_api ngraph inference_engine_transformations)
63 changes: 63 additions & 0 deletions docs/snippets/example_ngraph_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include <memory>

#include <ngraph/pattern/op/wrap_type.hpp>
#include <transformations/common_optimizations/common_optimizations.hpp>
#include <transformations/op_conversions/convert_gelu.hpp>
#include <transformations/op_conversions/convert_space_to_depth.hpp>
#include <transformations/op_conversions/convert_depth_to_space.hpp>
#include <transformations/op_conversions/convert_pad_to_group_conv.hpp>

// ! [ngraph:include]
#include <ngraph/ngraph.hpp>
Expand Down Expand Up @@ -249,3 +254,61 @@ void visualization_example(std::shared_ptr<ngraph::Function> f) {
manager.run_passes(f);
}
// ! [ngraph:visualize]

void pass_manager_example1(std::shared_ptr<ngraph::Function> f) {
// ! [ngraph:disable_gelu]
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::CommonOptimizations>();

auto pass_config = manager.get_pass_config();
pass_config->disable<ngraph::pass::ConvertGELU>();

manager.run_passes(f);
// ! [ngraph:disable_gelu]
}

void pass_manager_example2(std::shared_ptr<ngraph::Function> f) {
ngraph::pass::Manager manager;
std::function<bool(const std::shared_ptr<const Node>)> transformation_callback;
// ! [ngraph:disable_callback]
// Set callback to particular transformation with specific condition
auto pass_config = manager.get_pass_config();
pass_config->set_callback<ngraph::pass::ConvertSpaceToDepth,
ngraph::pass::ConvertDepthToSpace>(
[](const std::shared_ptr<const Node> &node) -> bool {
return node->input_value(0).get_shape().size() <= 5lu &&
node->input_value(0).get_shape().size() == node->get_output_shape(0).size();
});

// Update transformation to call callback
ngraph::matcher_pass_callback callback = [=](pattern::Matcher &m) {
auto node = m.get_match_root();
if (transformation_callback(node)) {
return false;
}
// transformation code
return false;
};
// ! [ngraph:disable_callback]
}

void pass_manager_example3(std::shared_ptr<ngraph::Function> f) {
std::function<bool(const std::shared_ptr<const Node>)> transformation_callback;
// ! [ngraph:disabled_by_default]
// Example of disabled by default transformation
{
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::ConvertPadToGroupConvolution, false>();
manager.run_passes(f);
}

// Enable disabled by default transformation inside plugin
{
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::CommonOptimizations>();
auto pass_config = manager.get_pass_config();
pass_config->enable<ngraph::pass::ConvertPadToGroupConvolution>();
manager.run_passes(f);
}
// ! [ngraph:disabled_by_default]
}
2 changes: 2 additions & 0 deletions docs/template_plugin/src/template_function_transformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ using namespace ngraph;

// ! [function_pass:template_transformation_cpp]
// template_function_transformation.cpp
NGRAPH_RTTI_DEFINITION(ngraph::pass::MyFunctionTransformation, "MyFunctionTransformation", 0);

bool pass::MyFunctionTransformation::run_on_function(std::shared_ptr<ngraph::Function> f) {
// Example transformation code
NodeVector nodes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MyFunctionTransformation;
// template_function_transformation.hpp
class ngraph::pass::MyFunctionTransformation: public ngraph::pass::FunctionPass {
public:
NGRAPH_RTTI_DECLARATION;
bool run_on_function(std::shared_ptr<ngraph::Function> f) override;
};
// ! [function_pass:template_transformation_hpp]
4 changes: 4 additions & 0 deletions docs/template_plugin/src/template_pattern_transformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ using namespace ngraph;

// ! [graph_rewrite:template_transformation_cpp]
// template_pattern_transformation.cpp
NGRAPH_RTTI_DEFINITION(ngraph::pass::DecomposeDivideMatcher, "DecomposeDivideMatcher", 0);

ngraph::pass::DecomposeDivideMatcher::DecomposeDivideMatcher() {
// Pattern example
auto input0 = pattern::any_input();
Expand Down Expand Up @@ -54,6 +56,8 @@ ngraph::pass::DecomposeDivideMatcher::DecomposeDivideMatcher() {
// ! [graph_rewrite:template_transformation_cpp]

// ! [matcher_pass:relu_fusion]
NGRAPH_RTTI_DEFINITION(ngraph::pass::ReluReluFusionMatcher, "ReluReluFusionMatcher", 0);

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});
Expand Down
2 changes: 2 additions & 0 deletions docs/template_plugin/src/template_pattern_transformation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ class ReluReluFusionMatcher;
*/
class ngraph::pass::DecomposeDivideMatcher: public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
DecomposeDivideMatcher();
};
// ! [graph_rewrite:template_transformation_hpp]

class ngraph::pass::ReluReluFusionMatcher: public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
ReluReluFusionMatcher();
};

0 comments on commit 7e47060

Please sign in to comment.