Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IE] Convert to unsigned NMS:0 ->Gather path #6474

Merged
merged 19 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
214e0fa
inserted Convert to unsigned
pavel-esir Jun 30, 2021
31d5a51
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Jul 9, 2021
38ecf40
moved declarations from hpp into cpp, specification corrected
pavel-esir Jul 9, 2021
aed9faa
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Jul 19, 2021
0351867
added static const modifier
pavel-esir Jul 19, 2021
ce6ddb0
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Aug 2, 2021
e531935
updated convert specification
pavel-esir Aug 2, 2021
b3a01e1
minor corrections
pavel-esir Aug 2, 2021
bbcfabb
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Aug 4, 2021
0d969b3
split into 3 passes(Init, Propogate, Update), renamed final pass to C…
pavel-esir Aug 5, 2021
fbb37bd
added description why transformation is needed
pavel-esir Aug 5, 2021
56f6d25
added matcher for several NMS versions, removed TRANSFORMATIONS_API m…
pavel-esir Aug 5, 2021
57c856e
applied comments:
pavel-esir Aug 5, 2021
1136c3d
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Aug 6, 2021
aed7a3a
removed redundant namespace prefixes
pavel-esir Aug 6, 2021
60989bf
fixed #include <ngraph/pass/graph_rewrite.hpp>
pavel-esir Aug 6, 2021
10fbec5
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Aug 11, 2021
60c067f
removed matcher_scope, debug code, and redundant dynamic_cast
pavel-esir Aug 11, 2021
1956627
Merge remote-tracking branch 'upstream/master' into nms_gather_resolving
pavel-esir Aug 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions docs/ops/movement/Gather_8.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

**Short description**: *Gather* operation takes slices of data of the first input tensor according to the indices
specified with the second input tensor and axis from the third input. Semantics of this operation is identical to
TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) operation.
TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) operation but also includes
support of negative indices.

**Detailed description**

Expand All @@ -15,6 +16,8 @@ TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) oper

Where `data`, `indices` and `axis` are tensors from first, second and third inputs correspondingly, `b` is
the number of batch dimensions. `N` and `M` are numbers of dimensions of `data` and `indices` tensors, respectively.
Allowed values for indices are in the range `[-data.shape[axis], data.shape[axis] - 1]`. If index value exceed allowed
range output data for corresponding index will be filled with zeros (Example 7).

**Attributes**:
* *batch_dims*
Expand Down Expand Up @@ -142,13 +145,23 @@ data = [1, 2, 3, 4, 5]
output = [1, 4, 5]
```

Example 7 with indices out of the range:
```
batch_dims = 0
axis = 0

indices = [3, 10, -20]
data = [1, 2, 3, 4, 5]
output = [4, 0, 0]
```

**Inputs**

* **1**: `data` tensor of type *T* with arbitrary data. **Required.**

* **2**: `indices` tensor of type *T_IND* with indices to gather. 0D tensor (scalar) for indices is also allowed.
The values for indices are in the range `[-data[axis], data[axis] - 1]`.
Negative values of indices indicate reverse indexing from `data[axis]`.
The values for indices are in the range `[-data.shape[axis], data.shape[axis] - 1]`.
Negative values of indices indicate reverse indexing from `data.shape[axis]`.
**Required.**

* **3**: Scalar or 1D tensor `axis` of *T_AXIS* type is a dimension index to gather data from. For example,
Expand Down
11 changes: 9 additions & 2 deletions docs/ops/type/Convert_1.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@

**Detailed description**

Conversion from one supported type to another supported type is always allowed. User must be aware of precision loss and value change caused by range difference between two types. For example, a 32-bit float `3.141592` may be round to a 32-bit int `3`. The result of unsupported conversions is undefined, e.g. conversion of negative signed integer value to any unsigned integer type.
Conversion from one supported type to another supported type is always allowed. User must be aware of precision loss
and value change caused by range difference between two types. For example, a 32-bit float `3.141592` may be round
to a 32-bit int `3`.

Output elements are represented as follows:
Conversion of negative signed integer to unsigned integer value happens in accordance with c++ standard. Notably,
result is the unique value of the destination unsigned type that is congruent to the source integer modulo 2^N (where
N is the bit width of the destination type). For example, when an int32 value `-1` is converted to uint32 the result
will be `uint32 max` which is `4,294,967,295`.

The result of unsupported conversions is undefined. Output elements are represented as follows:

\f[
o_{i} = Convert(a_{i})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <transformations/common_optimizations/dilated_convolution_converter.hpp>
#include <transformations/common_optimizations/binarize_weights.hpp>
#include <transformations/common_optimizations/conv_to_binary_conv.hpp>
#include <transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp>
#include <transformations/common_optimizations/eliminate_unsqueeze_gather.hpp>
#include <transformations/common_optimizations/split_squeeze_concat_fusion.hpp>
#include <transformations/common_optimizations/transpose_sinking.hpp>
Expand Down Expand Up @@ -58,6 +59,8 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr<ngraph::F
manager.register_pass<ngraph::pass::RemoveFilteringBoxesBySize>();
manager.register_pass<ngraph::pass::ConvertQuantizeDequantize>();
manager.register_pass<ngraph::pass::SimplifyShapeOfSubGraph>();
// workaround until dynamism in NMS is not supported
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: until -> while
// workaround while dynamism in NMS is not supported

manager.register_pass<ngraph::pass::ConvertNmsGatherPathToUnsigned>();

auto transpose_sinking = manager.register_pass<ngraph::pass::GraphRewrite>();
transpose_sinking->add_matcher<ngraph::pass::TransposeSinking>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <transformations_visibility.hpp>
#include <ngraph/pass/graph_rewrite.hpp>

namespace ngraph {
namespace pass {

class TRANSFORMATIONS_API ConvertNmsGatherPathToUnsigned;

} // namespace pass
} // namespace ngraph

/**
* @ingroup ie_transformation_common_api
* @brief Converts Gather indices to unsigned if indices are from NMS selected indices output.
* NMS returns -1 for not selected boxes, old version of Gather fill corresponding
* output for such indices with zero.
* But new Gather-8 has support of negative indices indicating counting from the end.
* In order to keep such behaviour (until dynamism is not supported) instead of -1 new
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the same until -> while

* Gather-8 will accept UINT32_MAX which is always outside of the bounds
* and corresponding output for such indices in gather always will be filled with zeros.
*/
class ngraph::pass::ConvertNmsGatherPathToUnsigned: public ngraph::pass::GraphRewrite {
public:
NGRAPH_RTTI_DECLARATION;
ConvertNmsGatherPathToUnsigned();
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "transformations/common_optimizations/split_squeeze_concat_fusion.hpp"
#include "transformations/common_optimizations/transpose_to_reshape.hpp"
#include "transformations/common_optimizations/strides_optimization.hpp"
#include "transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp"
#include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp"
#include "transformations/op_conversions/convert_pad_to_group_conv.hpp"
#include "transformations/op_conversions/convert_divide.hpp"
Expand All @@ -66,7 +67,6 @@
#include "transformations/op_conversions/reduce_l1_decomposition.hpp"
#include "transformations/op_conversions/reduce_l2_decomposition.hpp"
#include "transformations/op_conversions/hswish_decomposition.hpp"
#include "transformations/op_conversions/convert_previous_nms_to_nms_5.hpp"
#include "transformations/op_conversions/hsigmoid_decomposition.hpp"
#include "transformations/op_conversions/log_softmax_decomposition.hpp"
#include "transformations/op_conversions/mvn6_decomposition.hpp"
Expand All @@ -90,6 +90,7 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr<ngraph::
manager.register_pass<ngraph::pass::SimplifyShapeOfSubGraph>();
manager.register_pass<ngraph::pass::ConstantFolding>();
manager.register_pass<ngraph::pass::RemoveFilteringBoxesBySize>(); // Resolves dynamism (replaces NonZero), CF needed
manager.register_pass<ngraph::pass::ConvertNmsGatherPathToUnsigned>(); // workaround until dynamism in NMS is not supported
pavel-esir marked this conversation as resolved.
Show resolved Hide resolved

// TODO: move to KMB
manager.register_pass<ngraph::pass::ConvertQuantizeDequantize>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp"
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset5.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/op/util/broadcast_base.hpp>
#include <ngraph/op/util/gather_base.hpp>
#include <ngraph/rt_info.hpp>
#include <memory>
#include "itt.hpp"
#include "ngraph/node.hpp"

using namespace ngraph;
using namespace std;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: please add some description for each pass in this file: InitNMSPath, PropagateNMSPath, UpdateConvertGather

class InitNMSPath: public pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;

InitNMSPath() {
MATCHER_SCOPE(InitNMSPath);

auto nms_pattern = pattern::wrap_type<opset1::NonMaxSuppression,
opset3::NonMaxSuppression,
opset5::NonMaxSuppression>();

matcher_pass_callback callback = [=](pattern::Matcher &m) {
const auto& out_nodes = m.get_match_root()->output(0).get_target_inputs();
for (const auto& out_node : out_nodes) {
auto& out_rt_info = out_node.get_node()->get_rt_info();
out_rt_info["NMS_SELECTED_INDICES"] = make_shared<VariantWrapper<string>>("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would suggest to have regular rtInfo attribute to make it no copyable.

}
return true;
};

auto m = make_shared<pattern::Matcher>(nms_pattern, matcher_name);
register_matcher(m, callback);
}
};

NGRAPH_RTTI_DEFINITION(InitNMSPath, "InitNMSPath", 0);


class PropagateNMSPath: public pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;

PropagateNMSPath(){
MATCHER_SCOPE(PropagateNMSPath);

auto node_pattern = pattern::wrap_type<
opset8::Squeeze,
opset8::Unsqueeze,
opset8::Reshape,
op::util::BroadcastBase,
opset8::StridedSlice,
opset8::VariadicSplit,
opset8::Concat,
opset8::Convert>();

matcher_pass_callback callback = [=](pattern::Matcher &m) {
auto node = m.get_match_root();
const auto & inputs = node->input_values();
if (any_of(inputs.begin(), inputs.end(), [](const Output<Node> & output) {
return output.get_node()->get_rt_info().count("NMS_SELECTED_INDICES");
})) {
auto & rt_info = node->get_rt_info();
rt_info["NMS_SELECTED_INDICES"] = make_shared<VariantWrapper<string>>("");
}
return true;
};

auto m = make_shared<pattern::Matcher>(node_pattern, matcher_name);
register_matcher(m, callback);
}
};

NGRAPH_RTTI_DEFINITION(PropagateNMSPath, "PropagateNMSPath", 0);

class UpdateConvertGather: public pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;

UpdateConvertGather(){
MATCHER_SCOPE(UpdateConvertGather);

auto node_pattern = pattern::wrap_type<op::util::GatherBase>();

matcher_pass_callback callback = [=](pattern::Matcher &m) {
auto gather = m.get_match_root();
auto indices = gather->input_value(1);

const auto& rt_info = indices.get_node()->get_rt_info();
if (!rt_info.count("NMS_SELECTED_INDICES"))
return false;

auto out_type = (indices.get_element_type() == element::i64 ? element::u64 : element::u32);
auto existing_convert = dynamic_pointer_cast<opset8::Convert>(indices.get_node_shared_ptr());
if (existing_convert && indices.get_target_inputs().size() == 1) {
existing_convert->set_convert_element_type(out_type);
pavel-esir marked this conversation as resolved.
Show resolved Hide resolved
existing_convert->validate_and_infer_types();
} else {
auto new_convert_to_unsigned = make_shared<opset8::Convert>(indices, out_type);
gather->input(1).replace_source_output(new_convert_to_unsigned);
copy_runtime_info(gather, new_convert_to_unsigned);
}
return true;
};

auto m = make_shared<pattern::Matcher>(node_pattern, matcher_name);
register_matcher(m, callback);
}
};

NGRAPH_RTTI_DEFINITION(UpdateConvertGather, "UpdateConvertGather", 0);

pass::ConvertNmsGatherPathToUnsigned::ConvertNmsGatherPathToUnsigned() {
add_matcher<InitNMSPath>();
add_matcher<PropagateNMSPath>();
add_matcher<UpdateConvertGather>();
}

NGRAPH_RTTI_DEFINITION(pass::ConvertNmsGatherPathToUnsigned, "ConvertNmsGatherPathToUnsigned", 0);
Loading