Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Steve Yoo committed 2021-07-09 08:04:43 +09:00
commit 14020554d2
116 files changed
+1305 -7318

No files matched your search

+1 -6
View File
@@ -2,7 +2,6 @@
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
@@ -11,9 +10,7 @@
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
*.py text eol=lf
###############################################################################
# Set the merge driver for project and solution files
#
@@ -36,7 +33,6 @@
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
@@ -45,7 +41,6 @@
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
@@ -63,9 +58,9 @@
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
*.PNG filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.vsdx filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text
+3 -3
View File
@@ -13,9 +13,9 @@ include(CPackComponent)
set(IE_CPACK_IE_DIR deployment_tools/inference_engine)
function(ie_cpack_set_library_dir)
if(WIN32)
set(IE_CPACK_LIBRARY_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER}/${CMAKE_BUILD_TYPE} PARENT_SCOPE)
set(IE_CPACK_RUNTIME_PATH ${IE_CPACK_IE_DIR}/bin/${ARCH_FOLDER}/${CMAKE_BUILD_TYPE} PARENT_SCOPE)
set(IE_CPACK_ARCHIVE_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER}/${CMAKE_BUILD_TYPE} PARENT_SCOPE)
set(IE_CPACK_LIBRARY_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER}/$<CONFIG> PARENT_SCOPE)
set(IE_CPACK_RUNTIME_PATH ${IE_CPACK_IE_DIR}/bin/${ARCH_FOLDER}/$<CONFIG> PARENT_SCOPE)
set(IE_CPACK_ARCHIVE_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER}/$<CONFIG> PARENT_SCOPE)
else()
set(IE_CPACK_LIBRARY_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER} PARENT_SCOPE)
set(IE_CPACK_RUNTIME_PATH ${IE_CPACK_IE_DIR}/lib/${ARCH_FOLDER} PARENT_SCOPE)
+14 -11
View File
@@ -31,19 +31,18 @@ macro(ie_parse_ci_build_number)
set(IE_VERSION_MAJOR ${CMAKE_MATCH_1})
set(IE_VERSION_MINOR ${CMAKE_MATCH_2})
set(IE_VERSION_PATCH ${CMAKE_MATCH_3})
set(has_ci_version ON)
else()
set(IE_VERSION_MAJOR 0)
set(IE_VERSION_MINOR 0)
set(IE_VERSION_PATCH 0)
endif()
if(NOT DEFINED repo_root)
message(FATAL_ERROR "repo_root is not defined")
endif()
if(DEFINED IEDevScripts_DIR AND DEFINED OpeenVINO_SOURCE_DIR AND NOT DEFINED custom_build)
set(ie_version_hpp "${IE_MAIN_SOURCE_DIR}/include/ie_version.hpp")
macro(ie_get_hpp_version)
if(NOT DEFINED OpenVINO_SOURCE_DIR)
return()
endif()
set(ie_version_hpp "${OpenVINO_SOURCE_DIR}/inference-engine/include/ie_version.hpp")
if(NOT EXISTS ${ie_version_hpp})
message(FATAL_ERROR "File ie_version.hpp with IE_VERSION definitions is not found")
endif()
@@ -57,6 +56,13 @@ macro(ie_parse_ci_build_number)
string(REGEX REPLACE ".+IE_VERSION_PATCH[ ]+([0-9]+).*" "\\1"
IE_VERSION_PATCH_HPP "${IE_VERSION_PARTS}")
set(ie_hpp_version_is_found ON)
endmacro()
# detect OpenVINO version via ie_version.hpp
ie_get_hpp_version()
if(ie_hpp_version_is_found)
foreach(var IE_VERSION_MAJOR IE_VERSION_MINOR IE_VERSION_PATCH)
if(DEFINED ${var} AND NOT ${var} EQUAL ${var}_HPP)
message(FATAL_ERROR "${var} parsed from CI_BUILD_NUMBER (${${var}}) \
@@ -66,13 +72,10 @@ macro(ie_parse_ci_build_number)
set(${var} ${${var}_HPP})
endif()
endforeach()
elseif(has_ci_version)
message(WARNING "OpeenVINO_SOURCE_DIR is not defined. No way to compare versions")
else()
message(WARNING "No way to detect OpenVINO version. Supposing 0.0.0.0")
endif()
set(IE_VERSION "${IE_VERSION_MAJOR}.${IE_VERSION_MINOR}.${IE_VERSION_PATCH}")
message(STATUS "OpenVINO version is ${IE_VERSION}")
endmacro()
if (DEFINED ENV{CI_BUILD_NUMBER})
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 130 B

+16 -20
View File
@@ -4,33 +4,29 @@
**Category**: Arithmetic unary operation
**Short description**: *Asinh* performs element-wise hyperbolic inverse sine (arcsinh) operation with given tensor.
**Short description**: *Asinh* performs element-wise inverse hyperbolic sine operation (arcsinh) on a given input tensor.
**Attributes**:
No attributes available.
**Inputs**
* **1**: A tensor of type *T*. **Required.**
**Outputs**
* **1**: The result of element-wise asinh operation. A tensor of type *T*.
**Types**
* *T*: any floating point type.
*Asinh* does the following with the input tensor *a*:
**Detailed description**: *Asinh* performs element-wise inverse hyperbolic sine operation on a given input tensor, based on the following mathematical formula:
\f[
a_{i} = asinh(a_{i})
\f]
**Examples**
**Attributes**: *Asinh* operation has no attributes.
*Example 1*
**Inputs**
* **1**: A tensor of type *T* and arbitrary shape. **Required.**
**Outputs**
* **1**: The result of element-wise *Asinh* operation. A tensor of type *T* and the same shape as input tensor.
**Types**
* *T*: any numeric type.
**Example**
```xml
<layer ... type="Asinh">
+16 -20
View File
@@ -4,33 +4,29 @@
**Category**: Arithmetic unary operation
**Short description**: *Cosh* performs element-wise hyperbolic cosine operation with given tensor.
**Short description**: *Cosh* performs element-wise hyperbolic cosine operation on a given input tensor.
**Attributes**:
No attributes available.
**Inputs**
* **1**: An tensor of type *T*. **Required.**
**Outputs**
* **1**: The result of element-wise cosh operation. A tensor of type *T*.
**Types**
* *T*: any numeric type.
*Cosh* does the following with the input tensor *a*:
**Detailed description**: *Cosh* performs element-wise hyperbolic cosine (cosh) operation on a given input tensor, based on the following mathematical formula:
\f[
a_{i} = cosh(a_{i})
\f]
**Examples**
**Attributes**: *Cosh* operation has no attributes.
*Example 1*
**Inputs**
* **1**: A tensor of type *T* and arbitrary shape. **Required.**
**Outputs**
* **1**: The result of element-wise *Cosh* operation. A tensor of type *T* and the same shape as the input tensor.
**Types**
* *T*: any numeric type.
**Example**
```xml
<layer ... type="Cosh">
+62 -21
View File
@@ -4,46 +4,87 @@
**Category**: *Data movement*
**Short description**: The *BatchToSpace* operation reshapes the "batch" dimension 0 into N - 1 dimensions of shape `block_shape` + [batch] and interleaves these blocks back into the grid defined by the spatial dimensions `[1, ..., N - 1]` to obtain a result with the same rank as `data` input. The spatial dimensions of this intermediate result are then optionally cropped according to `crops_begin` and `crops_end` to produce the output. This is the reverse of the *SpaceToBatch* operation.
**Short description**: *BatchToSpace* operation permutes the batch dimension on a given input `data` into blocks in the spatial dimensions specified by `block_shape` input. The spatial dimensions are then optionally cropped according to `crops_begin` and `crops_end` inputs to produce the output.
**Detailed description**:
**Detailed description**
The *BatchToSpace* operation is similar to the TensorFlow* operation [BatchToSpaceND](https://www.tensorflow.org/api_docs/python/tf/batch_to_space_nd)
*BatchToSpace* operation is equivalent to the following operation steps on the input `data` with shape `[batch, D_1, D_2, ..., D_{N-1}]` and `block_shape`, `crops_begin`, `crops_end` inputs with shape `[N]` to produce the output tensor \f$y\f$.
The operation is equivalent to the following transformation of the input tensors `data` with shape `[batch, D_1, D_2 ... D_{N-1}]` and `block_shape`, `crops_begin`, `crops_end` of shape `[N]` to *Y* output tensor.
1. Reshape `data` input to produce a tensor of shape \f$[B_1, \dots, B_{N - 1}, \frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, D_1, D_2, \dots, D_{N - 1}]\f$
\f[x^{\prime} = reshape(data, [B_1, \dots, B_{N - 1}, \frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, D_1, D_2, \dots, D_{N - 1}])\f]
note: B_0 is expected to be 1.
x' = reshape(`data`, [B_1, ..., B_{N - 1}, batch / (B_1 * ... B_{N - 1}), D_1, D_2, ..., D_{N - 1}]), where B_i = block_shape[i]
2. Permute dimensions of \f$x^{\prime}\f$ to produce a tensor of shape \f$[\frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, D_1, B_1, D_2, B_2, \dots, D_{N-1}, B_{N - 1}]\f$
\f[x^{\prime\prime} = transpose(x', [N, N + 1, 0, N + 2, 1, \dots, N + N - 1, N - 1])\f]
x'' = transpose(x', [N, N + 1, 0, N + 2, 1, ..., N + N - 1, N - 1])
3. Reshape \f$x^{\prime\prime}\f$ to produce a tensor of shape \f$[\frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, D_1 \times B_1, D_2 \times B_2, \dots, D_{N - 1} \times B_{N - 1}]\f$
\f[x^{\prime\prime\prime} = reshape(x^{\prime\prime}, [\frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, D_1 \times B_1, D_2 \times B_2, \dots, D_{N - 1} \times B_{N - 1}])\f]
x''' = reshape(x'', [batch / (B_1 * ... * B_{N - 1}), D_1 * B_1, D_2 * B_2, ... , D_{N - 1} * B_{N - 1}])
4. Crop the start and end of spatial dimensions of \f$x^{\prime\prime\prime}\f$ according to `crops_begin` and `crops_end` inputs to produce the output \f$y\f$ of shape:
\f[\left[\frac{batch}{\left(B_1 \times \dots \times B_{N - 1}\right)}, crop(D_1 \times B_1, CB_1, CE_1), crop(D_2 \times B_2, CB_2, CE_2), \dots , crop(D_{N - 1} \times B_{N - 1}, CB_{N - 1}, CE_{N - 1})\right]\f]
Crop the start and end of dimensions according to `crops_begin`, `crops_end` to produce the output of shape:
note: `crops_begin[0], crops_end[0]` are expected to be 0.
`y = [batch / (B_1 * ... * B_{N - 1}), crop(D_1 * B_1, crops_begin[1], crops_end[1]), crop(D_2 * B_2, crops_begin[2], crops_end[2]), ... , crop(D_{N - 1} * B_{N - 1}, crops_begin[N - 1], crops_end[N - 1])]`
Where
**Attributes**
- \f$B_i\f$ = block_shape[i]
- \f$B_0\f$ is expected to be 1
- \f$CB_i\f$ = crops_begin[i]
- \f$CE_i\f$ = crops_end[i]
- \f$CB_0\f$ and \f$CE_0\f$ are expected to be 0
- \f$CB_i + CE_i \leq D_i \times B_i \f$
No attributes available.
*BatchToSpace* operation is the reverse of *SpaceToBatch* operation.
**Attributes**: *BatchToSpace* operation has no attributes.
**Inputs**
* **1**: `data` - input N-D tensor `[batch, D_1, D_2 ... D_{N-1}]` of *T1* type with rank >= 2. **Required.**
* **2**: `block_shape` - input 1-D tensor of *T2* type with shape `[N]` that is equal to the size of `data` input shape. All values must be >= 1.`block_shape[0]` is expected to be 1. **Required.**
* **3**: `crops_begin` - input 1-D tensor of *T2* type with shape `[N]` that is equal to the size of `data` input shape. All values must be non-negative. crops_begin specifies the amount to crop from the beginning along each axis of `data` input . It is required that `crop_start[i] + crop_end[i] <= block_shape[i] * input_shape[i]`. `crops_begin[0]` is expected to be 0. **Required.**
* **4**: `crops_end` - input 1-D tensor of *T2* type with shape `[N]` that is equal to the size of `data` input shape. All values must be non-negative. crops_end specifies the amount to crop from the ending along each axis of `data` input. It is required that `crop_start[i] + crop_end[i] <= block_shape[i] * input_shape[i]`. `crops_end[0]` is expected to be 0. **Required.**
* **1**: `data` - A tensor of type *T* and rank greater than or equal to 2. Layout is `[batch, D_1, D_2 ... D_{N-1}]` (number of batches, spatial axes). **Required.**
* **2**: `block_shape` - Specifies the block sizes of `batch` axis of `data` input which are moved to the corresponding spatial axes. A 1D tensor of type *T_INT* and shape `[N]`. All element values must be greater than or equal to 1.`block_shape[0]` is expected to be 1. **Required.**
* **3**: `crops_begin` - Specifies the amount to crop from the beginning along each axis of `data` input. A 1D tensor of type *T_INT* and shape `[N]`. All element values must be greater than or equal to 0. `crops_begin[0]` is expected to be 0. **Required.**
* **4**: `crops_end` - Specifies the amount to crop from the ending along each axis of `data` input. A 1D tensor of type *T_INT* and shape `[N]`. All element values must be greater than or equal to 0. `crops_end[0]` is expected to be 0. **Required.**
* **Note**: `N` corresponds to the rank of `data` input.
* **Note**: `batch` axis of `data` input must be evenly divisible by the cumulative product of `block_shape` elements.
* **Note**: It is required that `crops_begin[i] + crops_end[i] <= block_shape[i] * input_shape[i]`.
**Outputs**
* **1**: N-D tensor with shape `[batch / (block_shape[0] * block_shape[1] * ... * block_shape[N - 1]), D_1 * block_shape[1] - crops_begin[1] - crops_end[1], D_2 * block_shape[2] - crops_begin[2] - crops_end[2], ..., D_{N - 1} * block_shape[N - 1] - crops_begin[N - 1] - crops_end[N - 1]` of the same type as `data` input.
* **1**: Permuted tensor of type *T* with the same rank as `data` input tensor, and shape `[batch / (block_shape[0] * block_shape[1] * ... * block_shape[N - 1]), D_1 * block_shape[1] - crops_begin[1] - crops_end[1], D_2 * block_shape[2] - crops_begin[2] - crops_end[2], ..., D_{N - 1} * block_shape[N - 1] - crops_begin[N - 1] - crops_end[N - 1]`.
**Types**
* *T1*: any supported type.
* *T2*: any supported integer type.
* *T*: any supported type.
* *T_INT*: any supported integer type.
**Example**
**Examples**
*Example: 2D input tensor `data`*
```xml
<layer type="BatchToSpace" ...>
<input>
<port id="0"> <!-- data -->
<dim>10</dim> <!-- batch -->
<dim>2</dim> <!-- spatial dimension 1 -->
</port>
<port id="1"> <!-- block_shape value: [1, 5] -->
<dim>2</dim>
</port>
<port id="2"> <!-- crops_begin value: [0, 2] -->
<dim>2</dim>
</port>
<port id="3"> <!-- crops_end value: [0, 0] -->
<dim>2</dim>
</port>
</input>
<output>
<port id="3">
<dim>2</dim> <!-- data.shape[0] / (block_shape.shape[0] * block_shape.shape[1]) -->
<dim>8</dim> <!-- data.shape[1] * block_shape.shape[1] - crops_begin[1] - crops_end[1]-->
</port>
</output>
</layer>
```
*Example: 5D input tensor `data`*
```xml
<layer type="BatchToSpace" ...>
@@ -29,19 +29,12 @@ struct ConvData {
size_t input_height;
size_t input_width;
size_t input_channel_count;
size_t filter_height;
size_t filter_width;
size_t filter_count;
size_t filter_dilation_width;
size_t filter_dilation_height;
size_t filter_stride_width;
size_t filter_stride_height;
size_t pads_begin_width;
size_t pads_begin_height;
size_t pads_end_width;
size_t pads_end_height;
ngraph::op::PadType padding_type;
ngraph::Shape output_shape;
ngraph::element::Type element_type;
};
@@ -55,27 +48,18 @@ static bool VerifyAndGetConvParams(std::shared_ptr<ngraph::opset7::Convolution>
return false;
}
conv_data.output_shape = conv->get_output_shape(0);
conv_data.padding_type = conv->get_auto_pad();
conv_data.input_channel_count = conv->input_value(0).get_shape()[1];
conv_data.input_height = conv->input_value(0).get_shape()[2];
conv_data.input_width = conv->input_value(0).get_shape()[3];
conv_data.filter_count = conv->input_value(1).get_shape()[0];
conv_data.filter_height = conv->input_value(1).get_shape()[2];
conv_data.filter_width = conv->input_value(1).get_shape()[3];
conv_data.filter_dilation_height = conv->get_dilations()[0];
conv_data.filter_dilation_width = conv->get_dilations()[1];
conv_data.filter_stride_height = conv->get_strides()[0];
conv_data.filter_stride_width = conv->get_strides()[1];
conv_data.pads_begin_height = conv->get_pads_begin()[0];
conv_data.pads_begin_width = conv->get_pads_begin()[1];
conv_data.pads_end_height = conv->get_pads_end()[0];
conv_data.pads_end_width = conv->get_pads_end()[1];
conv_data.element_type = conv->get_element_type();
IE_ASSERT(conv_data.filter_count == conv_data.output_shape[1]);
return true;
return conv_data.pads_begin_height || conv_data.pads_end_height || conv_data.pads_begin_width || conv_data.pads_end_width;
}
static bool TransposeOrderMatches(std::shared_ptr<ngraph::opset7::Transpose> transpose, std::vector<size_t> order) {
@@ -117,75 +101,9 @@ static bool VerifyMaxPool(std::shared_ptr<ngraph::opset7::MaxPool> max_pool) {
auto pool_kernel = max_pool->get_kernel();
// Check if MaxPool vertical stride == pool size
// (TODO: remove when 50386 and 50379 are fixed and also verify pool_kernel[0] > 8 limitation below, gna_limitations can be used then)
// Check if padding is VALID
return (max_pool->get_auto_pad() == ngraph::op::PadType::VALID &&
pool_kernel.size() == 2 && pool_strides.size() == 2 &&
pool_kernel[0] == pool_strides[0] && pool_kernel[0] <= 8);
}
static size_t GetRequiredInputPadding(size_t input_size, size_t filter_size, size_t stride_size, size_t dilation_size, size_t output_size) {
size_t partial_padding_size = (output_size - 1) * stride_size + (filter_size - 1) * dilation_size + 1;
// This way of padding size calculation avoids problem with fractional numbers
return (partial_padding_size > input_size) ? (partial_padding_size - input_size) : 0;
}
static size_t CalculateOutputSize(size_t input_size, size_t filter_size, size_t stride_size, size_t dilation_size, size_t padding_size) {
return (input_size + padding_size - ((filter_size - 1) * dilation_size + 1)) / stride_size + 1;
}
static bool CalculatePadding(ConvData& conv_data) {
size_t output_height{ 0 };
size_t output_width{ 0 };
switch (conv_data.padding_type) {
case ngraph::op::PadType::EXPLICIT:
// all paddings already set
break;
case ngraph::op::PadType::VALID:
conv_data.pads_begin_height = 0;
conv_data.pads_begin_width = 0;
conv_data.pads_end_height = 0;
conv_data.pads_end_width = 0;
break;
case ngraph::op::PadType::SAME_LOWER:
case ngraph::op::PadType::SAME_UPPER:
{
output_height = conv_data.output_shape[2];
output_width = conv_data.output_shape[3];
size_t pads_width = GetRequiredInputPadding(conv_data.input_width, conv_data.filter_width,
conv_data.filter_stride_width, conv_data.filter_dilation_width, output_width);
size_t pads_height = GetRequiredInputPadding(conv_data.input_height, conv_data.filter_height,
conv_data.filter_stride_height, conv_data.filter_dilation_height, output_height);
conv_data.pads_begin_width = conv_data.pads_end_width = pads_width / 2;
conv_data.pads_begin_height = conv_data.pads_end_height = pads_height / 2;
if (conv_data.padding_type == ngraph::op::PadType::SAME_LOWER) {
conv_data.pads_begin_width += (pads_width % 2);
conv_data.pads_begin_height += (pads_height % 2);
} else {
conv_data.pads_end_width += (pads_width % 2);
conv_data.pads_end_height += (pads_height % 2);
}
break;
}
default:
break;
}
output_width = CalculateOutputSize(conv_data.input_width, conv_data.filter_width, conv_data.filter_stride_width,
conv_data.filter_dilation_width, conv_data.pads_begin_width + conv_data.pads_end_width);
output_height = CalculateOutputSize(conv_data.input_height, conv_data.filter_height, conv_data.filter_stride_height,
conv_data.filter_dilation_height, conv_data.pads_begin_height + conv_data.pads_end_height);
IE_ASSERT(output_width == conv_data.output_shape[3]);
IE_ASSERT(output_height == conv_data.output_shape[2]);
// Check if any calculated padding is non-zero, otherwise there is no need to decompose such convolution
return conv_data.pads_begin_height || conv_data.pads_end_height || conv_data.pads_begin_width || conv_data.pads_end_width;
pool_kernel.size() == 2 && pool_strides.size() == 2);
}
static std::shared_ptr<ngraph::opset7::StridedSlice> FlatCrop(ngraph::Output<ngraph::Node> input, size_t offset, size_t size) {
@@ -227,7 +145,7 @@ static std::shared_ptr<ngraph::Node> CreatePaddedNet(std::shared_ptr<ngraph::ops
ngraph::opset7::Constant::create(ngraph::element::i64, ngraph::Shape{ 2 },
ngraph::Shape{ 1ull, shape_size(leading_transpose->input_value(0).get_shape()) }), false);
// zero padding
// Constant with zero padding
auto const_holding_padding = std::make_shared<ngraph::opset7::Constant>(conv_data.element_type, ngraph::Shape{ 1, biggest_padding }, 0);
copy_runtime_info(conv, const_holding_padding);
@@ -342,9 +260,6 @@ static bool Convert(std::shared_ptr<ngraph::Node> leading_transpose,
if (max_pool && !VerifyMaxPool(std::dynamic_pointer_cast<ngraph::opset7::MaxPool>(max_pool)))
return false;
if (!CalculatePadding(conv_data))
return false;
GeneratePadding(std::dynamic_pointer_cast<ngraph::opset7::Transpose>(leading_transpose),
std::dynamic_pointer_cast<ngraph::opset7::Convolution>(conv), conv_data);
@@ -5,12 +5,54 @@
#include <memory>
#include "moc_transformations.hpp"
#include "pruning.hpp"
#include <ngraph/pass/manager.hpp>
#include <transformations/init_node_info.hpp>
#include <transformations/common_optimizations/gelu_fusion.hpp>
#include <transformations/common_optimizations/softplus_fusion.hpp>
#include <transformations/common_optimizations/softplus_to_mish_fusion.hpp>
#include <transformations/common_optimizations/swish_fusion.hpp>
#include <transformations/common_optimizations/remove_filtering_boxes_by_size.hpp>
#include <transformations/common_optimizations/hsigmoid_fusion.hpp>
#include <transformations/common_optimizations/hswish_fusion.hpp>
#include <transformations/common_optimizations/convert_quantize_dequantize.hpp>
#include <transformations/common_optimizations/pad_fusion.hpp>
NGRAPH_RTTI_DEFINITION(ngraph::pass::MOCTransformations, "MOCTransformations", 0);
bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr<ngraph::Function> f) {
// To avoid issues with dynamism we make nGraph Function dynamic and after we apply all
// transformations we restore original shapes to the nGraph Function back
std::unordered_map<ngraph::op::Parameter*, PartialShape> input_shapes;
for (auto && param : f->get_parameters()) {
input_shapes[param.get()] = param->get_partial_shape();
param->set_partial_shape(PartialShape::dynamic(param->get_partial_shape().rank()));
}
f->validate_nodes_and_infer_types();
ngraph::pass::Manager manager(get_pass_config());
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::RemoveFilteringBoxesBySize>();
manager.register_pass<ngraph::pass::ConvertQuantizeDequantize>();
auto common_fusions = manager.register_pass<ngraph::pass::GraphRewrite>();
common_fusions->add_matcher<ngraph::pass::SoftPlusFusion>();
common_fusions->add_matcher<ngraph::pass::SoftPlusToMishFusion>();
common_fusions->add_matcher<ngraph::pass::SwishFusion>();
common_fusions->add_matcher<ngraph::pass::HSwishFusion>();
common_fusions->add_matcher<ngraph::pass::HSigmoidFusion>();
common_fusions->add_matcher<ngraph::pass::PadFusion>();
common_fusions->add_matcher<ngraph::pass::GeluFusion>();
common_fusions->set_name("ngraph::pass::CommonFusions");
manager.run_passes(f);
// Restore original shapes to the nGraph Function
for (auto && param : f->get_parameters()) {
param->set_partial_shape(input_shapes.at(param.get()));
}
f->validate_nodes_and_infer_types();
return false;
}
@@ -71,8 +71,11 @@ public:
std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
void cache_output_descriptor();
private:
std::vector<std::tuple<ngraph::PartialShape, ngraph::element::Type>> m_inputs_desc;
std::vector<std::tuple<ngraph::PartialShape, ngraph::element::Type>> m_output_desc;
FrameworkNodeAttrs m_attrs;
};
@@ -12,6 +12,7 @@ namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API PadFusion;
class TRANSFORMATIONS_API PadElimination;
class TRANSFORMATIONS_API PadFusionAvgPool;
class TRANSFORMATIONS_API PadFusionMaxPool;
class TRANSFORMATIONS_API PadFusionConvolution;
@@ -22,6 +23,16 @@ class TRANSFORMATIONS_API PadFusionGroupConvolutionBackpropData;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief PadElimination eliminates pad that does nothing
*/
class ngraph::pass::PadElimination: public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
PadElimination();
};
/**
* @ingroup ie_transformation_common_api
* @brief PadFusion transformation replaces following graph:
@@ -113,5 +124,6 @@ public:
add_matcher<ngraph::pass::PadFusionConvolutionBackpropData>();
add_matcher<ngraph::pass::PadFusionGroupConvolution>();
add_matcher<ngraph::pass::PadFusionGroupConvolutionBackpropData>();
add_matcher<ngraph::pass::PadElimination>();
}
};
@@ -25,31 +25,71 @@ shared_ptr<Node> op::FrameworkNode::clone_with_new_inputs(const OutputVector& ne
return node;
}
void op::FrameworkNode::cache_output_descriptor() {
for (size_t i = 0; i < get_output_size(); ++i) {
m_output_desc.emplace_back(get_output_partial_shape(i), get_output_element_type(i));
}
}
void op::FrameworkNode::validate_and_infer_types() {
INTERNAL_OP_SCOPE(FrameworkNode_validate_and_infer_types);
// Save initial inputs descriptors
bool initialize_input_desc = m_inputs_desc.empty();
bool reset_output_shape_to_dynamic = false;
bool reset_output_shape_to_original = false;
for (uint64_t i = 0; i < get_input_size(); i++) {
// TODO: store constant values
const auto& new_input_desc =
std::make_tuple(get_input_partial_shape(i), get_input_element_type(i));
const auto& input_pshape = get_input_partial_shape(i);
const auto& input_type = get_input_element_type(i);
const auto& rank = input_pshape.rank();
const auto & get_error_message = [&]() {
std::stringstream out;
out << "Input descriptor for " << get_friendly_name()
<< " node has been changed:" << std::endl;
out << "Before: " << std::get<0>(m_inputs_desc[i]) << ", "
<< std::get<1>(m_inputs_desc[i]) << std::endl;
out << "After: " << input_pshape << ", "
<< input_type << std::endl;
out << "Please specify InferenceEngine Extensions to support this case.";
return out.str();
};
if (initialize_input_desc) {
m_inputs_desc.push_back(new_input_desc);
m_inputs_desc.emplace_back(input_pshape, input_type);
} else {
auto get_message = [&]() {
std::stringstream out;
out << "Input descriptor for " << get_friendly_name()
<< " node has been changed:" << std::endl;
out << "Before: " << std::get<0>(m_inputs_desc[i]) << ", "
<< std::get<1>(m_inputs_desc[i]) << std::endl;
out << "After: " << std::get<0>(new_input_desc) << ", "
<< std::get<1>(new_input_desc) << std::endl;
out << "Please specify InferenceEngine Extensions to support this case.";
return out.str();
};
const auto& orig_input_pshape = std::get<0>(m_inputs_desc[i]);
if (orig_input_pshape == input_pshape) {
reset_output_shape_to_original = true;
} else if (input_pshape.rank().is_dynamic()) {
reset_output_shape_to_dynamic = true;
} else if (rank.is_static() && orig_input_pshape.rank().is_static() &&
rank.get_length() == orig_input_pshape.rank().get_length()) {
for (int64_t dim = 0; dim < rank.get_length(); ++dim) {
NODE_VALIDATION_CHECK(this, input_pshape[dim].is_dynamic() ||
(orig_input_pshape[dim].is_static() &&
orig_input_pshape[dim].get_length() == input_pshape[dim].get_length()),
get_error_message());
}
reset_output_shape_to_dynamic = true;
} else {
NODE_VALIDATION_CHECK(this, m_inputs_desc[i] == std::make_tuple(input_pshape, input_type), get_error_message());
}
}
}
NODE_VALIDATION_CHECK(this, m_inputs_desc[i] == new_input_desc, get_message());
if (reset_output_shape_to_dynamic) {
cache_output_descriptor();
for (size_t i = 0; i < get_output_size(); ++i) {
if (get_output_partial_shape(i).rank().is_static()) {
set_output_type(i, get_output_element_type(i), PartialShape::dynamic());
}
}
}
if (reset_output_shape_to_original && !m_output_desc.empty()) {
for (size_t i = 0; i < get_output_size(); ++i) {
set_output_type(i, std::get<1>(m_output_desc[i]), std::get<0>(m_output_desc[i]));
}
}
}
@@ -12,6 +12,7 @@
#include <ngraph/rt_info.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/opsets/opset5.hpp>
#include <ngraph/validation_util.hpp>
using namespace ngraph;
@@ -385,3 +386,34 @@ pass::PadFusionGroupConvolutionBackpropData::PadFusionGroupConvolutionBackpropDa
auto m = std::make_shared<pattern::Matcher>(conv_pattern, matcher_name);
this->register_matcher(m, callback);
}
NGRAPH_RTTI_DEFINITION(pass::PadElimination, "PadElimination", 0);
pass::PadElimination::PadElimination() {
MATCHER_SCOPE(PadElimination);
auto pad_node_pattern = pattern::wrap_type<opset5::Pad>();
matcher_pass_callback callback = [=](pattern::Matcher& m) {
auto pad = m.get_match_root();
auto pad_begin_const = ngraph::get_constant_from_source(pad->input_value(1));
auto pad_end_const = ngraph::get_constant_from_source(pad->input_value(2));
if (!pad_begin_const || !pad_end_const) {
return false;
}
const auto pad_begin_value = pad_begin_const->cast_vector<int64_t>();
const auto pad_end_value = pad_end_const->cast_vector<int64_t>();
if (std::any_of(pad_begin_value.begin(), pad_begin_value.end(), [](int64_t value) { return value != 0; }) ||
std::any_of(pad_end_value.begin(), pad_end_value.end(), [](int64_t value) { return value != 0; })) {
return false;
}
return replace_output_update_name(pad->output(0), pad->input_value(0));
};
auto m = std::make_shared<pattern::Matcher>(pad_node_pattern, matcher_name);
this->register_matcher(m, callback);
}
@@ -19,26 +19,20 @@ ngraph::pass::SoftPlusFusion::SoftPlusFusion() {
// fuses ln(exp(x) + 1.0) operations into SoftPlus(x)
auto input = ngraph::pattern::any_input();
auto exp = std::make_shared<ngraph::opset4::Exp>(input);
auto add_constant = ngraph::pattern::wrap_type<ngraph::opset4::Constant>();
auto add_constant = ngraph::pattern::wrap_type<ngraph::opset4::Constant>(
pattern::type_matches_any({element::f32, element::f16}));
auto add = std::make_shared<ngraph::opset4::Add>(exp, add_constant);
auto log = std::make_shared<ngraph::opset4::Log>(add);
ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher &m) {
auto &pattern_to_output = m.get_pattern_value_map();
const auto &pattern_to_output = m.get_pattern_value_map();
auto exp_input = pattern_to_output.at(input);
auto constant = std::dynamic_pointer_cast<ngraph::opset4::Constant>(pattern_to_output.at(add_constant).get_node_shared_ptr());
if (!constant) return false;
if (constant == nullptr) {
return false;
}
if (constant->get_element_type() == ngraph::element::f32 || constant->get_element_type() == ngraph::element::f16) {
auto data = constant->cast_vector<float>();
if (data.size() != 1 || data[0] != 1.0) {
return false;
}
} else {
auto data = constant->cast_vector<float>();
if (data.size() != 1 || data[0] != 1.0) {
return false;
}
@@ -40,6 +40,7 @@ ngraph::pass::ConvertTopK3::ConvertTopK3() {
last1 = new_topk->output(1);
new_topk->set_friendly_name(topk->get_friendly_name());
} else if (topk->get_output_target_inputs(0).size() == 0) {
last0 = topk->output(0);
last1 = std::make_shared<ngraph::opset2::Convert>(new_topk->output(1), topk->get_index_element_type());
new_ops.push_back(last1.get_node_shared_ptr());
@@ -37,6 +37,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
{Negative, {}},
{Acos, {}},
{Asin, {}},
{Asinh, {}},
{Atan, {}},
{Cos, {}},
{Cosh, {}},
@@ -0,0 +1,59 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <string>
#include <memory>
#include <queue>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph_ops/framework_node.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
using namespace testing;
using namespace ngraph;
TEST(TransformationTests, FrameworkNode) {
auto param = std::make_shared<ngraph::opset8::Parameter>(element::i64, Shape{1, 64});
auto f_node = std::make_shared<ngraph::op::FrameworkNode>(OutputVector{param});
f_node->set_output_type(0, element::i64, Shape{1, 64});
// Set partially dynamic shape
param->set_partial_shape(PartialShape{Dimension::dynamic(), 64});
param->validate_and_infer_types();
ASSERT_NO_THROW(f_node->validate_and_infer_types());
ASSERT_EQ(f_node->get_output_partial_shape(0), PartialShape::dynamic());
// Set dynamic shape
param->set_partial_shape(PartialShape::dynamic(2));
param->validate_and_infer_types();
ASSERT_NO_THROW(f_node->validate_and_infer_types());
ASSERT_EQ(f_node->get_output_partial_shape(0), PartialShape::dynamic());
// Set fully dynamic shape
param->set_partial_shape(PartialShape::dynamic());
param->validate_and_infer_types();
ASSERT_NO_THROW(f_node->validate_and_infer_types());
ASSERT_EQ(f_node->get_output_partial_shape(0), PartialShape::dynamic());
// Set original static shape
param->set_partial_shape(Shape{1, 64});
param->validate_and_infer_types();
ASSERT_NO_THROW(f_node->validate_and_infer_types());
ASSERT_EQ(f_node->get_output_partial_shape(0), PartialShape({1, 64}));
// Set different static shape
param->set_partial_shape(Shape{2, 64});
param->validate_and_infer_types();
ASSERT_THROW(f_node->validate_and_infer_types(), ngraph_error::exception);
}
@@ -14,6 +14,7 @@
#include <transformations/init_node_info.hpp>
#include <transformations/utils/utils.hpp>
#include <ngraph/pass/manager.hpp>
#include <common_test_utils/ngraph_test_utils.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
@@ -21,6 +22,42 @@
using namespace testing;
using namespace ngraph;
TEST(TransformationTests, PadElimination) {
std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
Shape data_shape{1, 3, 14, 14};
{
auto data = std::make_shared<opset5::Parameter>(element::i32, data_shape);
set_tensor_name(data, "param");
auto pads_begin = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 0, 0});
auto pads_end = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 0, 0});
auto pad = std::make_shared<opset5::Pad>(data, pads_begin, pads_end, op::PadMode::CONSTANT);
set_tensor_name(pad, "pad");
auto filters = std::make_shared<opset5::Parameter>(element::i32, Shape{1, 3, 4, 4});
auto conv = std::make_shared<opset5::Convolution>(pad, filters, Strides{1, 1},
CoordinateDiff{0, 0}, CoordinateDiff{1, 1}, Shape{1, 1});
set_tensor_name(conv, "conv");
f = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
pass::Manager m;
m.register_pass<pass::InitNodeInfo>();
m.register_pass<pass::PadFusion>();
m.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto data = std::make_shared<opset5::Parameter>(element::i32, data_shape);
set_tensor_names(data, {"param", "pad"});
auto filters = std::make_shared<opset5::Parameter>(element::i32, Shape{1, 3, 4, 4});
auto conv = std::make_shared<opset5::Convolution>(data, filters, Strides{1, 1},
CoordinateDiff{0, 0}, CoordinateDiff{1, 1}, Shape{1, 1},
op::PadType::EXPLICIT);
set_tensor_name(conv, "conv");
f_ref = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, PadFusionAvgPoolExcludePad) {
std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
@@ -155,9 +192,11 @@ TEST(TransformationTests, PadFusionConvolutionBackpropData) {
auto pads_begin = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 1, 1});
auto pads_end = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 2, 2});
auto pad = std::make_shared<opset5::Pad>(data, pads_begin, pads_end, op::PadMode::CONSTANT);
set_tensor_name(pad, "pad");
auto filters = std::make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5, 5});
auto conv = std::make_shared<opset5::ConvolutionBackpropData>(pad, filters, Strides{1, 1},
CoordinateDiff{4, 4}, CoordinateDiff{3, 3}, Shape{1, 1});
set_tensor_name(conv, "conv");
f = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
pass::Manager m;
@@ -171,6 +210,7 @@ TEST(TransformationTests, PadFusionConvolutionBackpropData) {
auto filters = std::make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5, 5});
auto conv = std::make_shared<opset5::ConvolutionBackpropData>(data, filters, Strides{1, 1},
CoordinateDiff{3, 3}, CoordinateDiff{1, 1}, Shape{1, 1});
set_tensor_name(conv, "conv");
f_ref = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
}
@@ -389,12 +429,15 @@ TEST(TransformationTests, NegativePadFusionConvolutionBackpropDataTooSmallPad) {
Shape data_shape{1, 3, 14, 14};
{
auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
set_tensor_name(data, "data");
auto pads_begin = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 2, 2});
auto pads_end = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 2, 2});
auto pad = std::make_shared<opset5::Pad>(data, pads_begin, pads_end, op::PadMode::CONSTANT);
set_tensor_name(pad, "pad");
auto filters = std::make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5, 5});
auto conv = std::make_shared<opset5::ConvolutionBackpropData>(pad, filters, Strides{1, 1},
CoordinateDiff{1, 1}, CoordinateDiff{1, 1}, Shape{1, 1});
set_tensor_name(conv, "conv");
f = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
pass::Manager m;
@@ -405,12 +448,15 @@ TEST(TransformationTests, NegativePadFusionConvolutionBackpropDataTooSmallPad) {
}
{
auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
set_tensor_name(data, "data");
auto pads_begin = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 2, 2});
auto pads_end = opset5::Constant::create(element::i32, Shape{4}, {0, 0, 2, 2});
auto pad = std::make_shared<opset5::Pad>(data, pads_begin, pads_end, op::PadMode::CONSTANT);
set_tensor_name(pad, "pad");
auto filters = std::make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5, 5});
auto conv = std::make_shared<opset5::ConvolutionBackpropData>(pad, filters, Strides{1, 1},
CoordinateDiff{1, 1}, CoordinateDiff{1, 1}, Shape{1, 1});
set_tensor_name(conv, "conv");
f_ref = std::make_shared<Function>(NodeVector{conv}, ParameterVector{data, filters});
}
@@ -38,6 +38,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
{Negative, {}},
{Acos, {}},
{Asin, {}},
{Asinh, {}},
{Atan, {}},
{Cos, {}},
{Cosh, {}},
@@ -65,6 +66,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
// List of operations that should be tested also with integer precision
const std::map<ActivationTypes, std::vector<std::vector<float>>> intActivationTypes = {
{Asinh, {}},
{Atan, {}},
{Negative, {}},
{Ceiling, {}},
@@ -16,6 +16,39 @@ const std::vector<InferenceEngine::Precision> net_precisions = {
InferenceEngine::Precision::I32
};
const std::vector<std::vector<size_t>> data_shapes_2D = {
{12, 4},
{48, 3}
};
const std::vector<std::vector<int64_t>> block_shapes_2D = {
{1, 2},
{1, 6}
};
const std::vector<std::vector<int64_t>> crops_2D = {
{0, 0},
{0, 1}
};
const auto batch_to_space_2d_tests = ::testing::Combine(
::testing::ValuesIn(block_shapes_2D),
::testing::ValuesIn(crops_2D),
::testing::ValuesIn(crops_2D),
::testing::ValuesIn(data_shapes_2D),
::testing::ValuesIn(net_precisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(CommonTestUtils::DEVICE_CPU));
INSTANTIATE_TEST_CASE_P(
smoke_BatchToSpace_2D,
BatchToSpaceLayerTest,
batch_to_space_2d_tests,
BatchToSpaceLayerTest::getTestCaseName);
const std::vector<std::vector<size_t>> data_shapes_4D = {
{4, 1, 2, 2},
{4, 3, 2, 2},
@@ -39,7 +72,7 @@ const std::vector<std::vector<int64_t>> crops_end_4D = {
{0, 0, 0, 2}
};
const auto space_to_batch_4d_spatial_dims_tests = ::testing::Combine(
const auto batch_to_space_4d_spatial_dims_tests = ::testing::Combine(
::testing::Values(block_shapes_4D[0]),
::testing::ValuesIn(crops_begin_4D),
::testing::ValuesIn(crops_end_4D),
@@ -51,7 +84,7 @@ const auto space_to_batch_4d_spatial_dims_tests = ::testing::Combine(
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(CommonTestUtils::DEVICE_CPU));
const auto space_to_batch_4d_channel_dim_tests = ::testing::Combine(
const auto batch_to_space_4d_channel_dim_tests = ::testing::Combine(
::testing::Values(block_shapes_4D[1]),
::testing::Values(crops_begin_4D[0]),
::testing::Values(crops_end_4D[0]),
@@ -66,13 +99,13 @@ const auto space_to_batch_4d_channel_dim_tests = ::testing::Combine(
INSTANTIATE_TEST_CASE_P(
smoke_BatchToSpace_4D_spatial_dims,
BatchToSpaceLayerTest,
space_to_batch_4d_spatial_dims_tests,
batch_to_space_4d_spatial_dims_tests,
BatchToSpaceLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(
smoke_BatchToSpace_4D_channel_dim,
BatchToSpaceLayerTest,
space_to_batch_4d_channel_dim_tests,
batch_to_space_4d_channel_dim_tests,
BatchToSpaceLayerTest::getTestCaseName);
const std::vector<std::vector<size_t>> data_shapes_5D = {
@@ -96,7 +129,7 @@ const std::vector<std::vector<int64_t>> crops_end_5D = {
{0, 0, 0, 0, 1}
};
const auto space_to_batch_5d_spatial_dims_tests = ::testing::Combine(
const auto batch_to_space_5d_spatial_dims_tests = ::testing::Combine(
::testing::Values(block_shapes_5D[0]),
::testing::ValuesIn(crops_begin_5D),
::testing::ValuesIn(crops_end_5D),
@@ -108,7 +141,7 @@ const auto space_to_batch_5d_spatial_dims_tests = ::testing::Combine(
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(CommonTestUtils::DEVICE_CPU));
const auto space_to_batch_5d_channel_dim_tests = ::testing::Combine(
const auto batch_to_space_5d_channel_dim_tests = ::testing::Combine(
::testing::Values(block_shapes_5D[1]),
::testing::Values(crops_begin_5D[0]),
::testing::Values(crops_end_5D[0]),
@@ -123,13 +156,13 @@ const auto space_to_batch_5d_channel_dim_tests = ::testing::Combine(
INSTANTIATE_TEST_CASE_P(
smoke_BatchToSpace_5D_spatial_dims,
BatchToSpaceLayerTest,
space_to_batch_5d_spatial_dims_tests,
batch_to_space_5d_spatial_dims_tests,
BatchToSpaceLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(
smoke_BatchToSpace_5D_channel_dim,
BatchToSpaceLayerTest,
space_to_batch_5d_channel_dim_tests,
batch_to_space_5d_channel_dim_tests,
BatchToSpaceLayerTest::getTestCaseName);
} // namespace
} // namespace
@@ -247,10 +247,10 @@ const std::vector<std::map<std::string, std::string>> configs2D = {
};
const std::vector<op::PadType> padTypes = {
op::PadType::VALID,
op::PadType::EXPLICIT,
op::PadType::SAME_LOWER,
op::PadType::SAME_UPPER,
op::PadType::VALID
op::PadType::SAME_UPPER
};
const std::vector<modelType> models = {
@@ -277,14 +277,14 @@ const std::vector<std::vector<size_t >> maxpool1DPools = { {1, 2} };
const std::vector<std::vector<size_t >> maxpool1DStrides = { {1, 1} };
const std::vector<std::vector<size_t>> input2DNHWC = { {1, 16, 16, 32} };
const std::vector<std::vector<size_t >> kernels2D = { {2, 2}, {4, 1}, {1, 3}};
const std::vector<std::vector<size_t >> kernels2D = { {2, 2}, {4, 1}, {1, 3} };
const std::vector<std::vector<size_t >> strides2D = { {1, 1}, {1, 2}, {2, 1}, {2, 2} };
const std::vector<std::vector<ptrdiff_t>> padBegins2D = { {1, 2} };
const std::vector<std::vector<ptrdiff_t>> padEnds2D = { {3, 1} };
const std::vector<std::vector<size_t >> dilations2D = { {1, 1} };
const std::vector<size_t> numOutChannels2D = { 32 };
const std::vector<std::vector<size_t >> biases2D = { {1, 32, 1, 1} };
const std::vector<std::vector<size_t >> transpBiases2D = { {1, 1, 1, 32} };
const std::vector<size_t> numOutChannels2D = { 8 };
const std::vector<std::vector<size_t >> biases2D = { {1, 8, 1, 1} };
const std::vector<std::vector<size_t >> transpBiases2D = { {1, 1, 1, 8} };
const std::vector<std::vector<size_t >> maxpool2DPools = { {2, 2} };
const std::vector<std::vector<size_t >> maxpool2DStrides = { {2, 1} };
@@ -35,6 +35,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
{Negative, {}},
{Acos, {}},
{Asin, {}},
{Asinh, {}},
{Atan, {}},
{Cos, {}},
{Cosh, {}},
@@ -40,6 +40,7 @@ static std::map<ngraph::helpers::ActivationTypes, std::string> activationNames =
{ngraph::helpers::ActivationTypes::Negative, "Negative"},
{ngraph::helpers::ActivationTypes::Acos, "Acos"},
{ngraph::helpers::ActivationTypes::Asin, "Asin"},
{ngraph::helpers::ActivationTypes::Asinh, "Asinh"},
{ngraph::helpers::ActivationTypes::Atan, "Atan"},
{ngraph::helpers::ActivationTypes::Cos, "Cos"},
{ngraph::helpers::ActivationTypes::Cosh, "Cosh"},
@@ -779,6 +779,14 @@ void check_rt_info(const std::shared_ptr<ngraph::Function>& f) {
}
}
void set_tensor_name(ngraph::Output<ngraph::Node> output, const std::string & name) {
output.get_tensor_ptr()->set_names({name});
}
void set_tensor_names(ngraph::Output<ngraph::Node> output, const std::unordered_set<std::string> & names) {
output.get_tensor_ptr()->set_names(names);
}
NGRAPH_RTTI_DEFINITION(TestOpMultiOut, "TestOp", 0);
namespace attributes {
@@ -101,6 +101,10 @@ inline std::pair<bool, std::string> compare_functions(
void check_rt_info(const std::shared_ptr<ngraph::Function>& f);
void set_tensor_name(ngraph::Output<ngraph::Node> output, const std::string & name);
void set_tensor_names(ngraph::Output<ngraph::Node> output, const std::unordered_set<std::string> & names);
namespace ngraph {
namespace pass {
class InjectionPass;
@@ -6,6 +6,7 @@ VERIFIED_OP_REFERENCES = [
'Acos-1',
'Add-1',
'Asin-1',
'Asinh-3',
'Assign-6',
'AvgPool-1',
'BatchNormInference-5',
@@ -23,6 +24,7 @@ VERIFIED_OP_REFERENCES = [
'Convolution-1',
'Constant-1',
'Cos-1',
'Cosh-1',
'DeformableConvolution-1',
'DeformablePSROIPooling-1',
'DetectionOutput-1',
@@ -100,6 +100,7 @@ enum ActivationTypes {
Negative,
Acos,
Asin,
Asinh,
Atan,
Cos,
Cosh,
@@ -48,6 +48,8 @@ std::shared_ptr<ngraph::Node> makeActivation(const ngraph::Output<Node> &in,
return std::make_shared<ngraph::op::Acos>(in);
case ngraph::helpers::ActivationTypes::Asin:
return std::make_shared<ngraph::op::Asin>(in);
case ngraph::helpers::ActivationTypes::Asinh:
return std::make_shared<ngraph::op::Asinh>(in);
case ngraph::helpers::ActivationTypes::Atan:
return std::make_shared<ngraph::op::Atan>(in);
case ngraph::helpers::ActivationTypes::Cos:
@@ -0,0 +1,453 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <tuple>
#include "transformations/convert_padded2valid_conv.hpp"
#include "common_test_utils/ngraph_test_utils.hpp"
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset7.hpp>
#include <ngraph/pass/manager.hpp>
#include <transformations/init_node_info.hpp>
namespace testing {
namespace {
enum class modelType {
TranspConvTransp = 0, /* Transpose(NHWC->NCHW) => Conv => Transpose(NCHW->NHWC) */
TranspConvBcastAddTransp, /* Transpose(NHWC->NCHW) => Conv => Broadcasted Add (Bias) => Transpose(NCHW->NHWC) */
TranspConvBcastAddMaxPoolTransp, /* Transpose(NHWC->NCHW) => Conv => Broadcasted Add (Bias) => MaxPooling => Transpose(NCHW->NHWC) (2D Max Pool case) */
TranspConvBcastAddActTransp, /* Transpose(NHWC->NCHW) => Conv => Broadcasted Add (Bias) => Activation Function => Transpose(NCHW->NHWC) */
TranspConvBcastAddMaxPoolActTransp, /* Transpose(NHWC->NCHW) => Conv => Broadcasted Add (Bias) => MaxPool => Activation Function => Transpose(NCHW->NHWC) */
TranspConvTranspBcastAdd, /* Transpose(NHWC->NCHW) => conv => Transpose(NCHW->NHWC) => Bias */
TranspConvTranspBcastAddAct /* Transpose(NHWC->NCHW) => Conv => Transpose(NCHW->NHWC) => Bias => Activation Function */
};
struct ConvData {
size_t input_height;
size_t input_width;
size_t input_channel_count;
size_t pads_begin_width;
size_t pads_begin_height;
size_t pads_end_width;
size_t pads_end_height;
};
void GetConvParams(std::shared_ptr<ngraph::opset7::Convolution> conv, ConvData& conv_data) {
conv_data.input_channel_count = conv->input_value(0).get_shape()[1];
conv_data.input_height = conv->input_value(0).get_shape()[2];
conv_data.input_width = conv->input_value(0).get_shape()[3];
conv_data.pads_begin_height = conv->get_pads_begin()[0];
conv_data.pads_begin_width = conv->get_pads_begin()[1];
conv_data.pads_end_height = conv->get_pads_end()[0];
conv_data.pads_end_width = conv->get_pads_end()[1];
}
std::shared_ptr<ngraph::opset7::Result> createFunction(const modelType& model,
const ngraph::Output<ngraph::Node>& input_node,
const ngraph::Shape& filters_shape,
const ngraph::Strides& conv_stride,
const ngraph::CoordinateDiff& pads_begin,
const ngraph::CoordinateDiff& pads_end,
const ngraph::Strides& conv_dilation,
const ngraph::Shape& bias_shape,
const ngraph::Strides& maxpool_stride,
const ngraph::Shape& maxpool_shape,
const ngraph::op::PadType& pad_type,
ConvData* conv_data) {
auto transpose_in_order = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64, ngraph::Shape{4}, ngraph::Shape{0, 3, 1, 2});
auto transpose_in = std::make_shared<ngraph::opset7::Transpose>(input_node, transpose_in_order);
auto filters = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64,
ngraph::Shape{4, input_node.get_shape()[3], filters_shape[0], filters_shape[1]});
auto conv = std::make_shared<ngraph::opset7::Convolution>(transpose_in, filters, conv_stride, pads_begin, pads_end, conv_dilation, pad_type);
if (conv_data)
GetConvParams(conv, *conv_data);
auto transpose_out_order = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64, ngraph::Shape{4}, ngraph::Shape{0, 2, 3, 1});
auto bias_const = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64, bias_shape);
ngraph::Output<ngraph::Node> last_op = std::make_shared<ngraph::opset7::Transpose>(conv, transpose_out_order);
switch (model) {
case modelType::TranspConvBcastAddTransp:
{
auto bcast_add = std::make_shared<ngraph::opset7::Add>(conv, bias_const);
last_op = std::make_shared<ngraph::opset7::Transpose>(bcast_add, transpose_out_order);
}
break;
case modelType::TranspConvBcastAddMaxPoolTransp:
{
auto bcast_add = std::make_shared<ngraph::opset7::Add>(conv, bias_const);
auto maxpool = std::make_shared<ngraph::opset7::MaxPool>(bcast_add, maxpool_stride, ngraph::Shape{0, 0}, ngraph::Shape{0, 0}, maxpool_shape,
ngraph::op::RoundingType::FLOOR, ngraph::op::PadType::VALID);
auto transpose = std::make_shared<ngraph::opset7::Transpose>(maxpool, transpose_out_order);
last_op = std::make_shared<ngraph::opset7::Relu>(transpose);
}
break;
case modelType::TranspConvBcastAddActTransp:
{
auto bcast_add = std::make_shared<ngraph::opset7::Add>(conv, bias_const);
auto activation = std::make_shared<ngraph::opset7::Relu>(bcast_add);
last_op = std::make_shared<ngraph::opset7::Transpose>(activation, transpose_out_order);
}
break;
case modelType::TranspConvBcastAddMaxPoolActTransp:
{
auto bcast_add = std::make_shared<ngraph::opset7::Add>(conv, bias_const);
auto maxpool = std::make_shared<ngraph::opset7::MaxPool>(bcast_add, maxpool_stride, ngraph::Shape{0, 0}, ngraph::Shape{0, 0}, maxpool_shape,
ngraph::op::RoundingType::FLOOR, ngraph::op::PadType::VALID);
auto activation = std::make_shared<ngraph::opset7::Relu>(maxpool);
last_op = std::make_shared<ngraph::opset7::Transpose>(activation, transpose_out_order);
}
break;
case modelType::TranspConvTranspBcastAdd:
{
last_op = std::make_shared<ngraph::opset7::Add>(last_op, bias_const);
}
break;
case modelType::TranspConvTranspBcastAddAct:
{
auto bcast_add = std::make_shared<ngraph::opset7::Add>(last_op, bias_const);
last_op = std::make_shared<ngraph::opset7::Relu>(bcast_add);
}
break;
case modelType::TranspConvTransp:
default:
break;
}
return std::make_shared<ngraph::opset7::Result>(last_op);
}
std::shared_ptr<ngraph::Function> get_initial_function(const modelType& model,
const ngraph::PartialShape& input_shape,
const ngraph::Shape& filters_shape,
const ngraph::Strides& conv_stride,
const ngraph::CoordinateDiff& pads_begin,
const ngraph::CoordinateDiff& pads_end,
const ngraph::Strides& conv_dilation,
const ngraph::Shape& bias_shape,
const ngraph::Strides& maxpool_stride,
const ngraph::Shape& maxpool_shape,
const ngraph::op::PadType& pad_type,
ConvData& conv_data) {
auto inputParams = std::make_shared<ngraph::opset7::Parameter>(ngraph::element::i64, input_shape);
auto result = createFunction(model, inputParams, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation, bias_shape,
maxpool_stride, maxpool_shape, pad_type, &conv_data);
return std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, ngraph::ParameterVector{inputParams});
}
// ---------------------------------------------------------------------------------------------------------------------
class ConvertPadded2ValidConvTestInvalidFixture : public CommonTestUtils::TestsCommon,
public ::testing::WithParamInterface<std::tuple<modelType, ngraph::PartialShape, ngraph::Shape, ngraph::Strides,
ngraph::CoordinateDiff, ngraph::CoordinateDiff,
ngraph::Strides, ngraph::Shape,
ngraph::Strides, ngraph::Shape,
ngraph::op::PadType>> {
public:
void SetUp() override;
public:
std::shared_ptr<ngraph::Function> function, reference_function;
modelType model;
};
void ConvertPadded2ValidConvTestInvalidFixture::SetUp() {
ngraph::PartialShape input_shape;
ngraph::Shape filters_shape, bias_shape, maxpool_shape;
ngraph::Strides conv_stride, conv_dilation, maxpool_stride;
ngraph::CoordinateDiff pads_begin, pads_end;
ngraph::op::PadType pad_type;
ConvData conv_data;
std::tie(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type) = this->GetParam();
function = get_initial_function(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type, conv_data);
reference_function = get_initial_function(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type, conv_data);
}
// ---------------------------------------------------------------------------------------------------------------------
class ConvertPadded2ValidConvTestFixture: public CommonTestUtils::TestsCommon,
public ::testing::WithParamInterface<std::tuple<modelType, ngraph::PartialShape, ngraph::Shape, ngraph::Strides,
ngraph::CoordinateDiff, ngraph::CoordinateDiff,
ngraph::Strides, ngraph::Shape,
ngraph::Strides, ngraph::Shape,
ngraph::op::PadType>> {
public:
void SetUp() override;
std::shared_ptr<ngraph::Function> get_reference(const modelType& model,
const ngraph::PartialShape& input_shape,
const ngraph::Shape& filters_shape,
const ngraph::Strides& conv_stride,
const ngraph::CoordinateDiff& pads_begin,
const ngraph::CoordinateDiff& pads_end,
const ngraph::Strides& conv_dilation,
const ngraph::Shape& bias_shape,
const ngraph::Strides& maxpool_stride,
const ngraph::Shape& maxpool_shape,
const ngraph::op::PadType& pad_type,
const ConvData& conv_data);
public:
std::shared_ptr<ngraph::Function> function, reference_function;
modelType model;
};
void ConvertPadded2ValidConvTestFixture::SetUp() {
ngraph::PartialShape input_shape;
ngraph::Shape filters_shape, bias_shape, maxpool_shape;
ngraph::Strides conv_stride, conv_dilation, maxpool_stride;
ngraph::CoordinateDiff pads_begin, pads_end;
ngraph::op::PadType pad_type;
ConvData conv_data;
std::tie(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type) = this->GetParam();
function = get_initial_function(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type, conv_data);
reference_function = get_reference(model, input_shape, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation,
bias_shape, maxpool_stride, maxpool_shape, pad_type, conv_data);
}
std::shared_ptr<ngraph::opset7::StridedSlice> FlatCrop(ngraph::Output<ngraph::Node> input, size_t offset, size_t size) {
return std::make_shared<ngraph::opset7::StridedSlice>(
input, // data
ngraph::opset7::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {(size_t)0, offset}), // begin sice index
ngraph::opset7::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {(size_t)0, offset + size}), // end slice index
ngraph::opset7::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {(size_t)1, (size_t)1}), // strides
std::vector<int64_t>{1, 0}, // begin mask
std::vector<int64_t>{1, 0}); // end mask
}
void InsertPadding(ngraph::OutputVector& input_rows_to_concat, size_t size,
const std::shared_ptr<ngraph::opset7::Constant> padding_const, size_t biggest_padding) {
if (size == biggest_padding) {
input_rows_to_concat.push_back(padding_const);
} else {
auto slice = FlatCrop(padding_const, 0, size);
input_rows_to_concat.push_back(slice);
}
}
std::shared_ptr<ngraph::Node> CreatePaddedNet(const ngraph::Output<ngraph::Node>& input_node,
const ConvData& conv_data) {
size_t flat_left_padding = conv_data.input_channel_count * conv_data.pads_begin_width;
size_t flat_right_padding = conv_data.input_channel_count * conv_data.pads_end_width;
size_t padded_row_size = flat_left_padding + conv_data.input_channel_count * conv_data.input_width + flat_right_padding;
size_t flat_top_padding = padded_row_size * conv_data.pads_begin_height;
size_t flat_bottom_padding = padded_row_size * conv_data.pads_end_height;
size_t biggest_padding = std::max(std::max(flat_left_padding, flat_right_padding), std::max(flat_top_padding, flat_bottom_padding));
if (conv_data.input_height > 1 && (flat_top_padding > 1 || flat_bottom_padding > 1)) {
biggest_padding = biggest_padding > padded_row_size ? biggest_padding : padded_row_size;
}
if (!biggest_padding)
return nullptr;
auto flat_input = std::make_shared<ngraph::opset7::Reshape>(input_node,
ngraph::opset7::Constant::create(ngraph::element::i64, ngraph::Shape{2},
ngraph::Shape{1ull, shape_size(input_node.get_shape())}), false);
// Constant with zero padding
auto const_holding_padding = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64, ngraph::Shape{1, biggest_padding}, 0);
std::shared_ptr<ngraph::Node> original_row = flat_input;
ngraph::OutputVector input_rows_to_concat;
// Add top padding
for (size_t p = 0; p < conv_data.pads_begin_height; p++) {
InsertPadding(input_rows_to_concat, padded_row_size, const_holding_padding, biggest_padding);
}
if (flat_left_padding || flat_right_padding) {
// Pad every row of input plain if neccessary
for (size_t h = 0; h < conv_data.input_height; h++) {
// left padding input right padding
// | | |
// +--------------+-----------+
// |
// concat
if (conv_data.input_height > 1)
original_row = FlatCrop(flat_input, h * conv_data.input_width * conv_data.input_channel_count,
conv_data.input_width * conv_data.input_channel_count);
ngraph::OutputVector single_row_concat_inputs;
if (flat_left_padding) {
InsertPadding(single_row_concat_inputs, flat_left_padding, const_holding_padding, biggest_padding);
}
single_row_concat_inputs.push_back(original_row);
if (flat_right_padding) {
InsertPadding(single_row_concat_inputs, flat_right_padding, const_holding_padding, biggest_padding);
}
auto padded_row_concat = std::make_shared<ngraph::opset7::Concat>(single_row_concat_inputs, 1);
input_rows_to_concat.push_back(padded_row_concat);
}
} else {
input_rows_to_concat.push_back(original_row);
}
// Bottom padding
for (size_t p = 0; p < conv_data.pads_end_height; p++) {
InsertPadding(input_rows_to_concat, padded_row_size, const_holding_padding, biggest_padding);
}
auto padded_input_plane = std::make_shared<ngraph::opset7::Concat>(input_rows_to_concat, 1);
return padded_input_plane;
}
std::shared_ptr<ngraph::Function> ConvertPadded2ValidConvTestFixture::get_reference(const modelType& model,
const ngraph::PartialShape& input_shape,
const ngraph::Shape& filters_shape,
const ngraph::Strides& conv_stride,
const ngraph::CoordinateDiff& pads_begin,
const ngraph::CoordinateDiff& pads_end,
const ngraph::Strides& conv_dilation,
const ngraph::Shape& bias_shape,
const ngraph::Strides& maxpool_stride,
const ngraph::Shape& maxpool_shape,
const ngraph::op::PadType& pad_type,
const ConvData& conv_data) {
auto inputParams = std::make_shared<ngraph::opset7::Parameter>(ngraph::element::i64, input_shape);
// Add padding where neccessary
// padding
// padding
// ... row ...
// ... row ...
// ...........
// ... row ...
// padding
// padding
auto padded_input_plane = CreatePaddedNet(inputParams, conv_data);
std::shared_ptr<ngraph::opset7::Result> result;
if (padded_input_plane) {
auto shape_const = std::make_shared<ngraph::opset7::Constant>(ngraph::element::i64, ngraph::Shape{4},
ngraph::Shape{static_cast<size_t>(1),
conv_data.pads_begin_height + conv_data.input_height + conv_data.pads_end_height,
conv_data.pads_begin_width + conv_data.input_width + conv_data.pads_end_width,
conv_data.input_channel_count});
auto padded_input_plane_reshaped = std::make_shared<ngraph::opset7::Reshape>(padded_input_plane, shape_const, false);
result = createFunction(model, padded_input_plane_reshaped, filters_shape, conv_stride,
ngraph::CoordinateDiff{0, 0}, ngraph::CoordinateDiff{0, 0}, conv_dilation, bias_shape,
maxpool_stride, maxpool_shape, ngraph::op::PadType::EXPLICIT, nullptr);
} else {
// Valid padding
result = createFunction(model, inputParams, filters_shape, conv_stride, pads_begin, pads_end, conv_dilation, bias_shape,
maxpool_stride, maxpool_shape, pad_type, nullptr);
}
return std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, ngraph::ParameterVector{inputParams});
}
// ---------------------------------------------------------------------------------------------------------------------
void execute_test(const modelType& model, std::shared_ptr<ngraph::Function> function, std::shared_ptr<ngraph::Function> reference_function) {
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
switch (model) {
default:
case modelType::TranspConvTransp:
manager.register_pass<GNAPluginNS::ConvertPadded2ValidConv>();
break;
case modelType::TranspConvBcastAddTransp:
manager.register_pass<GNAPluginNS::ConvertPaddedWithBias2ValidConv>();
break;
case modelType::TranspConvBcastAddMaxPoolTransp:
manager.register_pass<GNAPluginNS::ConvertPaddedWithBiasMaxPool2ValidConv>();
break;
case modelType::TranspConvBcastAddActTransp:
manager.register_pass<GNAPluginNS::ConvertPaddedWithBiasAF2ValidConv>();
break;
case modelType::TranspConvBcastAddMaxPoolActTransp:
manager.register_pass<GNAPluginNS::ConvertPaddedWithBiasMaxPoolAF2ValidConv>();
break;
case modelType::TranspConvTranspBcastAdd:
manager.register_pass<GNAPluginNS::ConvertPaddedTransposedWithBias2ValidConv>();
break;
case modelType::TranspConvTranspBcastAddAct:
manager.register_pass<GNAPluginNS::ConvertPaddedTransposedWithBiasAF2ValidConv>();
break;
}
manager.run_passes(function);
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES);
const FunctionsComparator::Result result = func_comparator(function, reference_function);
ASSERT_TRUE(result.valid);
}
TEST_P(ConvertPadded2ValidConvTestFixture, CompareFunctions) {
execute_test(model, function, reference_function);
}
INSTANTIATE_TEST_SUITE_P(ConvertPadded2ValidConvTestSuite, ConvertPadded2ValidConvTestFixture,
::testing::Values(
std::make_tuple(modelType::TranspConvTransp, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvBcastAddTransp, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvBcastAddMaxPoolTransp, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvBcastAddActTransp, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::SAME_LOWER),
std::make_tuple(modelType::TranspConvBcastAddMaxPoolActTransp, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::SAME_UPPER),
std::make_tuple(modelType::TranspConvTranspBcastAdd, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 1, 1, 4}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvTranspBcastAddAct, ngraph::PartialShape{1, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 1, 1, 4}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT)));
TEST_P(ConvertPadded2ValidConvTestInvalidFixture, CompareFunctions) {
execute_test(model, function, reference_function);
}
INSTANTIATE_TEST_SUITE_P(ConvertPadded2ValidConvInvalidTestSuite, ConvertPadded2ValidConvTestInvalidFixture,
::testing::Values(
std::make_tuple(modelType::TranspConvTransp, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::SAME_UPPER),
std::make_tuple(modelType::TranspConvBcastAddTransp, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvBcastAddMaxPoolTransp, ngraph::PartialShape{2, 16, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{5, 1}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvBcastAddActTransp, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::SAME_LOWER),
std::make_tuple(modelType::TranspConvBcastAddMaxPoolActTransp, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 5}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 4, 1, 1}, ngraph::Strides{1, 1}, ngraph::Shape{1, 4}, ngraph::op::PadType::SAME_UPPER),
std::make_tuple(modelType::TranspConvTranspBcastAdd, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 1, 1, 4}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT),
std::make_tuple(modelType::TranspConvTranspBcastAddAct, ngraph::PartialShape{2, 1, 16, 8}, ngraph::Shape{1, 2}, ngraph::Strides{1, 1},
ngraph::CoordinateDiff{0, 2}, ngraph::CoordinateDiff{0, 3}, ngraph::Strides{1, 1},
ngraph::Shape{1, 1, 1, 4}, ngraph::Strides{1, 1}, ngraph::Shape{1, 2}, ngraph::op::PadType::EXPLICIT)));
} // namespace
} // namespace testing
@@ -9,7 +9,6 @@
namespace kernel_selector {
// Sub-group size used by "kernel_name_bfyx_os_iyx_osv16" kernel.
constexpr size_t sub_group_size = 16;
ConvolutionKernel_bfyx_os_iyx_osv16::ConvolutionKernel_bfyx_os_iyx_osv16()
: ConvolutionKernelBase("convolution_gpu_bfyx_os_iyx_osv16") {
@@ -94,6 +93,9 @@ static void shrink_blocks_to_output_size(size_t output_x, size_t output_y, size_
block_x -= unused_x / simds_x;
block_y -= unused_y / simds_y;
block_x = Align(block_x, 2);
block_y = Align(block_y, 2);
}
ConvolutionKernel_bfyx_os_iyx_osv16::AutoTuneOption ConvolutionKernel_bfyx_os_iyx_osv16::GetAutoTuneOptions(
@@ -107,9 +109,11 @@ ConvolutionKernel_bfyx_os_iyx_osv16::AutoTuneOption ConvolutionKernel_bfyx_os_iy
const convolution_params& cp = static_cast<const convolution_params&>(p);
const auto& sub_group_size = GetSubGroupSize(cp);
if (cp.stride.x == 1 && cp.stride.y == 1) {
if (cp.filterSize.x == 1 && cp.filterSize.y == 1) {
option.blockWidth = 16;
option.blockWidth = sub_group_size;
option.blockHeight = 1;
option.prefetch = 4;
// if less than 16 values is required to compute one single row of output
@@ -143,13 +147,13 @@ ConvolutionKernel_bfyx_os_iyx_osv16::AutoTuneOption ConvolutionKernel_bfyx_os_iy
if (cp.filterSize.x != 1 || cp.filterSize.y != 1 || cp.output.Batch().v != 1) {
shrink_blocks_to_output_size(cp.output.X().v, cp.output.Y().v, option.blockWidth, option.blockHeight);
}
return option;
}
ConvolutionKernelBase::DispatchData ConvolutionKernel_bfyx_os_iyx_osv16::SetDefault(const convolution_params& cp,
int autoTuneIndex) const {
DispatchData dispatchData = ConvolutionKernelBase::SetDefault(cp);
const auto& sub_group_size = GetSubGroupSize(cp);
const auto of_maps = cp.output.Feature().v;
const auto of_maps_per_group = of_maps / cp.groups;
@@ -196,6 +200,9 @@ bool ConvolutionKernel_bfyx_os_iyx_osv16::Validate(const Params& p, const option
JitConstants ConvolutionKernel_bfyx_os_iyx_osv16::GetJitConstants(const convolution_params& params,
const DispatchData& dispatchData) const {
const convolution_params& cp = static_cast<const convolution_params&>(params);
const auto& sub_group_size = GetSubGroupSize(cp);
const auto of_maps = params.output.Feature().v;
const auto of_maps_per_group = of_maps / params.groups;
const size_t of_threads_per_batch = RoundUp(of_maps_per_group, sub_group_size);
@@ -209,7 +216,7 @@ JitConstants ConvolutionKernel_bfyx_os_iyx_osv16::GetJitConstants(const convolut
jit.Merge(MakeFusedOpsJitConstants(params, {conf_scalar}));
}
jit.AddConstant(MakeJitConstant("OSV_SIZE", 16));
jit.AddConstant(MakeJitConstant("SUB_GROUP_SIZE", dispatchData.lws[2]));
jit.AddConstant(MakeJitConstant("OUTPUT_BLOCK_WIDTH", dispatchData.cldnnStyle.blockWidth));
jit.AddConstant(MakeJitConstant("OUTPUT_BLOCK_HEIGHT", dispatchData.cldnnStyle.blockHeight));
@@ -4,6 +4,7 @@
#pragma once
#include "api/cldnn/runtime/device_info.hpp"
#include "convolution_kernel_base.h"
#include <string>
#include <vector>
@@ -34,6 +35,16 @@ protected:
bool Validate(const Params& p, const optional_params& o) const override;
bool NeedPaddedInput() const override { return true; }
DispatchData SetDefault(const convolution_params& arg, int autoTuneIndex = -1) const override;
size_t GetSubGroupSize(const convolution_params& params) const {
if (params.engineInfo.computeUnitsCount <= 24) {
// Smaller # EU tends to be computation bounds.
// In such case, using larger worksize will result in larger computational inefficiency
// w.r.t the unalined output feature
return (params.output.Feature().v > 8) ? 16 : 8;
} else {
return 16;
}
}
private:
struct AutoTuneOption {
@@ -83,12 +83,11 @@ KERNEL(convolution_gpu_bfyx_os_iyx_osv16)(
uint fmg = feature_idx / SUB_GROUP_SIZE;
const uint g = split_idx;
#endif
UNIT_TYPE in[IN_BLOCK_ARRAY_SIZE];
UNIT_TYPE out[OUTPUT_BLOCK_WIDTH * OUTPUT_BLOCK_HEIGHT];
UNIT_TYPE w[PREFETCH];
uint in_addr;
uint weight_addr = fmg * FILTER_IFM_NUM * FILTER_SIZE_X * FILTER_SIZE_Y * SUB_GROUP_SIZE + lid;
uint weight_addr = fmg * FILTER_IFM_NUM * FILTER_SIZE_X * FILTER_SIZE_Y * OSV_SIZE + lid;
#if GROUPED
weight_addr += g * FILTER_GROUPS_PITCH;
@@ -156,7 +155,7 @@ KERNEL(convolution_gpu_bfyx_os_iyx_osv16)(
in_addr += INPUT0_FEATURE_PITCH;
for(int pf=0; pf<PREFETCH; pf++) {
w[pf] = weights[weight_addr]; weight_addr += SUB_GROUP_SIZE;
w[pf] = weights[weight_addr]; weight_addr += OSV_SIZE;
}
uint wi = 0;
@@ -182,12 +181,12 @@ KERNEL(convolution_gpu_bfyx_os_iyx_osv16)(
}
}
w[wi % PREFETCH] = weights[weight_addr];
weight_addr += SUB_GROUP_SIZE; // weights must be stored in just the right SIMD swizzled format for this to work, see host code for details.
weight_addr += OSV_SIZE; // weights must be stored in just the right SIMD swizzled format for this to work, see host code for details.
wi++;
});
});
// addr went beyond due to prefetch so move it back to correct location.
weight_addr -= PREFETCH * SUB_GROUP_SIZE;
weight_addr -= PREFETCH * OSV_SIZE;
}
uint out_split_offset = g * OUTPUT_FEATURE_PITCH * FILTER_OFM_NUM;
@@ -175,7 +175,6 @@ extensions/front/kaldi/tdnn_component_replacer.py
extensions/front/LayerNorm.py
extensions/front/Log1p.py
extensions/front/MatMul_normalizer.py
extensions/front/Mish_fusion.py
extensions/front/MoveEmbeddedInputsToInputs.py
extensions/front/mxnet/__init__.py
extensions/front/mxnet/activation.py
@@ -329,12 +328,10 @@ extensions/front/onnx/priorbox_clustered_ext.py
extensions/front/onnx/priorbox_ext.py
extensions/front/onnx/priorgridgenerator_ext.py
extensions/front/onnx/proposal_ext.py
extensions/front/onnx/quantize_dequantize_linear.py
extensions/front/onnx/quantize_ext.py
extensions/front/onnx/quantize_linear_ext.py
extensions/front/onnx/range_ext.py
extensions/front/onnx/reduce_ext.py
extensions/front/onnx/remove_filtering_boxes_by_size.py
extensions/front/onnx/reshape_ext.py
extensions/front/onnx/resize_ext.py
extensions/front/onnx/reverse_sequence_ext.py
@@ -371,13 +368,11 @@ extensions/front/RollWithEmptyAxesReplacer.py
extensions/front/scatter_normalizer.py
extensions/front/SizeReplacer.py
extensions/front/softmax.py
extensions/front/Softplus_fusion.py
extensions/front/softsign_replacer.py
extensions/front/sparse_to_dense_replacer.py
extensions/front/split_normalizer.py
extensions/front/SqueezeNormalize.py
extensions/front/sub.py
extensions/front/Swish_fusion.py
extensions/front/tf/__init__.py
extensions/front/tf/activation_ext.py
extensions/front/tf/argmax_ext.py
@@ -1,48 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.front.Softplus_fusion import SoftplusFusion
from extensions.ops.activation_ops import Mish
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.subgraph_matcher import SubgraphMatch
from mo.graph.graph import Graph, rename_nodes
class MishFusion(FrontReplacementSubgraph):
"""
The transformation looks for the pattern with Softplus defining the Mish function: Mish(x) = x * tanh(SoftPlus(x)).
"""
enabled = True
def run_after(self):
return [SoftplusFusion]
def pattern(self):
return dict(
nodes=[
('mul', dict(op='Mul')),
('tanh', dict(op='Tanh')),
('softplus', dict(op='SoftPlus')),
],
edges=[
('softplus', 'tanh'),
('tanh', 'mul'),
])
def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]):
mul = match['mul']
mul_name = mul.soft_get('name', mul.id)
softplus = match['softplus']
# determine the input port of Mul which gets the 'input' node output
input_port_idx = int(mul.in_port(0).get_connection().get_source().node.soft_get('op') == 'Tanh')
# check that the same tensor provided as input to Mul and SoftPlus
if mul.in_port(input_port_idx).get_source() != softplus.in_port(0).get_source():
return
mish = Mish(graph, {}).create_node()
mish.in_port(0).connect(mul.in_port(input_port_idx).get_source())
mul.out_port(0).get_connection().set_source(mish.out_port(0))
rename_nodes([(mul, mul_name + '/TBR'), (mish, mul_name)])
@@ -1,43 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.ops.activation_ops import SoftPlus
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.subgraph_matcher import SubgraphMatch
from mo.graph.graph import Graph, rename_nodes
from mo.middle.pattern_match import check_value
class SoftplusFusion(FrontReplacementSubgraph):
"""
The transformation looks for the pattern for the Softplus function: Softplus(x) = ln(1 + e^x)
"""
enabled = True
def pattern(self):
return dict(
nodes=[
('exp', dict(op='Exp')),
('add', dict(op='Add')),
('const_1', dict(op='Const', value=lambda v: check_value(v, lambda x: np.allclose(x, 1.0, atol=1e-6)))),
('ln', dict(op='Log')),
],
edges=[
('exp', 'add', {}),
('const_1', 'add', {}),
('add', 'ln', {}),
])
def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]):
ln = match['ln']
exp = match['exp']
ln_name = ln.soft_get('name', ln.id)
softplus = SoftPlus(graph, {}).create_node()
softplus.in_port(0).connect(exp.in_port(0).get_source())
ln.out_port(0).get_connection().set_source(softplus.out_port(0))
rename_nodes([(ln, ln_name + '/TBR'), (softplus, ln_name)])
@@ -1,87 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.ops.activation_ops import Swish
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.subgraph_matcher import SubgraphMatch
from mo.graph.graph import Graph, rename_nodes
class SwishWithSigmoidWithoutBeta(FrontReplacementSubgraph):
"""
The transformation looks for the pattern with Sigmoid defining the Swish function: Swish(x) = x * Sigmoid(x)
"""
enabled = True
def pattern(self):
return dict(
nodes=[
('sigmoid', dict(op='Sigmoid')),
('mul', dict(op='Mul')),
],
edges=[
('sigmoid', 'mul', {}),
])
def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]):
sigmoid = match['sigmoid']
mul = match['mul']
mul_name = mul.soft_get('name', mul.id)
# determine the input port of Mul which gets the 'input' node output
mul_input_port_idx = int(mul.in_port(0).get_connection().get_source().node.soft_get('op') == 'Sigmoid')
# check that the same tensor provided as input to Mul and Sigmoid
if mul.in_port(mul_input_port_idx).get_source() != sigmoid.in_port(0).get_source():
return
swish = Swish(graph, {}).create_node()
swish.in_port(0).connect(sigmoid.in_port(0).get_source())
mul.out_port(0).get_connection().set_source(swish.out_port(0))
rename_nodes([(mul, mul_name + '/TBR'), (swish, mul_name)])
class SwishWithSigmoidWithBeta(FrontReplacementSubgraph):
"""
The transformation looks for the pattern with Sigmoid defining the Swish function: Swish(x) = x * Sigmoid(x * beta)
"""
enabled = True
def pattern(self):
return dict(
nodes=[
('sigmoid', dict(op='Sigmoid')),
('beta', dict()),
('mul_beta', dict(op='Mul')),
('mul', dict(op='Mul')),
],
edges=[
('beta', 'mul_beta', {}),
('mul_beta', 'sigmoid', {}),
('sigmoid', 'mul', {}),
])
def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]):
beta = match['beta']
mul = match['mul']
mul_beta = match['mul_beta']
mul_name = mul.soft_get('name', mul.id)
# determine the input port of Muls which get the 'input' node output
mul_beta_input_port_idx = int(mul_beta.in_port(0).get_connection().get_source().node.id == beta.id)
mul_input_port_idx = int(mul.in_port(0).get_connection().get_source().node.soft_get('op') == 'Sigmoid')
# check that the same tensor provided as input to Mul and MulBeta
if mul.in_port(mul_input_port_idx).get_source() != mul_beta.in_port(mul_beta_input_port_idx).get_source():
return
swish = Swish(graph, {}).create_node()
swish.in_port(0).connect(mul_beta.in_port(mul_beta_input_port_idx).get_source())
# connect Beta value
swish.in_port(1).connect(mul_beta.in_port(1 - mul_beta_input_port_idx).get_source())
mul.out_port(0).get_connection().set_source(swish.out_port(0))
rename_nodes([(mul, mul_name + '/TBR'), (swish, mul_name)])
@@ -1,87 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import logging as log
import numpy as np
from extensions.ops.fakequantize import FakeQuantize
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.subgraph_matcher import SubgraphMatch
from mo.graph.graph import Graph, rename_nodes
from mo.ops.const import Const
from mo.utils.error import Error
class QuantizeDequantizeLinear(FrontReplacementSubgraph):
"""
Fuses QuantizeLinear and DequantizeLinear nodes into single FakeQuantize.
Covers cases when the values for zero point and scale are same in both QuantizeLinear and DequantizeLinear.
"""
enabled = True
def pattern(self):
return dict(
nodes=[
('quantize', dict(op='QuantizeLinear')),
('dequantize', dict(op='DequantizeLinear')),
],
edges=[
('quantize', 'dequantize', {'in': 0}),
]
)
def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]):
q = match['quantize']
dq = match['dequantize']
q_scale = q.in_port(1).get_source().node
q_zerop = q.in_port(2).get_source().node
dq_scale = dq.in_port(1).get_source().node
dq_zerop = dq.in_port(2).get_source().node
inp_port = q.in_port(0).get_source()
name = inp_port.node.soft_get('name', inp_port.node.id)
# only constant as for zero_point/scale supported
if q_scale.soft_get('type') == 'Const' and dq_scale.soft_get('type') == 'Const' and \
q_zerop.soft_get('type') == 'Const' and dq_zerop.soft_get('type') == 'Const':
# only patterns with same scale/zero_point values for Q and DQ are supported
if q_scale.value == dq_scale.value and q_zerop.value == dq_zerop.value:
log.debug('Found Q-DQ pattern after {}'.format(name))
zero_point_type = q_zerop.value.dtype
# data type affects range of output values: [-128..127] or [0..255]
if zero_point_type == np.int8:
output_min_value = -128.0
output_max_value = 127.0
elif zero_point_type == np.uint8:
output_min_value = 0.0
output_max_value = 255.0
else:
raise Error('Not supported type {} for zero point value in node {}'.format(
zero_point_type, q_zerop.soft_get('name')))
min_value = q_scale.value * (output_min_value - q_zerop.value)
max_value = q_scale.value * (output_max_value - q_zerop.value)
input_min = Const(graph, {'value': np.array(min_value)}).create_node()
input_max = Const(graph, {'value': np.array(max_value)}).create_node()
FQ = FakeQuantize(graph, {
'levels': 256,
'name': match['quantize'].name + '_Dequantize/FakeQuantize'
}).create_node()
FQ.in_port(0).connect(match['quantize'].in_port(0).get_source())
FQ.in_port(1).connect(input_min.out_port(0))
FQ.in_port(2).connect(input_max.out_port(0))
FQ.in_port(3).connect(input_min.out_port(0))
FQ.in_port(4).connect(input_max.out_port(0))
match['dequantize'].out_port(0).get_connection().set_source(FQ.out_port(0))
dq_name = match['dequantize'].soft_get('name', match['dequantize'].id)
rename_nodes([(match['dequantize'], dq_name + '/to_be_removed'), (FQ, dq_name)])
else:
raise Error('QuantizeLinear and DequantizeLinear (after {}) have different scale or zero-point values, '
'cannot fuse into FakeQuantize!'.format(name))
@@ -1,117 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.front.split_normalizer import AttributedVariadicSplitToVariadicSplit
from extensions.ops.range import Range
from mo.front.common.partial_infer.utils import int64_array
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.tf.graph_utils import create_op_node_with_second_input
from mo.graph.graph import Graph
from mo.graph.graph import Node
from mo.ops.const import Const
from mo.ops.shape import Shape
from mo.ops.squeeze import Squeeze
from mo.utils.shape import node_to_get_batch_value
def skip_nodes_by_condition(current_node: Node, condition: callable):
while condition(current_node):
current_node = current_node.in_node()
return current_node
class RemoveFilteringBoxesBySize(FrontReplacementSubgraph):
"""
The transformation looks for a sub-graph that selects boxes with nonzero height and width. The output node of this
sub-graph is a Cast node that produces indices of nodes to be preserved. The transformation creates a new sub-graph
that produces a tensor with values from 0 to input.shape[0] to select all boxes. The output of this sub-graph will
be used in the NonMaxSuppression so the implementation of this layer should ignore boxes with negative sizes.
"""
enabled = True
force_clean_up = True
def run_after(self):
return [AttributedVariadicSplitToVariadicSplit]
def pattern(self):
return dict(
nodes=[
('split', dict(op='VariadicSplit')),
('sub_1', dict(op='Sub')),
('sub_2', dict(op='Sub')),
('add_1', dict(op='Add')),
('add_2', dict(op='Add')),
('concat', dict(op='Concat')),
('split_2', dict(op='VariadicSplit')),
('squeeze_1', dict(op='Squeeze')),
('squeeze_2', dict(op='Squeeze')),
('less_1', dict(op='Less')),
('less_2', dict(op='Less')),
('not_1', dict(op='LogicalNot')),
('not_2', dict(op='LogicalNot')),
('cast_11', dict(op='Cast')),
('cast_12', dict(op='Cast')),
('cast_21', dict(op='Cast')),
('cast_22', dict(op='Cast')),
('and', dict(op='LogicalAnd')),
('cast_31', dict(op='Cast')),
('cast_32', dict(op='Cast')),
('nonzero', dict(op='NonZero')),
('transpose', dict(op='Transpose')),
('squeeze', dict(op='Squeeze')),
('cast', dict(op='Cast')),
],
edges=[
('split', 'sub_1', {'in': 0, 'out': 2}),
('split', 'sub_1', {'in': 1, 'out': 0}),
('split', 'sub_2', {'in': 0, 'out': 3}),
('split', 'sub_2', {'in': 1, 'out': 1}),
('sub_1', 'add_1', {}),
('sub_2', 'add_2', {}),
('split', 'concat', {'in': 0, 'out': 0}),
('split', 'concat', {'in': 1, 'out': 1}),
('add_1', 'concat', {'in': 2, 'out': 0}),
('add_2', 'concat', {'in': 3, 'out': 0}),
('concat', 'split_2', {}),
('split_2', 'squeeze_1', {'in': 0, 'out': 2}),
('split_2', 'squeeze_2', {'in': 0, 'out': 3}),
('squeeze_1', 'less_1', {}),
('squeeze_2', 'less_2', {}),
('less_1', 'not_1', {}),
('less_2', 'not_2', {}),
('not_1', 'cast_11', {}),
('cast_11', 'cast_12', {}),
('not_2', 'cast_21', {}),
('cast_21', 'cast_22', {}),
('cast_12', 'and', {}),
('cast_22', 'and', {}),
('and', 'cast_31', {}),
('cast_31', 'cast_32', {}),
('cast_32', 'nonzero', {}),
('nonzero', 'transpose', {}),
('transpose', 'squeeze', {}),
('squeeze', 'cast', {}),
])
def replace_sub_graph(self, graph: Graph, match: dict):
source_connection = match['split'].in_port(0).get_connection()
source_node = source_connection.get_source().node
cast_node = match['cast']
range_node = Range(graph, {'name': source_node.id + '/Range'}).create_node()
start_node = Const(graph, {'name': range_node.id + '/Start', 'value': int64_array(0)}).create_node()
step_node = Const(graph, {'name': range_node.id + '/Step', 'value': int64_array(1)}).create_node()
input_shape_node = Shape(graph, {'name': start_node.id + '/Shape'}).create_node()
input_shape_node.in_port(0).connect(source_node.out_port(0))
limit_node_1D = node_to_get_batch_value(input_shape_node)
limit_node = create_op_node_with_second_input(graph, Squeeze, int64_array([0]),
{'name': source_node.id + '/batch_0D_value'}, limit_node_1D)
range_node.in_port(0).connect(start_node.out_port(0))
range_node.in_port(1).connect(limit_node.out_port(0))
range_node.in_port(2).connect(step_node.out_port(0))
cast_node.out_port(0).get_connection().set_source(range_node.out_port(0))
graph.remove_nodes_from([node.id for node in match.values()])
@@ -6,6 +6,8 @@
:: Check if Python is installed
setlocal
set ROOT_DIR=%~dp0
python --version 2>NUL
if errorlevel 1 (
echo Error^: Python is not installed. Please install Python 3.5 ^(64-bit^) or higher from https://www.python.org/downloads/
@@ -35,10 +37,16 @@ if not "%python_ver%"=="okay" (
:: install Python modules
set USE_VENV="false"
set VENV_DIR=%USERPROFILE%\Documents\Intel\OpenVINO\venv_openvino
IF /I "%1%" EQU "" (
set postfix=
) ELSE (
IF /I "%1%" EQU "venv" (
set postfix=
set USE_VENV="true"
) ELSE (
IF /I "%1%" EQU "caffe" (
set postfix=_caffe
) ELSE (
@@ -59,6 +67,7 @@ IF /I "%1%" EQU "" (
) ELSE (
echo Unsupported framework
goto error
)
)
)
)
@@ -67,10 +76,20 @@ IF /I "%1%" EQU "" (
)
)
pip3 install --user -r ..\requirements%postfix%.txt
IF /I "%2%" EQU "venv" (
set USE_VENV="true"
)
IF %USE_VENV% == "true" (
python -m venv "%VENV_DIR%"
call "%VENV_DIR%\Scripts\activate.bat"
)
python -m pip install -U pip
python -m pip install -r "%ROOT_DIR%..\requirements%postfix%.txt"
:: Chek MO version
set python_command='python "%~dp0..\mo\utils\extract_release_version.py"'
set python_command='python "%ROOT_DIR%..\mo\utils\extract_release_version.py"'
FOR /F "delims=" %%i IN (%python_command%) DO set mo_release_version=%%i
IF "%mo_release_version%" == "None.None" (
set mo_is_custom="true"
@@ -80,12 +99,12 @@ IF "%mo_release_version%" == "None.None" (
:: Check if existing IE Python bindings satisfy requirements
set errorlevel=
python "%~dp0..\mo\utils\find_ie_version.py"
python "%ROOT_DIR%..\mo\utils\find_ie_version.py"
IF %errorlevel% EQU 0 goto ie_search_end
:: Check if OV already installed via pip
set errorlevel=
pip3 show openvino
python -m pip show openvino
IF %errorlevel% EQU 0 (
IF %mo_is_custom% == "true" (
echo [ WARNING ] OpenVINO ^(TM^) Toolkit version installed in pip is incompatible with the Model Optimizer
@@ -110,7 +129,7 @@ IF %mo_is_custom% == "true" (
)
set errorlevel=
pip3 install openvino==%mo_release_version%
python -m pip install openvino==%mo_release_version%
IF %errorlevel% NEQ 0 (
echo [ WARNING ] Could not find the OpenVINO ^(TM^) toolkit version %mo_release_version% in pip
echo [ WARNING ] The highest OpenVINO ^(TM^) toolkit version will be installed ^(may be incompatible with current Model Optimizer version^)
@@ -119,17 +138,17 @@ IF %errorlevel% NEQ 0 (
)
set errorlevel=
python "%~dp0..\mo\utils\find_ie_version.py"
python "%ROOT_DIR%..\mo\utils\find_ie_version.py"
IF %errorlevel% EQU 0 goto ie_search_end
echo [ WARNING ] The installed OpenVINO ^(TM^) toolkit version %mo_release_version% does not work as expected. Uninstalling...
pip3 uninstall -y openvino
python -m pip uninstall -y openvino
echo [ WARNING ] Consider building the Inference Engine Python API from sources
goto ie_search_end
:install_last_ov
set errorlevel=
pip3 install openvino
python -m pip install openvino
IF %errorlevel% NEQ 0 (
echo [ WARNING ] Could not find OpenVINO ^(TM^) toolkit version available in pip for installation
echo [ WARNING ] Consider building the Inference Engine Python API from sources
@@ -137,16 +156,26 @@ IF %errorlevel% NEQ 0 (
)
set errorlevel=
python "%~dp0..\mo\utils\find_ie_version.py"
python "%ROOT_DIR%..\mo\utils\find_ie_version.py"
IF %errorlevel% EQU 0 goto ie_search_end
echo [ WARNING ] The installed highest OpenVINO ^(TM^) toolkit version doesn't work as expected. Uninstalling...
pip3 uninstall -y openvino
python -m pip uninstall -y openvino
echo [ WARNING ] Consider building the Inference Engine Python API from sources
goto ie_search_end
:ie_search_end
IF %USE_VENV% == "true" (
echo.
echo Before running the Model Optimizer, please activate virtualenv environment by running "%VENV_DIR%\Scripts\activate.bat"
) ELSE (
echo.
echo [ WARNING ] All Model Optimizer dependencies are installed globally.
echo [ WARNING ] If you want to keep Model Optimizer in separate sandbox
echo [ WARNING ] run install_prerequisites.bat "{caffe|tf|tf2|mxnet|kaldi|onnx}" venv
)
echo *****************************************************************************************
echo Optional: To speed up model conversion process, install protobuf-*.egg located in the
echo "model-optimizer\install_prerequisites" folder or building protobuf library from sources.
@@ -35,6 +35,7 @@ for ((i=1;i <= $#;i++)) {
esac
}
VENV_DIR="$HOME/venv_openvino"
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]-$0}" )" && pwd )"
if [[ -f /etc/centos-release ]]; then
@@ -53,23 +54,8 @@ if [[ $DISTRO == "centos" ]]; then
elif command -v python3.5 >/dev/null 2>&1; then
python_binary=python3.5
fi
if [ -z "$python_binary" ]; then
sudo -E yum install -y https://centos7.iuscommunity.org/ius-release.rpm
sudo -E yum install -y python36u python36u-pip
sudo -E pip3.6 install virtualenv
python_binary=python3.6
fi
# latest pip is needed to install tensorflow
sudo -E "$python_binary" -m pip install --upgrade pip
elif [[ $DISTRO == "ubuntu" ]]; then
sudo -E apt update
sudo -E apt -y --no-install-recommends install python3-pip python3-venv
else
python_binary=python3
sudo -E "$python_binary" -m pip install --upgrade pip
elif [[ "$OSTYPE" == "darwin"* ]]; then
python_binary=python3
python3 -m pip install --upgrade pip
fi
install_latest_ov() {
@@ -181,21 +167,21 @@ find_ie_bindings() {
}
if [[ $V_ENV -eq 1 ]]; then
"$python_binary" -m venv "$SCRIPTDIR/../venv${postfix}"
source "$SCRIPTDIR/../venv${postfix}/bin/activate"
venv_python_binary="$SCRIPTDIR/../venv${postfix}/bin/$python_binary"
$venv_python_binary -m pip install -r "$SCRIPTDIR/../requirements${postfix}.txt"
"$python_binary" -m venv "$VENV_DIR"
source "$VENV_DIR/bin/activate"
venv_python_binary="$VENV_DIR/bin/$python_binary"
# latest pip is needed to install tensorflow
"$venv_python_binary" -m pip install --upgrade pip
"$venv_python_binary" -m pip install -r "$SCRIPTDIR/../requirements${postfix}.txt"
find_ie_bindings "$venv_python_binary" false
echo
echo "Before running the Model Optimizer, please activate virtualenv environment by running \"source ${SCRIPTDIR}/../venv${postfix}/bin/activate\""
echo "Before running the Model Optimizer, please activate virtualenv environment by running \"source $VENV_DIR/bin/activate\""
else
if [[ "$OSTYPE" == "darwin"* ]]; then
python3 -m pip install -r "$SCRIPTDIR/../requirements${postfix}.txt"
find_ie_bindings python3 false
else
sudo -E $python_binary -m pip install -r "$SCRIPTDIR/../requirements${postfix}.txt"
find_ie_bindings $python_binary true
fi
# latest pip is needed to install tensorflow
"$python_binary" -m pip install --upgrade pip
"$python_binary" -m pip install -r "$SCRIPTDIR/../requirements${postfix}.txt"
find_ie_bindings "$python_binary" false
echo
echo "[WARNING] All Model Optimizer dependencies are installed globally."
echo "[WARNING] If you want to keep Model Optimizer in separate sandbox"
echo "[WARNING] run install_prerequisites.sh \"{caffe|tf|tf2|mxnet|kaldi|onnx}\" venv"
@@ -70,8 +70,18 @@ def tf_tensor_content(tf_dtype, shape, pb_tensor):
log.error(decode_err_msg, extra={'is_warning': True})
value = np.array(type_helper[1](pb_tensor))
if len(shape) == 0 or shape.prod() == 0:
if len(value) == 1:
# Ignore an empty value, if len(shape) > 1
# For example, value = [] and shape = [1, 1, 0]
# This is needed to reshape this value later and to return reshaped value = [[[]]]
# Otherwise there can be failures during partial inference, because we are storing an empty value with incorrect
# shape
if len(shape) == 0 or (len(shape) == 1 and shape.prod() == 0):
try:
value_length = len(value)
except TypeError:
# case, when value is a scalar
value_length = 0
if value_length == 1:
# return scalar if shape is [] otherwise broadcast according to shape
try:
return np.array(value[0], dtype=type_helper[0])
@@ -1,66 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
from extensions.front.Mish_fusion import MishFusion
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, regular_op, result, build_graph_with_edge_attrs
ref_nodes = {**regular_op('input', {'type': 'Parameter'}),
**regular_op('mish', {'type': 'Mish', 'name': 'final_mul'}),
**result('result')
}
ref_edges = [('input', 'mish'), ('mish', 'result')]
class MishFusionTest(unittest.TestCase):
nodes = {
**regular_op('input', {'type': 'Parameter'}),
**regular_op('softplus', {'op': 'SoftPlus'}),
**regular_op('tanh', {'op': 'Tanh'}),
**regular_op('mul', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}
edges = [('input', 'softplus', {'in': 0, 'out': 0}),
('input', 'mul', {'in': 0, 'out': 0}),
('softplus', 'tanh', {'in': 0, 'out': 0}),
('tanh', 'mul', {'in': 1, 'out': 0}),
('mul', 'result', {'in': 0, 'out': 0})]
def test_mish_fusion(self):
graph = build_graph_with_edge_attrs(self.nodes, self.edges, {})
graph_ref = build_graph(ref_nodes, ref_edges)
graph.stage = 'front'
MishFusion().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
self.assertTrue(len(graph.get_op_nodes(name='final_mul')) == 1 and
graph.get_op_nodes(name='final_mul')[0].op == 'Mish')
def test_mish_fusion_different_source(self):
# check case when different tensors goes to Mul and SoftPlus
graph = build_graph_with_edge_attrs({
**regular_op('input', {'type': 'Parameter'}),
**regular_op('input_2', {'type': 'Parameter'}),
**regular_op('softplus', {'op': 'SoftPlus'}),
**regular_op('tanh', {'op': 'Tanh'}),
**regular_op('mul', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}, [('input', 'softplus', {'in': 0, 'out': 0}),
('input_2', 'mul', {'in': 0, 'out': 0}),
('softplus', 'tanh', {'in': 0, 'out': 0}),
('tanh', 'mul', {'in': 1, 'out': 0}),
('mul', 'result', {'in': 0, 'out': 0})], {})
graph_ref = graph.copy()
graph.stage = 'front'
MishFusion().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
@@ -1,57 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
from extensions.front.Softplus_fusion import SoftplusFusion
from mo.front.common.partial_infer.utils import float_array
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, const, regular_op, result, build_graph_with_edge_attrs
ref_nodes = {**regular_op('input', {'type': 'Parameter'}),
**regular_op('softplus', {'type': 'SoftPlus', 'name': 'final_log'}),
**result('result')
}
ref_edges = [('input', 'softplus'), ('softplus', 'result')]
class SoftplusFusionTest(unittest.TestCase):
nodes = {
**regular_op('input', {'type': 'Parameter'}),
**regular_op('exp', {'op': 'Exp'}),
**const('const_1', float_array([1.0])),
**regular_op('add', {'op': 'Add'}),
**regular_op('ln', {'op': 'Log', 'name': 'final_log'}),
**result('result'),
}
edges = [('input', 'exp', {'in': 0, 'out': 0}),
('const_1', 'add', {'in': 0, 'out': 0}),
('exp', 'add', {'in': 1, 'out': 0}),
('add', 'ln', {'in': 0, 'out': 0}),
('ln', 'result', {'in': 0, 'out': 0})]
def test_softplus_fusion_test(self):
graph = build_graph_with_edge_attrs(self.nodes, self.edges, {})
graph_ref = build_graph(ref_nodes, ref_edges)
graph.stage = 'front'
SoftplusFusion().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
self.assertTrue(len(graph.get_op_nodes(name='final_log')) == 1 and
graph.get_op_nodes(name='final_log')[0].op == 'SoftPlus')
def test_softplus_fusion_test_wrong_const(self):
graph = build_graph_with_edge_attrs(self.nodes, self.edges, {'const_1': {'value': float_array([0.9999])}})
graph_ref = graph.copy()
graph.stage = 'front'
SoftplusFusion().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
@@ -1,119 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
from extensions.front.Swish_fusion import SwishWithSigmoidWithoutBeta, SwishWithSigmoidWithBeta
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, regular_op, result, build_graph_with_edge_attrs
ref_nodes = {**regular_op('input', {'type': 'Parameter'}),
**regular_op('swish', {'type': 'Swish', 'name': 'final_mul'}),
**result('result')
}
ref_edges = [('input', 'swish'), ('swish', 'result')]
class SwishWithSigmoidWithoutBetaTest(unittest.TestCase):
nodes = {
**regular_op('input', {'type': 'Parameter'}),
**regular_op('sigmoid', {'op': 'Sigmoid'}),
**regular_op('mul', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}
edges = [('input', 'mul', {'in': 0, 'out': 0}),
('input', 'sigmoid', {'in': 0, 'out': 0}),
('sigmoid', 'mul', {'in': 1, 'out': 0}),
('mul', 'result', {'in': 0, 'out': 0})]
def test_swish_with_sigmoid_without_beta_test(self):
graph = build_graph_with_edge_attrs(self.nodes, self.edges, {})
graph_ref = build_graph(ref_nodes, ref_edges)
graph.stage = 'front'
SwishWithSigmoidWithoutBeta().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
self.assertTrue(len(graph.get_op_nodes(name='final_mul')) == 1 and
graph.get_op_nodes(name='final_mul')[0].op == 'Swish')
def test_swish_with_sigmoid_without_beta_different_tensors(self):
graph = build_graph_with_edge_attrs({
**regular_op('input', {'type': 'Parameter'}),
**regular_op('input_2', {'type': 'Parameter'}),
**regular_op('sigmoid', {'op': 'Sigmoid'}),
**regular_op('mul', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}, [('input_2', 'mul', {'in': 0, 'out': 0}),
('input', 'sigmoid', {'in': 0, 'out': 0}),
('sigmoid', 'mul', {'in': 1, 'out': 0}),
('mul', 'result', {'in': 0, 'out': 0})], {})
graph_ref = graph.copy()
graph.stage = 'front'
SwishWithSigmoidWithoutBeta().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
class SwishWithSigmoidWithBetaTest(unittest.TestCase):
nodes = {
**regular_op('input', {'type': 'Parameter'}),
**regular_op('beta', {'type': 'Parameter'}),
**regular_op('mul_beta', {'op': 'Mul'}),
**regular_op('sigmoid', {'op': 'Sigmoid'}),
**regular_op('mul_2', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}
edges = [('input', 'mul_beta', {'in': 0, 'out': 0}),
('input', 'mul_2', {'in': 0, 'out': 0}),
('beta', 'mul_beta', {'in': 1, 'out': 0}),
('mul_beta', 'sigmoid', {'in': 0, 'out': 0}),
('sigmoid', 'mul_2', {'in': 1, 'out': 0}),
('mul_2', 'result', {'in': 0, 'out': 0})]
def test_swish_with_sigmoid_with_beta_test(self):
graph = build_graph_with_edge_attrs(self.nodes, self.edges, {})
new_ref_nodes = ref_nodes.copy()
new_ref_nodes.update(**regular_op('beta', {'type': 'Parameter'}))
graph_ref = build_graph(new_ref_nodes, ref_edges + [('beta', 'swish')])
graph.stage = 'front'
SwishWithSigmoidWithBeta().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
self.assertTrue(len(graph.get_op_nodes(name='final_mul')) == 1 and
graph.get_op_nodes(name='final_mul')[0].op == 'Swish')
def test_swish_with_sigmoid_with_beta_different_tensors(self):
graph = build_graph_with_edge_attrs({
**regular_op('input', {'type': 'Parameter'}),
**regular_op('input_2', {'type': 'Parameter'}),
**regular_op('beta', {'type': 'Parameter'}),
**regular_op('mul_beta', {'op': 'Mul'}),
**regular_op('sigmoid', {'op': 'Sigmoid'}),
**regular_op('mul_2', {'op': 'Mul', 'name': 'final_mul'}),
**result('result'),
}, [('input', 'mul_beta', {'in': 0, 'out': 0}),
('input_2', 'mul_2', {'in': 0, 'out': 0}),
('beta', 'mul_beta', {'in': 1, 'out': 0}),
('mul_beta', 'sigmoid', {'in': 0, 'out': 0}),
('sigmoid', 'mul_2', {'in': 1, 'out': 0}),
('mul_2', 'result', {'in': 0, 'out': 0})], {})
graph_ref = graph.copy()
graph.stage = 'front'
SwishWithSigmoidWithBeta().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
@@ -1,115 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.front.onnx.quantize_dequantize_linear import QuantizeDequantizeLinear
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph
# quantize and dequantize share tensors with scale/zp
nodes0_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'quantize': {'kind': 'op', 'op': 'QuantizeLinear'},
'dequantize': {'kind': 'op', 'op': 'DequantizeLinear'},
'scale_param': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
# quantize and dequantize do not share tensors with scale/zp
nodes1_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'quantize': {'kind': 'op', 'op': 'QuantizeLinear'},
'dequantize': {'kind': 'op', 'op': 'DequantizeLinear'},
'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
nodes_ref_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'fq': {'kind': 'op', 'op': 'FakeQuantize'},
'min_param': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'max_param': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
class TestQuantizeDeQuantize2FakeQuantize(unittest.TestCase):
def test_quantizedequantize2fakequantize_0(self):
# testing the code path with uint8 zero-point
graph = build_graph(nodes1_attributes,
[('input', 'quantize'),
('quantize', 'dequantize'),
('scale_param_q', 'quantize'),
('zerop_param_q', 'quantize'),
('scale_param_dq', 'dequantize'),
('zerop_param_dq', 'dequantize'),
('dequantize', 'out'),
],
{'scale_param_q': {'shape': np.array([1]), 'value': np.float32(1.0 / 255)},
'zerop_param_q': {'shape': np.array([1]), 'value': np.uint8(0)},
'scale_param_dq': {'shape': np.array([1]), 'value': np.float32(1.0 / 255)},
'zerop_param_dq': {'shape': np.array([1]), 'value': np.uint8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'fq', {'in': 0}),
('min_param', 'fq', {'out': 0, 'in': 1}),
('min_param', 'fq', {'out': 0, 'in': 3}),
('max_param', 'fq', {'out': 0, 'in': 2}),
('max_param', 'fq', {'out': 0, 'in': 4}),
('fq', 'out'),
],
{'fq': {'levels': 256},
'min_param': {'value': np.float32(0.0)},
'max_param': {'value': np.float32(1.0)},
}, nodes_with_edges_only=True)
graph.stage = 'front'
tested_class = QuantizeDequantizeLinear()
tested_class.find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_quantizedequantize2fakequantize_1(self):
# testing the code path with int8 zero-point
graph = build_graph(nodes0_attributes,
[('input', 'quantize'),
('quantize', 'dequantize'),
('scale_param', 'quantize'),
('zerop_param', 'quantize'),
('scale_param', 'dequantize'),
('zerop_param', 'dequantize'),
('dequantize', 'out'),
],
{'scale_param': {'shape': np.array([1]), 'value': np.float32(1.0 / 255)},
'zerop_param': {'shape': np.array([1]), 'value': np.int8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'fq', {'in': 0}),
('min_param', 'fq', {'out': 0, 'in': 1}),
('min_param', 'fq', {'out': 0, 'in': 3}),
('max_param', 'fq', {'out': 0, 'in': 2}),
('max_param', 'fq', {'out': 0, 'in': 4}),
('fq', 'out'),
],
{'fq': {'levels': 256},
'min_param': {'value': np.float32(-128.0 / 255)},
'max_param': {'value': np.float32(127.0 / 255)},
}, nodes_with_edges_only=True)
graph.stage = 'front'
tested_class = QuantizeDequantizeLinear()
tested_class.find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
@@ -211,3 +211,30 @@ class TensorContentParsing(unittest.TestCase):
with self.assertLogs(log.getLogger(), level="ERROR") as cm:
result = tf_tensor_content(pb_tensor.dtype, shape, pb_tensor)
self.assertEqual([warning_message, warning_message], cm.output)
def test_empty_value(self):
pb_tensor = PB({
'dtype': 1,
'float_val': []
})
shape = int64_array([1, 1, 0])
tf_dtype = pb_tensor.dtype
ref = np.array([[[]]], dtype=np.float32)
res = tf_tensor_content(tf_dtype, shape, pb_tensor)
self.assertEqual(res.shape, ref.shape)
self.assertTrue(np.all(res == ref))
def test_scalar_value(self):
pb_tensor = PB({
'dtype': 3,
'int_val': 4
})
shape = int64_array([])
tf_dtype = pb_tensor.dtype
ref = np.array(4, dtype=np.int32)
res = tf_tensor_content(tf_dtype, shape, pb_tensor)
self.assertEqual(ref, res)
@@ -8,7 +8,7 @@ set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_OLD ${CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY}
set(CMAKE_PDB_OUTPUT_DIRECTORY_OLD ${CMAKE_PDB_OUTPUT_DIRECTORY})
set(PYTHON_VERSION python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
message("Python version=${PYTHON_VERSION}")
message(STATUS "Python version=${PYTHON_VERSION}")
if(WIN32)
set(PYTHON_BRIDGE_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/$<CONFIG>/python_api/${PYTHON_VERSION}/)
@@ -45,6 +45,7 @@ namespace ngraph
const std::unordered_set<std::string>& get_names() const;
void set_names(const std::unordered_set<std::string>& names);
void add_names(const std::unordered_set<std::string>& names);
void set_tensor_type(const element::Type& element_type, const PartialShape& pshape);
void set_element_type(const element::Type& elemenet_type);
void set_partial_shape(const PartialShape& partial_shape);
+2 -2
View File
@@ -19,8 +19,8 @@ namespace ngraph
class NGRAPH_API Asinh : public util::UnaryElementwiseArithmetic
{
public:
static constexpr NodeTypeInfo type_info{"Asinh", 3};
const NodeTypeInfo& get_type_info() const override { return type_info; }
NGRAPH_RTTI_DECLARATION;
/// \brief Constructs an Asinh operation.
Asinh() = default;
/// \brief Constructs an Asinh operation.
+2 -2
View File
@@ -16,8 +16,8 @@ namespace ngraph
class NGRAPH_API Cosh : public util::UnaryElementwiseArithmetic
{
public:
static constexpr NodeTypeInfo type_info{"Cosh", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
NGRAPH_RTTI_DECLARATION;
/// \brief Constructs a hyperbolic cosine operation.
Cosh() = default;
/// \brief Constructs a hyperbolic cosine operation.
+1 -1
View File
@@ -12,7 +12,7 @@
namespace ngraph
{
//
// In various places, like ConstantFolding and DynElimination, it is
// In various places, like ConstantFolding, it is
// useful to transform DynSlice by converting it to a sequence of ops:
//
// Slice (to do the basic slicing)
@@ -13,7 +13,8 @@ namespace ngraph
{
namespace reference
{
template <typename T>
template <typename T,
typename std::enable_if<!std::is_integral<T>::value, bool>::type = true>
void asinh(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
@@ -21,6 +22,16 @@ namespace ngraph
out[i] = std::asinh(arg[i]);
}
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
void asinh(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
{
out[i] = std::roundl(std::asinh(arg[i]));
}
}
} // namespace reference
} // namespace runtime
} // namespace ngraph
@@ -13,7 +13,8 @@ namespace ngraph
{
namespace reference
{
template <typename T>
template <typename T,
typename std::enable_if<!std::is_integral<T>::value, bool>::type = true>
void cosh(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
@@ -21,6 +22,16 @@ namespace ngraph
out[i] = std::cosh(arg[i]);
}
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
void cosh(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
{
out[i] = std::roundl(std::cosh(arg[i]));
}
}
} // namespace reference
} // namespace runtime
} // namespace ngraph
+8
View File
@@ -123,6 +123,14 @@ void descriptor::Tensor::set_names(const std::unordered_set<std::string>& names)
m_names = names;
}
void descriptor::Tensor::add_names(const std::unordered_set<std::string>& names)
{
for (const auto& name : names)
{
m_names.insert(name);
}
}
ostream& operator<<(ostream& out, const descriptor::Tensor& tensor)
{
std::string names;
+10 -4
View File
@@ -167,11 +167,9 @@ void ngraph::replace_node(std::shared_ptr<Node> target,
// Change I's connected upstream output to O_rep
for (size_t i = 0; i < target->get_output_size(); i++)
{
for (auto& input : target->output(i).get_target_inputs())
{
input.replace_source_output(replacement->output(output_order[i]));
}
target->output(i).replace(replacement->output(output_order[i]));
}
replacement->add_node_control_dependents(target);
replacement->add_node_control_dependencies(target);
target->clear_control_dependents();
@@ -912,7 +910,15 @@ bool ngraph::replace_output_update_name(Output<Node> output, const Output<Node>&
replacement.get_tensor().set_name(output.get_node()->get_friendly_name());
NGRAPH_SUPPRESS_DEPRECATED_END
}
// Save replacement tensor names before replacement as they will be
// overrided by the output tensor names
auto output_names = replacement.get_tensor_ptr()->get_names();
output.replace(replacement);
// Restore back original replacement tensor names
replacement.get_tensor().add_names(output_names);
copy_runtime_info({replacement.get_node_shared_ptr(), output.get_node_shared_ptr()},
replacement.get_node_shared_ptr());
return true;
+1
View File
@@ -76,6 +76,7 @@ namespace ngraph
{
input.replace_source_output(replacement);
}
replacement.get_tensor_ptr()->set_names(get_tensor_ptr()->get_names());
}
using RTMap = std::map<std::string, std::shared_ptr<Variant>>;
+13 -11
View File
@@ -7,6 +7,7 @@
#include "itt.hpp"
#include "ngraph/op/asinh.hpp"
#include "ngraph/op/util/elementwise_args.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/runtime/reference/asinh.hpp"
#include "ngraph/type/element_type.hpp"
@@ -14,7 +15,7 @@
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::v3::Asinh::type_info;
NGRAPH_RTTI_DEFINITION(op::v3::Asinh, "Asinh", 3, util::UnaryElementwiseArithmetic);
op::v3::Asinh::Asinh(const Output<Node>& arg)
: UnaryElementwiseArithmetic(arg)
@@ -32,25 +33,26 @@ shared_ptr<Node> op::v3::Asinh::clone_with_new_inputs(const OutputVector& new_ar
namespace asinhop
{
template <element::Type_t ET>
bool evaluate(const HostTensorPtr& arg0, const HostTensorPtr& out)
inline bool evaluate(const HostTensorPtr& arg0, const HostTensorPtr& out, const size_t count)
{
runtime::reference::asinh(
arg0->get_data_ptr<ET>(), out->get_data_ptr<ET>(), shape_size(arg0->get_shape()));
runtime::reference::asinh(arg0->get_data_ptr<ET>(), out->get_data_ptr<ET>(), count);
return true;
}
bool evaluate_asinh(const HostTensorPtr& arg0, const HostTensorPtr& out)
{
bool rc = true;
size_t count = shape_size(arg0->get_shape());
out->set_unary(arg0);
switch (arg0->get_element_type())
{
NGRAPH_TYPE_CASE(evaluate_asinh, i32, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, i64, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, u32, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, u64, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, f16, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, f32, arg0, out);
NGRAPH_TYPE_CASE(evaluate_asinh, i32, arg0, out, count);
NGRAPH_TYPE_CASE(evaluate_asinh, i64, arg0, out, count);
NGRAPH_TYPE_CASE(evaluate_asinh, u32, arg0, out, count);
NGRAPH_TYPE_CASE(evaluate_asinh, u64, arg0, out, count);
NGRAPH_TYPE_CASE(evaluate_asinh, f16, arg0, out, count);
NGRAPH_TYPE_CASE(evaluate_asinh, f32, arg0, out, count);
default: rc = false; break;
}
return rc;
@@ -65,7 +67,7 @@ bool op::v3::Asinh::evaluate(const HostTensorVector& outputs, const HostTensorVe
bool op::v3::Asinh::has_evaluate() const
{
NGRAPH_OP_SCOPE(v1_Asinh_has_evaluate);
NGRAPH_OP_SCOPE(v3_Asinh_has_evaluate);
switch (get_input_element_type(0))
{
case ngraph::element::i32:
+4 -5
View File
@@ -88,8 +88,8 @@ void op::v1::BatchToSpace::validate_and_infer_types()
if (data_rank.is_static())
{
NODE_VALIDATION_CHECK(this,
(data_rank.get_length() >= 4),
"data input must have rank greater than or equal to 4. Got: ",
(data_rank.get_length() >= 2),
"data input must have rank greater or equal than 2. Got: ",
data_rank.get_length());
if (inputs_same_ps.is_static())
@@ -197,7 +197,7 @@ namespace
}
auto data_shape = data->get_shape();
auto data_rank = data_shape.size();
if (!(data_rank == 4 || data_rank == 5))
if (data_rank < 2)
{
return false;
}
@@ -346,7 +346,6 @@ bool ngraph::op::v1::BatchToSpace::evaluate(const HostTensorVector& outputs,
bool ngraph::op::v1::BatchToSpace::has_evaluate() const
{
NGRAPH_OP_SCOPE(v1_BatchToSpace_has_evaluate);
return !get_input_partial_shape(0).is_dynamic() &&
(get_input_shape(0).size() == 4 || get_input_shape(0).size() == 5) &&
return !get_input_partial_shape(0).is_dynamic() && get_input_shape(0).size() >= 2 &&
get_input_shape(0).size() <= shape_size(get_input_shape(1));
}
+4 -3
View File
@@ -5,16 +5,16 @@
#include "itt.hpp"
#include "ngraph/op/cosh.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/sinh.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/runtime/reference/cosh.hpp"
#include "ngraph/validation_util.hpp"
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::Cosh::type_info;
NGRAPH_RTTI_DEFINITION(op::v0::Cosh, "Cosh", 0, util::UnaryElementwiseArithmetic);
op::Cosh::Cosh(const Output<Node>& arg)
: UnaryElementwiseArithmetic(arg)
@@ -68,6 +68,7 @@ namespace coshop
bool op::Cosh::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const
{
NGRAPH_OP_SCOPE(v0_Cosh_evaluate);
NGRAPH_CHECK(validate_host_tensor_vector(outputs, 1) && validate_host_tensor_vector(inputs, 1));
return coshop::evaluate_cosh(inputs[0], outputs[0], shape_size(get_output_shape(0)));
}
+3 -1
View File
@@ -57,11 +57,13 @@ void op::util::ScatterNDBase::validate_and_infer_types()
NODE_VALIDATION_CHECK(this,
inputs_rank.is_dynamic() || indices_rank.is_dynamic() ||
indices_shape[indices_rank.get_length() - 1].is_dynamic() ||
indices_shape[indices_rank.get_length() - 1].get_length() <=
inputs_rank.get_length(),
"Last dimension of indices can be at most the rank of inputs");
if (inputs_rank.is_static() && indices_rank.is_static() && updates_rank.is_static())
if (inputs_rank.is_static() && indices_rank.is_static() && updates_rank.is_static() &&
indices_shape[indices_rank.get_length() - 1].is_static())
{
auto expected_updates_rank = indices_rank.get_length() + inputs_rank.get_length() -
indices_shape[indices_rank.get_length() - 1].get_length() - 1;
-5
View File
@@ -3,9 +3,6 @@
#
if(NOT WIN32)
message(${CMAKE_SOURCE_DIR}/thirdparty/cmake_static_protobuf)
message(BINARY ${CMAKE_CURRENT_BINARY_DIR})
# There seems no suitable other way to identify exact output binary name for libprotobuf
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
# Use 'protobufd' directly as it is done in the same way in protobuf cmake files
@@ -15,8 +12,6 @@ if(NOT WIN32)
set(PROTOBUF_STATIC_LIB_OUTPUT ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_STATIC_LIBRARY_PREFIX}protobuf${CMAKE_STATIC_LIBRARY_SUFFIX})
endif()
message("Static protobuf lib: ${PROTOBUF_STATIC_LIB_OUTPUT}")
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libprotobuf_static)
add_custom_command(
OUTPUT
@@ -29,8 +29,6 @@ else()
set(PDPD_PROTOC_EXECUTABLE $<TARGET_FILE:protoc>)
endif()
message("PDPD_PROTOC_EXECUTABLE is [${PDPD_PROTOC_EXECUTABLE}]")
foreach(INFILE ${proto_files})
get_filename_component(FILE_DIR ${INFILE} DIRECTORY)
get_filename_component(FILE_WE ${INFILE} NAME_WE)
+1 -1
View File
@@ -19,7 +19,7 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/pybind11 EXCLUDE_FROM_ALL)
# PYTHON_VERSION_MAJOR and PYTHON_VERSION_MINOR are defined inside pybind11
set(PYTHON_VERSION python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
message("Python version=${PYTHON_VERSION}")
message(STATUS "Python version=${PYTHON_VERSION}")
set(LIBRARY_OUTPUT_DIRECTORY_BIN ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
if(OpenVINO_SOURCE_DIR)
+4 -3
View File
@@ -75,13 +75,10 @@ set(SRC
op_eval/strided_slice.cpp
op_eval/transpose.cpp
op_eval/variadic_split.cpp
op_is.cpp
opset1.cpp
partial_shape.cpp
pass_config.cpp
pass_liveness.cpp
pass_manager.cpp
pass_shape_relevance.cpp
pattern.cpp
provenance.cpp
replace_node.cpp
@@ -95,6 +92,7 @@ set(SRC
type_prop/adaptive_avg_pool.cpp
type_prop/adaptive_max_pool.cpp
type_prop/asin.cpp
type_prop/asinh.cpp
type_prop/assign.cpp
type_prop/atan.cpp
type_prop/avg_pool.cpp
@@ -112,6 +110,7 @@ set(SRC
type_prop/convolution.cpp
type_prop/convolution_backprop_data.cpp
type_prop/cos.cpp
type_prop/cosh.cpp
type_prop/ctc_greedy_decoder.cpp
type_prop/ctc_greedy_decoder_seq_len.cpp
type_prop/ctc_loss.cpp
@@ -231,6 +230,7 @@ set(SRC
visitors/value_map.cpp
visitors/op/adaptive_avg_pool.cpp
visitors/op/adaptive_max_pool.cpp
visitors/op/asinh.cpp
visitors/op/atan.cpp
visitors/op/batch_norm.cpp
visitors/op/batch_to_space.cpp
@@ -241,6 +241,7 @@ set(SRC
visitors/op/convert.cpp
visitors/op/convolution_backprop.cpp
visitors/op/cos.cpp
visitors/op/cosh.cpp
visitors/op/cum_sum.cpp
visitors/op/deformable_convolution.cpp
visitors/op/deformable_psroi_pooling.cpp
+15
View File
@@ -49,3 +49,18 @@ NGRAPH_TEST(${BACKEND_NAME}, asinh)
test_case.add_expected_output<float>(shape, expected);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, asinh_i32)
{
Shape shape{11};
auto A = make_shared<op::Parameter>(element::i32, shape);
auto f = make_shared<Function>(make_shared<op::Asinh>(A), ParameterVector{A});
vector<int> input{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
vector<int> expected{-2, -2, -2, -1, -1, 0, 1, 1, 2, 2, 2};
auto test_case = test::TestCase<TestEngine>(f);
test_case.add_input<int>(input);
test_case.add_expected_output<int>(shape, expected);
test_case.run();
}
+21
View File
@@ -79,6 +79,27 @@ NGRAPH_TEST_P(${BACKEND_NAME}, BatchToSpaceTestFloat, BatchToSpaceTestFloatCases
BatchToSpaceTestExecute(GetParam());
}
const test::NDArray<float, 2> input_with_shape_4x3(
{{1.0f, 2.0f, 3.0f},
{4.0f, 5.0f, 6.0f},
{7.0f, 8.0f, 9.0f},
{10.0f, 11.0f, 12.0f}});
const test::NDArray<int64_t, 1> zero_crops_2d({0, 0});
NGRAPH_INSTANTIATE_TEST_SUITE_P(
${BACKEND_NAME},
batch_to_space_2d_without_crops,
BatchToSpaceTestFloat,
testing::Values(
BatchToSpaceParams<float>{input_with_shape_4x3,
test::NDArray<int64_t, 1>({1, 2}),
zero_crops_2d,
zero_crops_2d,
test::NDArray<float, 2>(
{{1.0f, 7.0f, 2.0f, 8.0f, 3.0f, 9.0f},
{4.0f, 10.0f, 5.0f, 11.0f, 6.0f, 12.0f}})}));
const test::NDArray<float, 4> input_with_shape_4x1x1x3(
{{{{1.0f, 2.0f, 3.0f}}},
{{{4.0f, 5.0f, 6.0f}}},
+14 -18
View File
@@ -2,23 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstdlib>
#include <random>
#include <string>
// clang-format off
#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS
#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS
#endif
#ifdef ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS
#define DEFAULT_DOUBLE_TOLERANCE_BITS ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS
#endif
// clang-format on
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "util/engine/test_engines.hpp"
@@ -31,7 +14,7 @@ using namespace ngraph;
static string s_manifest = "${MANIFEST}";
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
NGRAPH_TEST(${BACKEND_NAME}, cosh)
NGRAPH_TEST(${BACKEND_NAME}, cosh_float)
{
Shape shape{6};
auto A = make_shared<op::Parameter>(element::f32, shape);
@@ -49,3 +32,16 @@ NGRAPH_TEST(${BACKEND_NAME}, cosh)
test_case.add_expected_output<float>(shape, expected);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, cosh_int)
{
Shape shape{5};
auto A = make_shared<op::Parameter>(element::i32, shape);
auto f = make_shared<Function>(make_shared<op::Cosh>(A), ParameterVector{A});
auto test_case = test::TestCase<TestEngine>(f);
test_case.add_input<int32_t>({1, 5, 2, 3, 3});
test_case.add_expected_output<int32_t>(shape,
{2, 74, 4, 10, 10});
test_case.run();
}
-142
View File
@@ -1,142 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/pass/constant_folding.hpp"
#include "ngraph/pass/dyn_elimination.hpp"
#include "ngraph/pass/manager.hpp"
#include "pass/opset0_downgrade.hpp"
#include "util/all_close_f.hpp"
#include "util/test_tools.hpp"
using namespace ngraph;
using namespace std;
TEST(dyn_elimination, transpose)
{
Shape shape_in{2, 4, 6, 8};
auto param = make_shared<op::Parameter>(element::boolean, shape_in);
auto constant_perm =
make_shared<op::Constant>(element::i64, Shape{4}, vector<int64_t>{2, 3, 1, 0});
auto transpose = make_shared<op::Transpose>(param, constant_perm);
auto f = make_shared<Function>(transpose, ParameterVector{param});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Transpose>(f), 0);
ASSERT_EQ(count_ops_of_type<op::v1::Reshape>(f), 1);
auto new_reshape =
as_type_ptr<op::v1::Reshape>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
ASSERT_TRUE(new_reshape);
ASSERT_EQ(new_reshape->get_input_order(), (AxisVector{2, 3, 1, 0}));
ASSERT_EQ(new_reshape->get_output_shape(0), (Shape{6, 8, 4, 2}));
ASSERT_EQ(new_reshape->get_output_element_type(0), element::boolean);
}
// For now, we can't handle the case where the input has dynamic shapes,
// because the classic Reshape op demands a Shape. Probably won't be able to
// deal with this until/unless we make a "StaticTranspose". Just make sure
// we don't crash or mangle the graph.
TEST(dyn_elimination, transpose_dyn_shape)
{
PartialShape shape_in{2, 4, Dimension::dynamic(), 8};
auto param = make_shared<op::Parameter>(element::boolean, shape_in);
auto constant_perm =
make_shared<op::Constant>(element::i64, Shape{4}, vector<int64_t>{2, 3, 1, 0});
auto transpose = make_shared<op::Transpose>(param, constant_perm);
auto f = make_shared<Function>(transpose, ParameterVector{param});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Transpose>(f), 1);
ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
auto new_transpose =
as_type_ptr<op::Transpose>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
ASSERT_TRUE(new_transpose);
ASSERT_EQ(new_transpose->get_output_element_type(0), element::boolean);
ASSERT_TRUE(new_transpose->get_output_partial_shape(0).relaxes(
PartialShape{Dimension::dynamic(), 8, 4, 2}));
}
TEST(dyn_elimination, range)
{
auto constant_start = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{0});
auto constant_stop = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{5});
auto constant_step = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{2});
auto range = make_shared<op::Range>(constant_start, constant_stop, constant_step);
ASSERT_EQ(range->get_element_type(), element::i64);
ASSERT_EQ(range->get_shape(), (Shape{3}));
auto f = make_shared<Function>(range, ParameterVector{});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Range>(f), 0);
ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
auto replacement =
as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
ASSERT_NE(replacement, nullptr);
ASSERT_EQ(replacement->get_element_type(), element::i64);
ASSERT_EQ(replacement->get_shape(), (Shape{3}));
auto vals = replacement->get_vector<int64_t>();
ASSERT_EQ(vals, (vector<int64_t>{0, 2, 4}));
}
TEST(dyn_elimination, range_f64)
{
auto constant_start = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{-0.5});
auto constant_stop = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{2});
auto constant_step = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{0.25});
auto range = make_shared<op::Range>(constant_start, constant_stop, constant_step);
ASSERT_EQ(range->get_element_type(), element::f64);
ASSERT_EQ(range->get_shape(), (Shape{10}));
auto f = make_shared<Function>(range, ParameterVector{});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Range>(f), 0);
ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
auto replacement =
as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
ASSERT_NE(replacement, nullptr);
ASSERT_EQ(replacement->get_element_type(), element::f64);
ASSERT_EQ(replacement->get_shape(), (Shape{10}));
auto vals = replacement->get_vector<double>();
ASSERT_TRUE(test::all_close_f(
vals, vector<double>{-0.5, -0.25, 0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75}));
}
-577
View File
@@ -1,577 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/op/util/op_types.hpp"
#include "ngraph/validation_util.hpp"
#include "op/convolution.hpp"
#include "op/group_conv.hpp"
#include "util/test_tools.hpp"
using namespace ngraph;
NGRAPH_SUPPRESS_DEPRECATED_START
namespace
{
void op_is_Abs()
{
op::Abs node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Acos()
{
op::Acos node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Asin()
{
op::Asin node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Atan()
{
op::Atan node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_AvgPool()
{
op::AvgPool node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_BatchNormInference()
{
op::v0::BatchNormInference node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Broadcast()
{
op::v1::Broadcast node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Ceiling()
{
op::Ceiling node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Clamp()
{
op::Clamp node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Concat()
{
op::Concat node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Constant()
{
op::Constant node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Convert()
{
op::Convert node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Convolution()
{
op::v0::Convolution node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_ConvolutionBackpropData()
{
op::v0::ConvolutionBackpropData node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Cos()
{
op::Cos node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Cosh()
{
op::Cosh node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_CumSum()
{
op::CumSum node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_DepthToSpace()
{
op::DepthToSpace node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Elu()
{
op::Elu node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Erf()
{
op::Erf node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Exp()
{
op::Exp node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_FakeQuantize()
{
op::FakeQuantize node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Floor()
{
op::Floor node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_GRN()
{
op::GRN node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Gather()
{
op::v1::Gather node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Gelu()
{
op::Gelu node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_GroupConvolution()
{
op::v0::GroupConvolution node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_GroupConvolutionBackpropData()
{
op::v0::GroupConvolutionBackpropData node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_HardSigmoid()
{
op::HardSigmoid node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Interpolate()
{
op::v0::Interpolate node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Log()
{
op::Log node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_LRN()
{
op::LRN node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_LSTMSequence()
{
op::v0::LSTMSequence node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_MatMul()
{
op::MatMul node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_NormalizeL2()
{
op::v0::NormalizeL2 node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_MVN()
{
op::MVN node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Negative()
{
op::Negative node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Parameter()
{
op::Parameter node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_PRelu()
{
op::PRelu node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_PriorBox()
{
op::PriorBox node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Range()
{
op::Range node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Relu()
{
op::Relu node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Result()
{
op::Result node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_ReverseSequence()
{
op::ReverseSequence node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Selu()
{
op::Selu node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_ShapeOf()
{
op::ShapeOf node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_ShuffleChannels()
{
op::ShuffleChannels node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Sigmoid()
{
op::Sigmoid node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Sign()
{
op::Sign node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Sin()
{
op::Sin node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Sinh()
{
op::Sinh node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_SpaceToDepth()
{
op::SpaceToDepth node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Sqrt()
{
op::Sqrt node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_SquaredDifference()
{
op::SquaredDifference node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_TRUE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Squeeze()
{
op::Squeeze node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Tan()
{
op::Tan node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Tanh()
{
op::Tanh node;
EXPECT_TRUE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_TensorIterator()
{
op::TensorIterator node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Tile()
{
op::v0::Tile node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Unsqueeze()
{
op::v0::Unsqueeze node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_FALSE(op::is_binary_elementwise_logical(&node));
}
void op_is_Xor()
{
op::Xor node;
EXPECT_FALSE(op::is_unary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_arithmetic(&node));
EXPECT_FALSE(op::is_binary_elementwise_comparison(&node));
EXPECT_TRUE(op::is_binary_elementwise_logical(&node));
}
} // namespace
TEST(op_is, check)
{
NGRAPH_SUPPRESS_DEPRECATED_START
#define NGRAPH_OP(a, b) op_is_##a();
#include "opset0_tbl.hpp"
#undef NGRAPH_OP
NGRAPH_SUPPRESS_DEPRECATED_END
}
-49
View File
@@ -1,49 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "ngraph/log.hpp"
#include "ngraph/ngraph.hpp"
#include "ngraph/pass/manager.hpp"
#include "ngraph/pass/visualize_tree.hpp"
#include "pass/liveness.hpp"
#include "util/test_tools.hpp"
using namespace std;
using namespace ngraph;
namespace ng = ngraph;
TEST(liveness, constant)
{
Shape shape{1};
auto c = op::Constant::create(element::i32, shape, {5});
auto f = make_shared<Function>(make_shared<op::Negative>(c), ParameterVector{});
pass::Manager pass_manager;
pass_manager.register_pass<pass::Liveness>();
pass_manager.run_passes(f);
auto tmp = f->get_ordered_ops();
vector<shared_ptr<Node>> sorted{tmp.begin(), tmp.end()};
ASSERT_EQ(3, sorted.size());
EXPECT_EQ(0, sorted[0]->liveness_new_list.size());
EXPECT_EQ(0, sorted[0]->liveness_free_list.size());
// op::Negative is live on output to op::Result
// op::Negative is new
EXPECT_EQ(1, sorted[1]->liveness_new_list.size());
EXPECT_EQ(0, sorted[1]->liveness_free_list.size());
// op::Negative is live on input to op::Result
EXPECT_EQ(0, sorted[2]->liveness_new_list.size());
// op::Negative is freed
EXPECT_EQ(1, sorted[2]->liveness_free_list.size());
}
-171
View File
@@ -1,171 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/pass/manager.hpp"
#include "pass/shape_relevance.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace ngraph;
using namespace std;
TEST(shape_relevance, simple)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto param1 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto x = make_shared<op::v1::Add>(param0, param1);
auto f = make_shared<Function>(x, ParameterVector{param0, param1});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
ASSERT_FALSE(param1->is_relevant_to_shapes());
}
TEST(shape_relevance, param_direct)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto param1 = make_shared<op::Parameter>(element::i64, Shape{4});
auto x = make_shared<op::v1::Reshape>(param0, param1, true);
auto f = make_shared<Function>(x, ParameterVector{param0, param1});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
ASSERT_TRUE(param1->is_relevant_to_shapes());
}
TEST(shape_relevance, param_indirect)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto param1 = make_shared<op::Parameter>(element::i64, Shape{4});
auto param2 = make_shared<op::Parameter>(element::i64, Shape{2});
auto c = make_shared<op::Concat>(NodeVector{param1, param2}, 0);
auto x = make_shared<op::v1::Reshape>(param0, c, true);
auto f = make_shared<Function>(x, ParameterVector{param0, param1, param2});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
ASSERT_TRUE(param1->is_relevant_to_shapes());
ASSERT_TRUE(param2->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_direct_v0)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto x = make_shared<op::v1::Reshape>(param0, make_shared<op::v0::ShapeOf>(param0), true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_direct_v3)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto x = make_shared<op::v1::Reshape>(param0, make_shared<op::v3::ShapeOf>(param0), true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_direct_i32_v3)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto x = make_shared<op::v1::Reshape>(
param0, make_shared<op::v3::ShapeOf>(param0, element::i32), true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_indirect_v0)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto s = make_shared<op::v0::ShapeOf>(param0);
auto r = make_shared<op::v1::Reverse>(
s, op::Constant::create(element::i64, {1}, {0}), op::v1::Reverse::Mode::INDEX);
auto x = make_shared<op::v1::Reshape>(param0, r, true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_indirect_v3)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto s = make_shared<op::v3::ShapeOf>(param0);
auto r = make_shared<op::v1::Reverse>(
s, op::Constant::create(element::i64, {1}, {0}), op::v1::Reverse::Mode::INDEX);
auto x = make_shared<op::v1::Reshape>(param0, r, true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
TEST(shape_relevance, param_shape_of_indirect_i32_v3)
{
auto param0 = make_shared<op::Parameter>(element::f32, Shape{4, 6});
auto s = make_shared<op::v3::ShapeOf>(param0, element::i32);
auto r = make_shared<op::v1::Reverse>(
s, op::Constant::create(element::i64, {1}, {0}), op::v1::Reverse::Mode::INDEX);
auto x = make_shared<op::v1::Reshape>(param0, r, true);
auto f = make_shared<Function>(x, ParameterVector{param0});
pass::Manager manager;
manager.register_pass<pass::ShapeRelevance>();
manager.run_passes(f);
ASSERT_FALSE(param0->is_relevant_to_shapes());
}
-56
View File
@@ -15,7 +15,6 @@
#include "ngraph/ngraph.hpp"
#include "ngraph/pass/manager.hpp"
#include "ngraph/provenance.hpp"
#include "pass/fused_op_decomposition.hpp"
#include "util/provenance_enabler.hpp"
using namespace std;
@@ -380,61 +379,6 @@ TEST(provenance, builder)
}
}
TEST(provenance, fused_copy_origin_tags)
{
test::ProvenanceEnabler provenance_enabler;
auto p1 = make_shared<op::Parameter>(element::f32, PartialShape{2, 3, 4});
p1->add_provenance_tag("P1");
auto g = make_shared<op::MVN>(p1);
g->add_provenance_tag("G");
auto r = make_shared<op::Result>(g);
auto f = make_shared<Function>(ResultVector{r}, ParameterVector{p1});
pass::Manager manager;
manager.register_pass<pass::FusedOpDecomposition>();
manager.run_passes(f);
traverse_nodes(f, [&](const std::shared_ptr<Node>& node) {
auto tags = node->get_provenance_tags();
if (node == p1)
{
EXPECT_EQ(tags.size(), 1);
EXPECT_TRUE(tags.find("P1") != tags.end());
}
else if (node == r)
{
}
else
{
EXPECT_TRUE(tags.find("G") != tags.end());
EXPECT_TRUE(tags.find("<Decomposed from MVN>") != tags.end());
}
});
}
TEST(provenance, fused_decomposition_tag)
{
test::ProvenanceEnabler provenance_enabler;
auto p1 = make_shared<op::Parameter>(element::f32, PartialShape{2, 3, 4});
auto fused_op = make_shared<op::MVN>(p1);
auto result = make_shared<op::Result>(fused_op);
auto f = make_shared<Function>(ResultVector{result}, ParameterVector{p1});
pass::Manager manager;
manager.register_pass<pass::FusedOpDecomposition>();
manager.run_passes(f);
const auto tag = "<Decomposed from MVN>";
auto tag_check = [&tag](std::shared_ptr<ngraph::Node> node) {
auto tags = node->get_provenance_tags();
EXPECT_TRUE(tags.find(tag) != tags.end());
};
const auto decomposed_op = f->get_result()->get_input_node_shared_ptr(0);
traverse_nodes(as_node_vector(decomposed_op->outputs()), tag_check, {p1});
}
TEST(provenance, empty_group)
{
auto p1 = make_shared<op::Parameter>(element::i32, PartialShape{2, 3, 4});
+60
View File
@@ -108,3 +108,63 @@ TEST(replace_node, replace_nodes)
ASSERT_EQ(z_replacement->get_input_node_shared_ptr(0), x_replacement);
ASSERT_EQ(z_replacement->get_input_node_shared_ptr(1), mul);
}
TEST(replace_node, simple_node_replacement)
{
auto param = std::make_shared<op::Parameter>(element::i64, Shape{1, 64});
param->output(0).get_tensor().set_names({"a", "b"});
auto relu = std::make_shared<op::Relu>(param);
relu->output(0).get_tensor().set_names({"c", "d"});
auto new_relu = std::make_shared<op::Relu>(param);
new_relu->output(0).get_tensor().set_names({"f"});
replace_node(relu, new_relu);
ASSERT_EQ(new_relu->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"c", "d"}));
}
TEST(replace_node, node_elimination)
{
auto param = std::make_shared<op::Parameter>(element::i64, Shape{1, 64});
param->output(0).get_tensor().set_names({"a", "b"});
auto relu1 = std::make_shared<op::Relu>(param);
relu1->output(0).get_tensor().set_names({"c", "d"});
auto relu2 = std::make_shared<op::Relu>(relu1);
relu2->output(0).get_tensor().set_names({"e", "f"});
ASSERT_TRUE(replace_output_update_name(relu2->output(0), relu2->input_value(0)));
ASSERT_EQ(relu1->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"c", "d", "e", "f"}));
ASSERT_EQ(param->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"a", "b"}));
}
TEST(replace_node, output_replacement)
{
auto param = std::make_shared<op::Parameter>(element::i64, Shape{1, 64});
param->output(0).get_tensor().set_names({"a", "b"});
auto relu = std::make_shared<op::Relu>(param);
relu->output(0).get_tensor().set_names({"c", "d"});
auto new_relu = std::make_shared<op::Relu>(param);
new_relu->output(0).get_tensor().set_names({"f"});
relu->output(0).replace(new_relu->output(0));
ASSERT_EQ(new_relu->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"c", "d"}));
}
TEST(replace_node, source_replacement)
{
auto param = std::make_shared<op::Parameter>(element::i64, Shape{1, 64});
param->output(0).get_tensor().set_names({"a", "b"});
auto param1 = std::make_shared<op::Parameter>(element::i64, Shape{1, 64});
param1->output(0).get_tensor().set_names({"c", "d"});
auto relu = std::make_shared<op::Relu>(param);
relu->input(0).replace_source_output(param1->output(0));
ASSERT_EQ(param->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"a", "b"}));
ASSERT_EQ(param1->output(0).get_tensor().get_names(), std::unordered_set<std::string>({"c", "d"}));
}
-18
View File
@@ -14,26 +14,8 @@ set (SRC
performance_counter.hpp
dynamic/dynamic_backend.cpp
dynamic/dynamic_backend.hpp
op/avg_pool.cpp
op/avg_pool.hpp
op/convolution.cpp
op/convolution.hpp
op/group_conv.cpp
op/group_conv.hpp
pass/dyn_elimination.cpp
pass/dyn_elimination.hpp
pass/fused_op_decomposition.cpp
pass/fused_op_decomposition.hpp
pass/implicit_broadcast_elimination.cpp
pass/implicit_broadcast_elimination.hpp
pass/liveness.cpp
pass/liveness.hpp
pass/opset0_downgrade.cpp
pass/opset0_downgrade.hpp
pass/opset1_downgrade.cpp
pass/opset1_downgrade.hpp
pass/opset1_upgrade.cpp
pass/opset1_upgrade.hpp
pass/shape_relevance.cpp
pass/shape_relevance.hpp
)
@@ -15,8 +15,6 @@
#include "ngraph/specialize_function.hpp"
#include "ngraph/util.hpp"
#include "pass/dyn_elimination.hpp"
#include "pass/opset0_downgrade.hpp"
#include "pass/opset1_downgrade.hpp"
#include "pass/shape_relevance.hpp"
using namespace std;
@@ -239,10 +237,8 @@ bool runtime::dynamic::DynamicExecutable::call(
pass::Manager passes;
// Opset1Downgrade should be moved below DynElimination
// when ConstantFolding for v3 ops will be ready
passes.register_pass<pass::Opset1Downgrade>();
passes.register_pass<pass::ConstantFolding>();
passes.register_pass<pass::DynElimination>();
passes.register_pass<pass::Opset0Downgrade>(); // Converts dynamic v1 variants to v0 ops
passes.set_per_pass_validation(false);
// FIXME(amprocte): Vile, temporary hack: we need to do repeated rounds of
+4 -8
View File
@@ -8,7 +8,6 @@
#include "ngraph/pass/manager.hpp"
#include "ngraph/shape.hpp"
#include "ngraph/type/element_type.hpp"
#include "pass/opset1_upgrade.hpp"
using namespace std;
using namespace ngraph;
@@ -63,7 +62,7 @@ namespace
memcpy(blob_ptr, data, data_size * elem_type.size());
return blob;
}
}
} // namespace
namespace
{
@@ -78,21 +77,18 @@ namespace
ie_ops.insert(opset4.begin(), opset4.end());
auto& opset5 = get_opset5().get_type_info_set();
ie_ops.insert(opset5.begin(), opset5.end());
auto& opset6= get_opset6().get_type_info_set();
auto& opset6 = get_opset6().get_type_info_set();
ie_ops.insert(opset6.begin(), opset6.end());
auto& opset7= get_opset7().get_type_info_set();
auto& opset7 = get_opset7().get_type_info_set();
ie_ops.insert(opset7.begin(), opset7.end());
return ie_ops;
}
}
} // namespace
runtime::ie::IE_Executable::IE_Executable(shared_ptr<Function> func, string device)
: m_device{device}
{
static std::set<NodeTypeInfo> ie_ops = get_ie_ops();
pass::Manager passes;
passes.register_pass<pass::Opset1Upgrade>();
passes.run_passes(func);
for (const auto& node : func->get_ops())
{
@@ -21,7 +21,6 @@
#include "ngraph/runtime/reference/reorg_yolo.hpp"
#include "ngraph/runtime/reference/tensor_iterator.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "op/avg_pool.hpp"
namespace ngraph
{
-34
View File
@@ -1,34 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "atan2.hpp"
#include "ngraph/op/add.hpp"
#include "ngraph/op/divide.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/negative.hpp"
#include "ngraph/op/sqrt.hpp"
#include "ngraph/op/subtract.hpp"
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::v0::Atan2::type_info;
op::v0::Atan2::Atan2(const Output<Node>& y, const Output<Node>& x, const AutoBroadcastSpec& autob)
: BinaryElementwiseArithmetic(y, x, autob)
{
constructor_validate_and_infer_types();
}
shared_ptr<Node> op::v0::Atan2::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<Atan2>(new_args.at(0), new_args.at(1), this->get_autob());
}
bool op::v0::Atan2::visit_attributes(AttributeVisitor& visitor)
{
BinaryElementwiseArithmetic::visit_attributes(visitor);
return true;
}
-43
View File
@@ -1,43 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <memory>
#include "backend_visibility.hpp"
#include "ngraph/op/util/binary_elementwise_arithmetic.hpp"
namespace ngraph
{
namespace op
{
namespace v0
{
/// \brief Elementwise full arctan operation
class BACKEND_API Atan2 : public util::BinaryElementwiseArithmetic
{
public:
static constexpr NodeTypeInfo type_info{"Atan2", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
Atan2()
: util::BinaryElementwiseArithmetic(AutoBroadcastSpec::NONE)
{
}
/// \brief atan2(y,x) is the angle from the origin to the point (x,y) (note reversed
/// order).
///
/// \param y
/// \param x
Atan2(const Output<Node>& y,
const Output<Node>& x,
const AutoBroadcastSpec& autob = AutoBroadcastSpec());
std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
bool visit_attributes(AttributeVisitor& visitor) override;
};
}
}
}
-235
View File
@@ -1,235 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "avg_pool.hpp"
#include "ngraph/attribute_visitor.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/validation_util.hpp"
using namespace std;
using namespace ngraph;
// *** AvgPool OP SET 0 ***
constexpr NodeTypeInfo op::v0::AvgPool::type_info;
op::v0::AvgPool::AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation,
const PadType& pad_type,
bool ceil_mode)
: Op({arg})
, m_window_shape(window_shape)
, m_window_movement_strides(window_movement_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_include_padding_in_avg_computation(include_padding_in_avg_computation)
, m_pad_type(pad_type)
, m_ceil_mode(ceil_mode)
{
constructor_validate_and_infer_types();
}
op::v0::AvgPool::AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation,
const PadType& pad_type)
: AvgPool(arg,
window_shape,
window_movement_strides,
padding_below,
padding_above,
include_padding_in_avg_computation,
pad_type,
false)
{
}
op::v0::AvgPool::AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation)
: AvgPool(arg,
window_shape,
window_movement_strides,
padding_below,
padding_above,
include_padding_in_avg_computation,
PadType::EXPLICIT)
{
}
bool op::v0::AvgPool::visit_attributes(AttributeVisitor& visitor)
{
visitor.on_attribute("window_shape", m_window_shape);
visitor.on_attribute("window_movement_strides", m_window_movement_strides);
visitor.on_attribute("padding_below", m_padding_below);
visitor.on_attribute("padding_above", m_padding_above);
visitor.on_attribute("include_padding_in_avg_computation",
m_include_padding_in_avg_computation);
visitor.on_attribute("pad_type", m_pad_type);
visitor.on_attribute("ceil_mode", m_ceil_mode);
return true;
}
void op::v0::AvgPool::validate_and_infer_types()
{
if (0 == m_window_movement_strides.size())
{
m_window_movement_strides = Strides(m_window_shape.size(), 1);
}
if (0 == m_padding_below.size())
{
m_padding_below = Shape(m_window_shape.size(), 0);
}
if (0 == m_padding_above.size())
{
m_padding_above = Shape(m_window_shape.size(), 0);
}
const PartialShape& arg_shape = get_input_partial_shape(0);
if (m_pad_type == PadType::SAME_UPPER || m_pad_type == PadType::SAME_LOWER)
{
if (arg_shape.is_static())
{
CoordinateDiff padding_above, padding_below;
infer_auto_padding(arg_shape.to_shape(),
m_window_shape,
m_window_movement_strides,
Strides(m_window_shape.size(), 1), // No dilation
m_pad_type,
padding_above,
padding_below);
m_padding_above = Shape(padding_above.begin(), padding_above.end());
m_padding_below = Shape(padding_below.begin(), padding_below.end());
}
}
// infer_batched_forward_pooling wants CoordinateDiffs for these, while the pooling ops for
// now still take Shape (no negative padding).
CoordinateDiff padding_below(m_padding_below.begin(), m_padding_below.end());
CoordinateDiff padding_above(m_padding_above.begin(), m_padding_above.end());
set_output_type(0,
get_input_element_type(0),
infer_batched_pooling_forward(this,
arg_shape,
padding_below,
padding_above,
m_window_shape,
m_window_movement_strides,
m_include_padding_in_avg_computation,
m_ceil_mode));
}
op::v0::AvgPool::AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides)
: AvgPool(arg, window_shape, window_movement_strides, Shape(), Shape(), false)
{
}
op::v0::AvgPool::AvgPool(const Output<Node>& arg, const Shape& window_shape)
: AvgPool(arg, window_shape, Strides(), Shape(), Shape(), false)
{
}
const Shape& op::v0::AvgPool::get_window_shape() const
{
return m_window_shape;
}
void op::v0::AvgPool::set_window_shape(const Shape& window_shape)
{
m_window_shape = window_shape;
}
const Strides& op::v0::AvgPool::get_window_movement_strides() const
{
return m_window_movement_strides;
}
void op::v0::AvgPool::set_window_movement_strides(const Strides& window_movement_strides)
{
m_window_movement_strides = window_movement_strides;
}
const Shape& op::v0::AvgPool::get_padding_below() const
{
return m_padding_below;
}
void op::v0::AvgPool::set_padding_below(const Shape& padding_below)
{
m_padding_below = padding_below;
}
const Shape& op::v0::AvgPool::get_padding_above() const
{
return m_padding_above;
}
void op::v0::AvgPool::set_padding_above(const Shape& padding_above)
{
m_padding_above = padding_above;
}
bool op::v0::AvgPool::get_include_padding_in_avg_computation() const
{
return m_include_padding_in_avg_computation;
}
void op::v0::AvgPool::set_include_padding_in_avg_computation(
bool include_padding_in_avg_computation)
{
m_include_padding_in_avg_computation = include_padding_in_avg_computation;
}
const op::PadType& op::v0::AvgPool::get_pad_type() const
{
return m_pad_type;
}
void op::v0::AvgPool::set_pad_type(const op::PadType& pad_type)
{
m_pad_type = pad_type;
}
bool op::v0::AvgPool::get_ceil_mode() const
{
return m_ceil_mode;
}
void op::v0::AvgPool::set_ceil_mode(bool ceil_mode)
{
m_ceil_mode = ceil_mode;
}
shared_ptr<Node> op::v0::AvgPool::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v0::AvgPool>(new_args.at(0),
m_window_shape,
m_window_movement_strides,
m_padding_below,
m_padding_above,
m_include_padding_in_avg_computation,
m_pad_type,
m_ceil_mode);
}
shared_ptr<Node> op::v0::AvgPool::get_default_value() const
{
return Constant::create(get_element_type(), get_shape(), {0});
}
-164
View File
@@ -1,164 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/op/op.hpp"
#include "ngraph/op/util/attr_types.hpp"
namespace ngraph
{
namespace op
{
namespace v0
{
/// \brief Batched average pooling operation, with optional padding and window stride.
///
class BACKEND_API AvgPool : public Op
{
public:
static constexpr NodeTypeInfo type_info{"AvgPool", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched average pooling operation.
AvgPool() = default;
/// \brief Constructs a batched average pooling operation.
///
/// \param arg The output producing the input data batch tensor.<br>
/// `[d1, dn]`
/// \param window_shape The window shape.<br>
/// `[n]`
/// \param window_movement_strides The window movement strides.<br>
/// `[n]`
/// \param padding_below The below-padding shape.<br>
/// `[n]`
/// \param padding_above The above-padding shape.<br>
/// `[n]`
/// \param include_padding_in_avg_computation If true then averages include padding
/// elements, each treated as the number zero. If false, padding elements are
/// entirely ignored when computing averages. \param pad_type Padding type to use
/// for additional padded dimensions \param ceil_mode Whether to use ceiling while
/// computing output shape.
AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation,
const PadType& pad_type,
bool ceil_mode);
/// \brief Constructs a batched average pooling operation.
///
/// \param arg The output producing the input data batch tensor.<br>
/// `[d1, dn]`
/// \param window_shape The window shape.<br>
/// `[n]`
/// \param window_movement_strides The window movement strides.<br>
/// `[n]`
/// \param padding_below The below-padding shape.<br>
/// `[n]`
/// \param padding_above The above-padding shape.<br>
/// `[n]`
/// \param include_padding_in_avg_computation If true then averages include padding
/// elements, each treated as the number zero. If false, padding elements are
/// entirely ignored when computing averages. \param pad_type Padding type to use
/// for additional padded dimensions
AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation,
const PadType& pad_type);
/// \brief Constructs a batched average pooling operation.
///
/// \param arg The output producing the input data batch tensor.<br>
/// `[d1, dn]`
/// \param window_shape The window shape.<br>
/// `[n]`
/// \param window_movement_strides The window movement strides.<br>
/// `[n]`
/// \param padding_below The below-padding shape.<br>
/// `[n]`
/// \param padding_above The above-padding shape.<br>
/// `[n]`
/// \param include_padding_in_avg_computation If true then averages include padding
/// elements, each treated as the number zero. If false, padding elements are
/// entirely ignored when computing averages.
AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides,
const Shape& padding_below,
const Shape& padding_above,
bool include_padding_in_avg_computation = false);
/// \brief Constructs a batched, unpadded average pooling operation (i.e., all
/// padding shapes are set to 0).
///
/// \param arg The output producing the input data batch tensor.<br>
/// `[d1, ..., dn]`
/// \param window_shape The window shape.<br>
/// `[n]`
/// \param window_movement_strides The window movement strides.<br>
/// `[n]`
AvgPool(const Output<Node>& arg,
const Shape& window_shape,
const Strides& window_movement_strides);
/// \brief Constructs an unstrided batched convolution operation (i.e., all window
/// movement strides are 1 and all padding shapes are set to 0).
///
/// \param arg The output producing the input data batch tensor.<br>
/// `[d1, ..., dn]`
/// \param window_shape The window shape.<br>
/// `[n]`
AvgPool(const Output<Node>& arg, const Shape& window_shape);
bool visit_attributes(AttributeVisitor& visitor) override;
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
/// \return The window shape.
const Shape& get_window_shape() const;
void set_window_shape(const Shape& window_shape);
/// \return The window movement strides.
const Strides& get_window_movement_strides() const;
void set_window_movement_strides(const Strides& window_movement_strides);
/// \return The below-padding shape.
const Shape& get_padding_below() const;
void set_padding_below(const Shape& padding_below);
/// \return The above-padding shape.
const Shape& get_padding_above() const;
void set_padding_above(const Shape& padding_above);
bool get_include_padding_in_avg_computation() const;
void
set_include_padding_in_avg_computation(bool include_padding_in_avg_computation);
/// \return The pad type for pooling.
const PadType& get_pad_type() const;
void set_pad_type(const PadType& pad_type);
bool get_ceil_mode() const;
void set_ceil_mode(bool ceil_mode);
/// \return The default value for AvgPool.
NGRAPH_SUPPRESS_DEPRECATED_START
virtual std::shared_ptr<Node> get_default_value() const override;
NGRAPH_SUPPRESS_DEPRECATED_END
protected:
Shape m_window_shape;
Strides m_window_movement_strides;
Shape m_padding_below;
Shape m_padding_above;
bool m_include_padding_in_avg_computation{false};
PadType m_pad_type{PadType::EXPLICIT};
bool m_ceil_mode{false};
};
} // namespace v0
} // namespace op
} // namespace ngraph
-343
View File
@@ -1,343 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "convolution.hpp"
#include "ngraph/axis_vector.hpp"
#include "ngraph/coordinate_diff.hpp"
#include "ngraph/op/reshape.hpp"
#include "ngraph/util.hpp"
#include "ngraph/validation_util.hpp"
using namespace std;
using namespace ngraph;
// *** Convolution OP SET 0 ***
constexpr NodeTypeInfo op::v0::Convolution::type_info;
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type)
: Op({data_batch, filters})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_data_dilation_strides(data_dilation_strides)
, m_pad_type(pad_type)
{
constructor_validate_and_infer_types();
}
bool op::v0::Convolution::visit_attributes(AttributeVisitor& visitor)
{
visitor.on_attribute("window_movement_strides", m_window_movement_strides);
visitor.on_attribute("window_dilation_strides", m_window_dilation_strides);
visitor.on_attribute("data_dilation_strides", m_data_dilation_strides);
visitor.on_attribute("padding_below", m_padding_below);
visitor.on_attribute("padding_above", m_padding_above);
visitor.on_attribute("pad_type", m_pad_type);
return true;
}
void op::v0::Convolution::validate_and_infer_types()
{
const PartialShape& data_batch_shape = get_input_partial_shape(0);
element::Type data_batch_et = get_input_element_type(0);
const PartialShape& filters_shape = get_input_partial_shape(1);
element::Type filters_et = get_input_element_type(1);
if (m_data_dilation_strides.size() == 0)
{
m_data_dilation_strides = conv_default_strides(this, data_batch_shape, filters_shape);
}
if (m_window_movement_strides.size() == 0)
{
m_window_movement_strides = conv_default_strides(this, data_batch_shape, filters_shape);
}
if (m_window_dilation_strides.size() == 0)
{
m_window_dilation_strides = conv_default_strides(this, data_batch_shape, filters_shape);
}
if (m_padding_below.size() == 0)
{
m_padding_below = conv_default_padding(this, data_batch_shape, filters_shape);
}
if (m_padding_above.size() == 0)
{
m_padding_above = conv_default_padding(this, data_batch_shape, filters_shape);
}
if (m_pad_type == PadType::SAME_UPPER || m_pad_type == PadType::SAME_LOWER)
{
if (data_batch_shape.is_static() && filters_shape.is_static())
{
// TODO: data dilation
m_padding_below.clear();
m_padding_above.clear();
auto filter_shape = filters_shape.to_shape();
filter_shape.erase(filter_shape.begin(), filter_shape.begin() + 2); // Remove {O,I}
infer_auto_padding(data_batch_shape.to_shape(),
filter_shape,
m_window_movement_strides,
m_window_dilation_strides,
m_pad_type,
m_padding_above,
m_padding_below);
}
}
element::Type result_et;
PartialShape result_shape;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(result_et, data_batch_et, filters_et),
"Element types for data batch and filters do not match (data batch element type: ",
data_batch_et,
", filters element type: ",
filters_et,
").");
result_shape = infer_convolution_forward(this,
data_batch_shape,
m_data_dilation_strides,
m_padding_below,
m_padding_above,
filters_shape,
m_window_movement_strides,
m_window_dilation_strides);
set_output_type(0, result_et, result_shape);
}
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above)
: Convolution(data_batch,
filters,
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above,
Strides())
{
}
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides)
: Convolution(data_batch,
filters,
window_movement_strides,
window_dilation_strides,
CoordinateDiff(),
CoordinateDiff())
{
}
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides)
: Convolution(data_batch,
filters,
window_movement_strides,
Strides(),
CoordinateDiff(),
CoordinateDiff())
{
}
op::v0::Convolution::Convolution(const Output<Node>& data_batch, const Output<Node>& filters)
: Convolution(data_batch, filters, Strides(), Strides(), CoordinateDiff(), CoordinateDiff())
{
}
shared_ptr<Node> op::v0::Convolution::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v0::Convolution>(new_args.at(0),
new_args.at(1),
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides,
m_pad_type);
}
constexpr NodeTypeInfo op::v0::ConvolutionBackpropData::type_info;
shared_ptr<Node> op::v0::Convolution::get_default_value() const
{
return ngraph::make_constant_from_string("0", get_element_type(), get_shape());
}
op::v0::ConvolutionBackpropData::ConvolutionBackpropData(
const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward)
: Op({filters, output_delta})
, m_data_batch_shape(data_batch_shape)
, m_window_movement_strides_forward(window_movement_strides_forward)
, m_window_dilation_strides_forward(window_dilation_strides_forward)
, m_padding_below_forward(padding_below_forward)
, m_padding_above_forward(padding_above_forward)
, m_data_dilation_strides_forward(data_dilation_strides_forward)
{
constructor_validate_and_infer_types();
}
bool op::v0::ConvolutionBackpropData::visit_attributes(AttributeVisitor& visitor)
{
visitor.on_attribute("data_batch_shape", m_data_batch_shape);
visitor.on_attribute("window_movement_strides_forward", m_window_movement_strides_forward);
visitor.on_attribute("window_dilation_strides_forward", m_window_dilation_strides_forward);
visitor.on_attribute("padding_below_forward", m_padding_below_forward);
visitor.on_attribute("padding_above_forward", m_padding_above_forward);
visitor.on_attribute("data_dilation_strides_forward", m_data_dilation_strides_forward);
return true;
}
void op::v0::ConvolutionBackpropData::validate_and_infer_types()
{
// Backprop to data is itself convolution, with inputs/outputs/attributes transmogrified as
// follows.
//
// Forward Backward
// "N" axis for data batch 0 0
// "C" axis for data batch 1 1
// "Co" axis for filters 0 0
// "Ci" axis for filters 1 1
// "N" axis for output 0 0
// "C" axis for output 1 1
// Data batch x delta
// Data batch shape S_x S_o
// Filters f reverse(f) [on spatial axes]
// Filters shape S_f S_f
// Window movement strides q_x p_x
// Window dilation strides p_f p_f
// Padding below a_x (S_f - 1)p_f - a_x
// Padding above b_x (S_f - 1)p_f +
// + ((a_x + (S_x - 1)p_x + b_x - (S_f - 1)p_f)
// % q_x)
// - b_x
// Data dilation strides p_x q_x
// Output shape S_o S_x
//
// To _validate_, we simply need to check/infer the output shape of the forward convolution,
// then check to make sure that the incoming delta has the same shape as the forward output.
const PartialShape& filters_shape = get_input_partial_shape(0);
element::Type filters_et = get_input_element_type(0);
const PartialShape& delta_shape = get_input_partial_shape(1);
element::Type delta_et = get_input_element_type(1);
element::Type forward_result_et;
PartialShape forward_result_shape;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(forward_result_et, delta_et, filters_et),
"Element types for data batch and filters do not match (data batch element type: ",
delta_et,
", filters element type: ",
filters_et,
").");
forward_result_shape = infer_convolution_forward(this,
m_data_batch_shape,
m_data_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
filters_shape,
m_window_movement_strides_forward,
m_window_dilation_strides_forward);
NODE_VALIDATION_CHECK(this,
forward_result_shape.compatible(delta_shape),
"Inferred forward output shape (",
forward_result_shape,
") does not match shape of ",
"delta (",
delta_shape,
").");
set_output_type(0, forward_result_et, m_data_batch_shape);
}
shared_ptr<Node>
op::v0::ConvolutionBackpropData::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v0::ConvolutionBackpropData>(m_data_batch_shape,
new_args.at(0),
new_args.at(1),
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
}
CoordinateDiff op::v0::ConvolutionBackpropData::compute_backward_delta_out_pad_below() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_window_dilation_strides_forward();
auto& filter_shape = get_input_shape(0);
auto& in_pad_below = get_padding_below_forward();
size_t spatial_dim_count = static_cast<size_t>(in_shape.size()) - 2;
CoordinateDiff backward_delta_out_pad_below;
backward_delta_out_pad_below.resize(spatial_dim_count);
for (size_t i = 0; i < spatial_dim_count; i++)
{
backward_delta_out_pad_below[i] =
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] -
in_pad_below[i];
}
return backward_delta_out_pad_below;
}
CoordinateDiff op::v0::ConvolutionBackpropData::compute_backward_delta_out_pad_above() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_window_dilation_strides_forward();
auto& filter_shape = get_input_shape(0);
auto& in_pad_below = get_padding_below_forward();
auto& in_pad_above = get_padding_above_forward();
auto& in_dilation = get_data_dilation_strides_forward();
auto& stride = get_window_movement_strides_forward();
size_t spatial_dim_count = static_cast<size_t>(in_shape.size()) - 2;
CoordinateDiff backward_delta_out_pad_above;
backward_delta_out_pad_above.resize(spatial_dim_count);
for (size_t i = 0; i < spatial_dim_count; i++)
{
backward_delta_out_pad_above[i] =
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] +
((in_pad_below[i] + ((in_shape[i + 2]) - 1) * in_dilation[i] + in_pad_above[i] -
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i]) %
stride[i]) -
in_pad_above[i];
}
return backward_delta_out_pad_above;
}
-304
View File
@@ -1,304 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/coordinate_diff.hpp"
#include "ngraph/op/op.hpp"
#include "ngraph/op/util/attr_types.hpp"
namespace ngraph
{
namespace op
{
namespace v0
{
/// \brief Batched convolution operation, with optional window dilation and stride.
///
class BACKEND_API Convolution : public Op
{
public:
static constexpr NodeTypeInfo type_info{"Convolution", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched convolution operation.
Convolution() = default;
/// \brief Constructs a batched convolution operation.
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
/// \param data_dilation_strides The data dilation strides.<br>
/// `[f]`
/// \param pad_type The pad type for automatically computing padding sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type = PadType::EXPLICIT);
/// \brief Constructs a batched convolution operation with no data dilation (i.e.,
/// all
/// data dilation strides are 1).
/// ngraph/test/runtime/interpreter/unit_test.manifest
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above);
/// \brief Constructs a batched convolution operation with no padding or data
/// dilation
/// (i.e., padding above and below are 0 everywhere, and all data dilation
/// strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides);
/// \brief Constructs a batched convolution operation with no window dilation,
/// padding,
/// or data dilation (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides);
/// \brief Constructs a batched convolution operation with no window dilation or
/// movement stride (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides and window movement strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch, const Output<Node>& filters);
void validate_and_infer_types() override;
bool visit_attributes(AttributeVisitor& visitor) override;
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
/// \return The window movement strides.
const Strides& get_window_movement_strides() const
{
return m_window_movement_strides;
}
void set_window_movement_strides(const Strides& window_movement_strides)
{
m_window_movement_strides = window_movement_strides;
}
/// \return The window dilation strides.
const Strides& get_window_dilation_strides() const
{
return m_window_dilation_strides;
}
void set_window_dilation_strides(const Strides& window_dilation_strides)
{
m_window_dilation_strides = window_dilation_strides;
}
/// \return The padding-below sizes (possibly negative).
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
void set_padding_below(const CoordinateDiff& padding_below)
{
m_padding_below = padding_below;
}
/// \return The padding-above sizes (possibly negative).
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
void set_adding_above(const CoordinateDiff& padding_above)
{
m_padding_above = padding_above;
}
/// \return The input data dilation strides.
const Strides& get_data_dilation_strides() const { return m_data_dilation_strides; }
void set_data_dilation_strides(const Strides& data_dilation_strides)
{
m_data_dilation_strides = data_dilation_strides;
}
/// \return The pad type for convolution.
const PadType& get_pad_type() const { return m_pad_type; }
void set_pad_type(const PadType& pad_type) { m_pad_type = pad_type; }
/// \return The default value for Convolution.
NGRAPH_SUPPRESS_DEPRECATED_START
virtual std::shared_ptr<Node> get_default_value() const override;
NGRAPH_SUPPRESS_DEPRECATED_END
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
Strides m_data_dilation_strides;
PadType m_pad_type;
};
/// \brief Data batch backprop for batched convolution operation.
class BACKEND_API ConvolutionBackpropData : public Op
{
public:
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropData", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution data batch-backprop operation.
ConvolutionBackpropData() = default;
///
/// \brief Constructs a batched-convolution data batch-backprop operation.
///
/// \param data_batch_shape The shape of the data batch from
/// forward-prop.
/// \param filters The node producing the filters from
/// forward-prop.
/// \param data The node producing output delta.
/// \param window_movement_strides_forward The window movement strides from
/// forward-prop.
/// \param window_dilation_strides_forward The window dilation strides from
/// forward-prop.
/// \param padding_below_forward The padding-below sizes from
/// forward-prop.
/// \param padding_above_forward The padding-above sizes from
/// forward-prop.
/// \param data_dilation_strides_forward The data dilation strides from
/// forward-prop.
///
ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& data,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward);
void validate_and_infer_types() override;
bool visit_attributes(AttributeVisitor& visitor) override;
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
/// \return The data batch shape.
const Shape& get_data_batch_shape() const { return m_data_batch_shape; }
void set_data_batch_shape(const Shape& data_batch_shape)
{
m_data_batch_shape = data_batch_shape;
}
/// \return The window movement strides from the forward prop.
const Strides& get_window_movement_strides_forward() const
{
return m_window_movement_strides_forward;
}
void set_window_movement_strides_forward(
const Strides& window_movement_strides_forward)
{
m_window_movement_strides_forward = window_movement_strides_forward;
}
/// \return The window dilation strides from the forward prop.
const Strides& get_window_dilation_strides_forward() const
{
return m_window_dilation_strides_forward;
}
void set_window_dilation_strides_forward(
const Strides& window_dilation_strides_forward)
{
m_window_dilation_strides_forward = window_dilation_strides_forward;
}
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_below_forward() const
{
return m_padding_below_forward;
}
void set_padding_below_forward(const CoordinateDiff& padding_below_forward)
{
m_padding_below_forward = padding_below_forward;
}
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_above_forward() const
{
return m_padding_above_forward;
}
void set_padding_above_forward(const CoordinateDiff& padding_above_forward)
{
m_padding_above_forward = padding_above_forward;
}
/// \return The input data dilation strides from the forward prop.
const Strides& get_data_dilation_strides_forward() const
{
return m_data_dilation_strides_forward;
}
void set_data_dilation_strides_forward(const Strides& data_dilation_strides_forward)
{
m_data_dilation_strides_forward = data_dilation_strides_forward;
}
// Compute the pad_above values to be used if in a convolution
CoordinateDiff compute_backward_delta_out_pad_above() const;
CoordinateDiff compute_backward_delta_out_pad_below() const;
protected:
Shape m_data_batch_shape;
Strides m_window_movement_strides_forward;
Strides m_window_dilation_strides_forward;
CoordinateDiff m_padding_below_forward;
CoordinateDiff m_padding_above_forward;
Strides m_data_dilation_strides_forward;
};
} // namespace v0
} // namespace op
} // namespace ngraph
-319
View File
@@ -1,319 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <numeric>
#include "convolution.hpp"
#include "group_conv.hpp"
#include "ngraph/attribute_visitor.hpp"
#include "ngraph/builder/reshape.hpp"
#include "ngraph/builder/split.hpp"
#include "ngraph/op/concat.hpp"
#include "ngraph/op/convolution.hpp"
#include "ngraph/validation_util.hpp"
using namespace std;
using namespace ngraph;
NGRAPH_SUPPRESS_DEPRECATED_START
//------------------------------------------------------------------------------
// v0::GroupConvolution
//------------------------------------------------------------------------------
constexpr NodeTypeInfo op::v0::GroupConvolution::type_info;
op::v0::GroupConvolution::GroupConvolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const size_t groups,
const PadType& pad_type)
: FusedOp({data_batch, filters})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_data_dilation_strides(data_dilation_strides)
, m_groups(groups)
, m_pad_type(pad_type)
, m_groups_in_filters(false)
{
constructor_validate_and_infer_types();
}
op::v0::GroupConvolution::GroupConvolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type)
: FusedOp({data_batch, filters})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_data_dilation_strides(data_dilation_strides)
, m_groups(0)
, m_pad_type(pad_type)
, m_groups_in_filters(true)
{
constructor_validate_and_infer_types();
}
void op::v0::GroupConvolution::pre_validate_and_infer_types()
{
auto data_shape = get_input_partial_shape(0);
auto filters_shape = get_input_partial_shape(1);
if (data_shape.is_static() && filters_shape.is_static())
{
// Update groups
if (m_groups_in_filters)
{
m_groups = get_input_partial_shape(1)[0].get_length();
}
// Data channels
NODE_VALIDATION_CHECK(this,
data_shape.to_shape()[1] % get_groups() == 0,
"Data channels not a multiple of group size");
// Output channels
NODE_VALIDATION_CHECK(this,
filters_shape.to_shape()[0] % get_groups() == 0,
"# Filters not a multiple of group size");
// Input Filters
NODE_VALIDATION_CHECK(this,
(filters_shape.to_shape()[m_groups_in_filters ? 2 : 1] *
get_groups()) == data_shape.to_shape()[1],
"Incorrect number of channels per filter");
}
else
{
set_output_type(0, get_input_element_type(0), PartialShape::dynamic());
}
}
void op::v0::GroupConvolution::post_validate_and_infer_types()
{
auto data_shape = get_input_partial_shape(0);
auto filters_shape = get_input_partial_shape(1);
if (data_shape.is_static() && filters_shape.is_static())
{
if (m_pad_type == PadType::SAME_UPPER || m_pad_type == PadType::SAME_LOWER)
{
m_padding_below.clear();
m_padding_above.clear();
auto filter_shape = filters_shape.to_shape();
filter_shape.erase(filter_shape.begin(), filter_shape.begin() + 2); // Remove {O,I}
infer_auto_padding(data_shape.to_shape(),
filter_shape,
m_window_movement_strides,
m_window_dilation_strides,
m_pad_type,
m_padding_above,
m_padding_below);
}
}
}
Shape op::v0::GroupConvolution::get_weights_dimensions() const
{
auto data_shape = get_input_shape(0);
auto weights_shape = get_input_shape(1);
// check if weights already includes groups
if (m_groups_in_filters)
{
return weights_shape;
}
// reshape weights into 5d tensors that includes groups
const size_t OC = 0;
const size_t OC_IN_OUTPUT = 1;
const size_t IC = 1;
Shape weights_shape_groups{weights_shape};
// adjust output and channel given a number of groups
weights_shape_groups.at(OC) = get_shape().at(OC_IN_OUTPUT) / get_groups();
weights_shape_groups.at(IC) = data_shape.at(IC) / get_groups();
// push_front the number of groups
weights_shape_groups.insert(weights_shape_groups.begin(), get_groups());
return weights_shape_groups;
}
shared_ptr<Node> op::v0::GroupConvolution::clone_with_new_inputs(const OutputVector& new_args) const
{
check_new_args_count(this, new_args);
if (m_groups_in_filters)
{
return make_shared<op::v0::GroupConvolution>(new_args.at(0),
new_args.at(1),
get_window_movement_strides(),
get_window_dilation_strides(),
get_padding_below(),
get_padding_above(),
get_data_dilation_strides(),
get_pad_type());
}
else
{
return make_shared<op::v0::GroupConvolution>(new_args.at(0),
new_args.at(1),
get_window_movement_strides(),
get_window_dilation_strides(),
get_padding_below(),
get_padding_above(),
get_data_dilation_strides(),
get_groups(),
get_pad_type());
}
}
OutputVector op::v0::GroupConvolution::decompose_op() const
{
auto data = input_value(0);
auto filters = input_value(1);
auto filters_shape = get_input_shape(1);
// Split one convolution op to N ops where N is the number of groups
// and concat results after computation.
NodeVector convolution_nodes;
// slice data
auto sliced_data = builder::opset1::split(data, get_groups(), 1);
// slice filters
auto sliced_filters = builder::opset1::split(filters, get_groups(), 0);
auto shape = Shape(std::next(std::begin(filters_shape), 1), std::end(filters_shape));
for (std::size_t group{0}; group < get_groups(); ++group)
{
auto sliced_filter = sliced_filters[group];
if (m_groups_in_filters)
{
// Remove group dimension after slicing
sliced_filter = builder::opset1::reshape(sliced_filters[group], shape);
}
convolution_nodes.push_back(
std::make_shared<ngraph::op::v0::Convolution>(sliced_data[group],
sliced_filter,
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides,
m_pad_type));
}
std::size_t concatenation_axis = 1;
return {std::make_shared<ngraph::op::Concat>(convolution_nodes, concatenation_axis)};
}
//------------------------------------------------------------------------------
// v0::GroupConvolutionBackpropData
//------------------------------------------------------------------------------
constexpr NodeTypeInfo op::v0::GroupConvolutionBackpropData::type_info;
op::v0::GroupConvolutionBackpropData::GroupConvolutionBackpropData(
const Output<Node>& data_batch,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const size_t groups)
: FusedOp({data_batch, filters, output_delta})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
, m_padding_below(padding_below)
, m_padding_above(padding_above)
, m_groups(groups)
{
constructor_validate_and_infer_types();
}
void op::v0::GroupConvolutionBackpropData::pre_validate_and_infer_types()
{
element::Type data_element_type = get_input_element_type(2);
element::Type filters_elem_type = get_input_element_type(1);
NODE_VALIDATION_CHECK(this,
data_element_type.is_dynamic() || data_element_type.is_real(),
"Output delta element type must be f16, bf16, f32, f64 or dynamic (got ",
data_element_type,
").");
NODE_VALIDATION_CHECK(this,
filters_elem_type.is_dynamic() || filters_elem_type.is_real(),
"Filters element type must be f16, bf16, f32, f64 or dynamic (got ",
filters_elem_type,
").");
PartialShape data_pshape = get_input_partial_shape(0);
PartialShape filters_pshape = get_input_partial_shape(1);
PartialShape delta_pshape = get_input_partial_shape(2);
if (data_pshape.is_dynamic() || filters_pshape.is_dynamic() || delta_pshape.is_dynamic())
{
set_output_type(0, data_element_type, PartialShape::dynamic());
}
}
shared_ptr<Node>
op::v0::GroupConvolutionBackpropData::clone_with_new_inputs(const OutputVector& new_args) const
{
if (new_args.size() != 3)
{
throw ngraph_error("Incorrect number of new arguments");
}
return make_shared<op::v0::GroupConvolutionBackpropData>(new_args.at(0),
new_args.at(1),
new_args.at(2),
get_window_movement_strides(),
get_window_dilation_strides(),
get_padding_below(),
get_padding_above(),
get_groups());
}
OutputVector op::v0::GroupConvolutionBackpropData::decompose_op() const
{
auto filters = input_value(1);
auto output_delta = input_value(2);
auto data_shape = get_input_shape(0);
NodeVector sliced_inputs;
auto groups = get_groups();
// slice data shape
data_shape[1] /= groups;
// slice delta
auto sliced_delta = builder::opset1::split(output_delta, groups, 1);
// slice filters
auto sliced_filters = builder::opset1::split(filters, groups, 0);
auto num_spatials = get_window_movement_strides().size();
for (size_t i = 0; i < groups; ++i)
{
auto sliced_conv = std::make_shared<op::v0::ConvolutionBackpropData>(
data_shape,
sliced_filters[i],
sliced_delta[i],
get_window_movement_strides(),
get_window_dilation_strides(),
get_padding_below(),
get_padding_above(),
Strides(num_spatials, 1)); // default data dilation strides
sliced_inputs.push_back(sliced_conv);
}
size_t concatenation_axis = 1;
return {std::make_shared<ngraph::op::Concat>(sliced_inputs, concatenation_axis)};
}
-131
View File
@@ -1,131 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/op/convolution.hpp"
#include "ngraph/op/op.hpp"
#include "ngraph/op/util/attr_types.hpp"
#include "ngraph/op/util/fused_op.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
namespace ngraph
{
namespace op
{
namespace v0
{
/// \brief Group Convolution
class BACKEND_API GroupConvolution : public ngraph::op::util::FusedOp
{
public:
static constexpr NodeTypeInfo type_info{"GroupConvolution", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
GroupConvolution() = default;
GroupConvolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const size_t groups,
const PadType& pad_type = PadType::EXPLICIT);
// constructor which accept groups included in filters shape.
GroupConvolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type = PadType::EXPLICIT);
Shape get_weights_dimensions() const;
const Strides& get_window_movement_strides() const
{
return m_window_movement_strides;
}
const Strides& get_window_dilation_strides() const
{
return m_window_dilation_strides;
}
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
const Strides& get_data_dilation_strides() const { return m_data_dilation_strides; }
Output<Node> get_filters() { return input_value(1); }
Output<Node> get_data_batch() { return input_value(0); }
size_t get_groups() const { return m_groups; };
const PadType& get_pad_type() const { return m_pad_type; }
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
virtual OutputVector decompose_op() const override;
virtual void pre_validate_and_infer_types() override;
virtual void post_validate_and_infer_types() override;
bool has_groups_in_filters() const { return m_groups_in_filters; }
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
Strides m_data_dilation_strides;
size_t m_groups;
PadType m_pad_type{PadType::NOTSET};
private:
bool m_groups_in_filters;
};
/// \brief Group Convolution data batch backprop
class BACKEND_API GroupConvolutionBackpropData : public ngraph::op::util::FusedOp
{
public:
static constexpr NodeTypeInfo type_info{"GroupConvolutionBackpropData", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
GroupConvolutionBackpropData() = default;
GroupConvolutionBackpropData(const Output<Node>& data_batch,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const size_t groups);
const Strides& get_window_movement_strides() const
{
return m_window_movement_strides;
}
const Strides& get_window_dilation_strides() const
{
return m_window_dilation_strides;
}
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
size_t get_groups() const { return m_groups; };
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
virtual OutputVector decompose_op() const override;
virtual void pre_validate_and_infer_types() override;
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
size_t m_groups;
};
}
} // namespace op
} // namespace ngraph
NGRAPH_SUPPRESS_DEPRECATED_END
-101
View File
@@ -1,101 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
// This collection contains one entry for each op. If an op is added it must be
// added to this list.
//
// In order to use this list you want to define a macro named exactly NGRAPH_OP
// When you are done you should undef the macro
// As an example if you wanted to make a list of all op names as strings you could do this:
//
// #define NGRAPH_OP(a,b) #a,
// std::vector<std::string> op_names{
// #include "this include file name"
// };
// #undef NGRAPH_OP
//
// This sample expands to a list like this:
// "Abs",
// "Acos",
// ...
//
// #define NGRAPH_OP(a,b) b::a,
// std::vector<std::string> op_names{
// #include "this include file name"
// };
// #undef NGRAPH_OP
//
// This sample expands to a list like this:
// ngraph::op::Abs,
// ngraph::op::Acos,
// ...
//
// It's that easy. You can use this for fun and profit.
#ifndef NGRAPH_OP
#warning "NGRAPH_OP not defined"
#define NGRAPH_OP(x, y)
#endif
NGRAPH_OP(Abs, ngraph::op)
NGRAPH_OP(Acos, ngraph::op)
NGRAPH_OP(Asin, ngraph::op)
NGRAPH_OP(Atan, ngraph::op)
NGRAPH_OP(AvgPool, ngraph::op::v0)
NGRAPH_OP(BatchNormInference, ngraph::op::v0)
NGRAPH_OP(Broadcast, ngraph::op::v1)
NGRAPH_OP(Ceiling, ngraph::op)
NGRAPH_OP(Clamp, ngraph::op)
NGRAPH_OP(Concat, ngraph::op)
NGRAPH_OP(Constant, ngraph::op)
NGRAPH_OP(Convert, ngraph::op)
NGRAPH_OP(Convolution, ngraph::op::v0)
NGRAPH_OP(ConvolutionBackpropData, ngraph::op::v0)
NGRAPH_OP(Cos, ngraph::op)
NGRAPH_OP(Cosh, ngraph::op)
NGRAPH_OP(CumSum, ngraph::op::v0)
NGRAPH_OP(DepthToSpace, ngraph::op)
NGRAPH_OP(Elu, ngraph::op)
NGRAPH_OP(Erf, ngraph::op)
NGRAPH_OP(Exp, ngraph::op)
NGRAPH_OP(FakeQuantize, ngraph::op)
NGRAPH_OP(Floor, ngraph::op)
NGRAPH_OP(GRN, ngraph::op)
NGRAPH_OP(Gather, ngraph::op::v1)
NGRAPH_OP(Gelu, ngraph::op)
NGRAPH_OP(GroupConvolution, ngraph::op::v0)
NGRAPH_OP(GroupConvolutionBackpropData, ngraph::op::v0)
NGRAPH_OP(HardSigmoid, ngraph::op)
NGRAPH_OP(Interpolate, ngraph::op::v0)
NGRAPH_OP(Log, ngraph::op)
NGRAPH_OP(LRN, ngraph::op)
NGRAPH_OP(LSTMSequence, ngraph::op::v0)
NGRAPH_OP(MatMul, ngraph::op)
NGRAPH_OP(MVN, ngraph::op)
NGRAPH_OP(Negative, ngraph::op)
NGRAPH_OP(NormalizeL2, ngraph::op::v0)
NGRAPH_OP(Parameter, ngraph::op)
NGRAPH_OP(PRelu, ngraph::op)
NGRAPH_OP(PriorBox, ngraph::op)
NGRAPH_OP(Range, ngraph::op)
NGRAPH_OP(Relu, ngraph::op)
NGRAPH_OP(Result, ngraph::op)
NGRAPH_OP(ReverseSequence, ngraph::op)
NGRAPH_OP(Selu, ngraph::op)
NGRAPH_OP(ShapeOf, ngraph::op)
NGRAPH_OP(ShuffleChannels, ngraph::op)
NGRAPH_OP(Sigmoid, ngraph::op)
NGRAPH_OP(Sign, ngraph::op)
NGRAPH_OP(Sin, ngraph::op)
NGRAPH_OP(Sinh, ngraph::op)
NGRAPH_OP(SpaceToDepth, ngraph::op)
NGRAPH_OP(Sqrt, ngraph::op)
NGRAPH_OP(SquaredDifference, ngraph::op)
NGRAPH_OP(Squeeze, ngraph::op)
NGRAPH_OP(Tan, ngraph::op)
NGRAPH_OP(Tanh, ngraph::op)
NGRAPH_OP(TensorIterator, ngraph::op)
NGRAPH_OP(Tile, ngraph::op::v0)
NGRAPH_OP(Unsqueeze, ngraph::op::v0)
NGRAPH_OP(Xor, ngraph::op)
@@ -1,80 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "fused_op_decomposition.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/op/util/op_types.hpp"
#include "ngraph/provenance.hpp"
using namespace std;
using namespace ngraph;
NGRAPH_SUPPRESS_DEPRECATED_START
pass::FusedOpDecomposition::FusedOpDecomposition(op_query_t callback)
: m_has_direct_support{callback}
{
}
bool pass::FusedOpDecomposition::run_on_node(shared_ptr<Node> node)
{
bool modified = false;
if (op::supports_decompose(node))
{
if (m_has_direct_support && m_has_direct_support(*node))
{
// Op supported by backend. Do not decompose
return modified;
}
OutputVector output_vector = node->decompose_op();
NodeVector subgraph_outputs = as_node_vector(output_vector);
if (ngraph::get_provenance_enabled())
{
// Capture the input values as an edge for provenance
auto base_input_values = node->input_values();
auto provenance_tags = node->get_provenance_tags();
const std::string tag = "<Decomposed from " + std::string(node->get_type_name()) + ">";
provenance_tags.insert(tag);
// Transfer the new provenance tags to the newly created ops
for (auto output_node : subgraph_outputs)
{
output_node->add_provenance_tags_above(base_input_values, provenance_tags);
}
}
// Run recursively until no more fused ops
auto subgraph = extract_subgraph(subgraph_outputs, as_node_vector(node->input_values()));
for (auto subgraph_node : subgraph)
{
run_on_node(subgraph_node);
}
size_t i = 0;
for (auto output_node : subgraph_outputs)
{
for (size_t j = 0; j < output_node->outputs().size(); j++, i++)
{
std::set<Input<Node>> fop_users = node->outputs().at(i).get_target_inputs();
for (auto fop_user : fop_users)
{
fop_user.replace_source_output(output_node->output(j));
}
}
}
if (i != node->get_output_size())
{
throw ngraph_error("While replacing " + node->get_name() +
", mismatch between op output count and outputs of the decomposed "
"subgraph. Expected: " +
to_string(node->get_output_size()) + " Got: " + to_string(i));
}
modified = true;
}
return modified;
}
@@ -1,67 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <memory>
#include "backend_visibility.hpp"
#include "ngraph/pass/pass.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
namespace ngraph
{
namespace pass
{
/// \brief The FusedOpDecomposition pass is used to decompose a fused op
/// into a sub-graph of supported ops if the fused op is not supported by
/// the backend.
///
/// \details By default, the pass decomposes a fused op if it is not
/// supported by the backend and runs recursively until no more fused ops
/// can be found or the new ops are supported by the backend.
/// If the backend supports a fused op, then it can provide a callback
/// function while registering the pass. The callback function can then
/// provide logic to prevent decomposing the supported op.
/// It also adds provenance tags along the way to each op for easy reference
/// and debugging.
///
/// In the example shown below, the original graph has a fused GeLU op.
/// After applying this pass, the GeLU op is decomposed into group of ops which
/// together perform the same operation as GeLU.
/// <table>
/// <tr><th>Before the pass</th>
/// <th> After the pass</th>
/// </tr>
/// <tr>
/// <td> \image html decompose_gelu_pre.svg </td>
/// <td> \image html decompose_gelu_post.svg </td>
/// </tr>
/// </table>
class BACKEND_API FusedOpDecomposition : public NodePass
{
public: /// \brief Function signature type for callback used to check whether provided node
/// is supported by backend.
using op_query_t = std::function<bool(const Node& node)>;
///
/// \brief Constructor for the Fused operation decomposition pass.
///
/// \param[in] callback The function object used to determine whether current backend
/// provide direct support for passed node. Should have signature:
/// bool fn(const Node&)
///
FusedOpDecomposition(op_query_t callback = nullptr);
bool run_on_node(std::shared_ptr<ngraph::Node> node) override;
private:
/// \brief A function returning whether provided Node is supported by current backend.
/// The returned bool value is used to control whether decompose operator or not.
op_query_t m_has_direct_support = nullptr;
};
}
}
NGRAPH_SUPPRESS_DEPRECATED_END
@@ -1,61 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "implicit_broadcast_elimination.hpp"
#include "ngraph/builder/autobroadcast.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/op/util/binary_elementwise_arithmetic.hpp"
#include "ngraph/op/util/binary_elementwise_comparison.hpp"
#include "ngraph/op/util/binary_elementwise_logical.hpp"
#include "ngraph/op/util/op_types.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace std;
using namespace ngraph;
bool ngraph::pass::ImplicitBroadcastElimination::run_on_node(std::shared_ptr<Node> node)
{
if (ngraph::op::supports_auto_broadcast(node))
{
if (node->get_autob().m_type != op::AutoBroadcastType::NONE)
{
auto new_args = pass::explicit_broadcast(node);
for (size_t i = 0; i < new_args.size(); i++)
{
node->input(i).replace_source_output(new_args[i]->output(0));
}
return true;
}
}
return false;
}
NodeVector ngraph::pass::explicit_broadcast(std::shared_ptr<Node>& node)
{
NodeVector rc;
if (ngraph::op::supports_auto_broadcast(node))
{
auto autob = node->get_autob();
if (autob.m_type == op::AutoBroadcastType::NONE)
{
for (auto& val : node->input_values())
rc.emplace_back(val.get_node_shared_ptr());
}
else if (autob.m_type == op::AutoBroadcastType::NUMPY)
{
rc = as_node_vector(builder::numpy_broadcast_outputs(node->input_values()));
}
else if (autob.m_type == op::AutoBroadcastType::PDPD)
{
rc = as_node_vector(builder::pdpd_broadcast(node->input_values(), autob.m_axis));
}
else
{
throw ngraph_error("Unsupported implicit broadcast type");
}
}
return rc;
}
@@ -1,28 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/node.hpp"
#include "ngraph/pass/pass.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
namespace ngraph
{
namespace pass
{
NodeVector explicit_broadcast(std::shared_ptr<Node>& node);
class ImplicitBroadcastElimination;
}
}
class BACKEND_API ngraph::pass::ImplicitBroadcastElimination : public ngraph::pass::NodePass
{
public:
bool run_on_node(std::shared_ptr<ngraph::Node> node) override;
};
NGRAPH_SUPPRESS_DEPRECATED_END
-119
View File
@@ -1,119 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <exception>
#include <sstream>
#include <unordered_set>
#include "liveness.hpp"
#include "ngraph/descriptor/input.hpp"
#include "ngraph/descriptor/output.hpp"
#include "ngraph/function.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/log.hpp"
#include "ngraph/node.hpp"
#include "ngraph/op/constant.hpp"
#include "ngraph/op/parameter.hpp"
#include "ngraph/op/result.hpp"
#include "ngraph/util.hpp"
using namespace std;
using namespace ngraph;
bool pass::Liveness::run_on_function(shared_ptr<Function> function)
{
auto ops = function->get_ordered_ops();
unordered_set<descriptor::Tensor*> persistent_tensors;
unordered_set<descriptor::Tensor*> output_tensors;
for (const shared_ptr<op::Parameter>& node : function->get_parameters())
{
for (auto& output : node->outputs())
{
descriptor::Tensor& tensor = output.get_tensor();
persistent_tensors.insert(&tensor);
}
}
for (const shared_ptr<op::Result>& node : function->get_results())
{
for (auto& output : node->outputs())
{
descriptor::Tensor& tensor = output.get_tensor();
persistent_tensors.insert(&tensor);
output_tensors.insert(&tensor);
}
}
for (const shared_ptr<Node>& node : ops)
{
if (auto constant_node = as_type_ptr<op::Constant>(node))
{
for (auto& output : constant_node->outputs())
{
descriptor::Tensor& tensor = output.get_tensor();
persistent_tensors.insert(&tensor);
}
}
}
unordered_set<descriptor::Tensor*> currently_live;
for (auto it = ops.rbegin(); it != ops.rend(); it++)
{
const shared_ptr<Node>& node = *it;
node->liveness_new_list.clear();
node->liveness_free_list.clear();
unordered_set<descriptor::Tensor*> input_tensor_decls;
for (auto& input : node->inputs())
{
descriptor::Tensor& tensor = input.get_tensor();
if (persistent_tensors.find(&tensor) == persistent_tensors.end())
{
input_tensor_decls.insert(&tensor);
}
}
unordered_set<descriptor::Tensor*> output_tensor_decls;
for (auto& output : node->outputs())
{
descriptor::Tensor& tensor = output.get_tensor();
if (persistent_tensors.find(&tensor) == persistent_tensors.end())
{
output_tensor_decls.insert(&tensor);
}
}
unordered_set<descriptor::Tensor*> free_tensor_decls;
unordered_set<descriptor::Tensor*> new_tensor_decls;
unordered_set<descriptor::Tensor*> all_tensor_decls = input_tensor_decls;
all_tensor_decls.insert(output_tensor_decls.begin(), output_tensor_decls.end());
for (descriptor::Tensor* tensor_decl : all_tensor_decls)
{
if (currently_live.find(tensor_decl) == currently_live.end())
{
// this is the last node that value is seen in
// delete it at the end of the op
currently_live.insert(tensor_decl);
if (output_tensors.find(tensor_decl) == output_tensors.end())
{
// Don't free output tensors
free_tensor_decls.insert(tensor_decl);
}
}
}
for (descriptor::Tensor* output_decl : output_tensor_decls)
{
auto currently_live_it = currently_live.find(output_decl);
if (currently_live_it != currently_live.end())
{
new_tensor_decls.insert(output_decl);
currently_live.erase(currently_live_it);
}
}
node->liveness_free_list = free_tensor_decls;
node->liveness_new_list = new_tensor_decls;
}
return false;
}
-23
View File
@@ -1,23 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/descriptor/tensor.hpp"
#include "ngraph/pass/pass.hpp"
namespace ngraph
{
namespace pass
{
class Liveness;
}
}
class BACKEND_API ngraph::pass::Liveness : public FunctionPass
{
public:
bool run_on_function(std::shared_ptr<ngraph::Function>) override;
};
@@ -1,132 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <algorithm>
#include <cstdint>
#include <functional>
#include <numeric>
#include "ngraph/builder/autobroadcast.hpp"
#include "ngraph/builder/reshape.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/node.hpp"
#include "ngraph/op/util/attr_types.hpp"
#include "ngraph/op/util/op_types.hpp"
#include "ngraph/ops.hpp"
#include "ngraph/provenance.hpp"
#include "ngraph/slice_plan.hpp"
#include "ngraph/type.hpp"
#include "ngraph/validation_util.hpp"
#include "op/avg_pool.hpp"
#include "pass/implicit_broadcast_elimination.hpp"
#include "pass/opset0_downgrade.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
using namespace std;
using namespace ngraph;
namespace opset0_downgrade
{
template <typename OpV0, typename OpV1>
shared_ptr<Node> op_cast_binary_elementwise_node(const shared_ptr<OpV1>& node)
{
const auto input_arg0 = node->input_value(0);
const auto input_arg1 = node->input_value(1);
const auto autob = node->get_autob();
auto replacement_node = make_shared<OpV0>(input_arg0, input_arg1, autob);
replace_node(node, replacement_node);
return replacement_node;
}
template <typename OpV0, typename OpV1>
shared_ptr<Node> op_cast_reduction_node(const shared_ptr<OpV1>& node)
{
auto replacement_node = make_shared<OpV0>(node->input_value(0), node->input_value(1));
if (node->get_keep_dims())
{
string v1_op_name = string{node->get_type_name()} + ":v1";
string v0_op_name = string{OpV0{}.get_type_name()} + ":v0";
NGRAPH_CHECK(node->reduction_axes_constant(),
"Unable to convert ",
v1_op_name,
"to ",
v0_op_name,
" if reduction axes are not constant (for keep_dims=true). Node: ",
*node);
auto output_pshape = replacement_node->get_output_partial_shape(0);
NGRAPH_CHECK(output_pshape.is_static(),
"Unable to convert ",
v1_op_name,
"to ",
v0_op_name,
" if output shape is dynamic (for keep_dims=true). Node: ",
*node);
const auto output_shape = output_pshape.to_shape();
auto reshaped_output_shape = output_shape;
for (const auto& axis : node->get_reduction_axes())
{
reshaped_output_shape.insert(reshaped_output_shape.begin() + axis, 1);
}
auto shape_pattern = op::Constant::create(
element::u64, {reshaped_output_shape.size()}, reshaped_output_shape);
auto reshaped_product =
make_shared<op::v1::Reshape>(replacement_node->output(0), shape_pattern, false);
return reshaped_product;
}
else
{
return replacement_node;
}
}
// Default is that we did nothing
shared_ptr<Node> op_cast(shared_ptr<Node> node) { return nullptr; }
shared_ptr<Node> op_cast(shared_ptr<op::v1::LogicalXor> node)
{
return op_cast_binary_elementwise_node<op::v0::Xor, op::v1::LogicalXor>(node);
}
using DispatchMap = map<NodeTypeInfo, std::function<bool(shared_ptr<Node> node)>>;
template <typename T>
bool op_cast_thunk(shared_ptr<Node> node)
{
auto downgraded_node = op_cast(as_type_ptr<T>(node));
if (downgraded_node)
{
if (ngraph::get_provenance_enabled())
{
const std::string provenance_tag =
"<Opset0_Downgrade (v1 " + std::string(node->get_type_name()) + ")>";
downgraded_node->add_provenance_tags_above(node->input_values(), {provenance_tag});
}
return true;
}
return false;
}
DispatchMap& get_dispatch_map()
{
static DispatchMap dispatch_map{
#define NGRAPH_OP(NAME, NAMESPACE) {NAMESPACE::NAME::type_info, op_cast_thunk<NAMESPACE::NAME>},
#include "ngraph/opsets/opset1_tbl.hpp"
#undef NGRAPH_OP
};
return dispatch_map;
}
} // namespace opset0_downgrade
bool pass::Opset0Downgrade::run_on_node(shared_ptr<Node> node)
{
bool modified = false;
auto& dispatch_map = opset0_downgrade::get_dispatch_map();
auto it = dispatch_map.find(node->get_type_info());
if (it != dispatch_map.end())
{
modified = it->second(node);
}
return modified;
}
@@ -1,31 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "backend_visibility.hpp"
#include "ngraph/pass/pass.hpp"
NGRAPH_SUPPRESS_DEPRECATED_START
namespace ngraph
{
namespace pass
{
class BACKEND_API Opset0Downgrade : public NodePass
{
public:
///
/// \brief Constructor for the Opv1 downgrade transformation pass.
///
/// \details This transformation pass iterates over all nodes in a graph
/// and updates version 1 ops to their version 0 equivalents.
/// All ops in the final graph have op version 0.
Opset0Downgrade() = default;
bool run_on_node(std::shared_ptr<ngraph::Node> node) override;
};
}
}
NGRAPH_SUPPRESS_DEPRECATED_END
Loaded 100 of 116 files, more files were not shown because too many files have changed in this diff. Show more