Merge remote-tracking branch 'upstream/master'

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

7
.gitattributes vendored
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

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)

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})

0
docs/IE_DG/img/applying_low_latency.png Executable file → Normal file
View File

0
docs/IE_DG/img/applying_low_latency_2.png Executable file → Normal file
View File

0
docs/IE_DG/img/llt2_use_const_initializer.png Executable file → Normal file
View File

0
docs/IE_DG/img/low_latency_limitation_1.png Executable file → Normal file
View File

0
docs/IE_DG/img/low_latency_limitation_2.png Executable file → Normal file
View File

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

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">

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">

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" ...>

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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>();
}
};

View File

@ -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();
if (initialize_input_desc) {
m_inputs_desc.push_back(new_input_desc);
} else {
auto get_message = [&]() {
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: " << std::get<0>(new_input_desc) << ", "
<< std::get<1>(new_input_desc) << std::endl;
out << "After: " << input_pshape << ", "
<< input_type << std::endl;
out << "Please specify InferenceEngine Extensions to support this case.";
return out.str();
};
NODE_VALIDATION_CHECK(this, m_inputs_desc[i] == new_input_desc, get_message());
if (initialize_input_desc) {
m_inputs_desc.emplace_back(input_pshape, input_type);
} else {
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());
}
}
}
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]));
}
}
}

View File

@ -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);
}

View File

@ -19,28 +19,22 @@ 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 {
return false;
}
auto softplus = std::make_shared<ngraph::opset4::SoftPlus>(exp_input);

View File

@ -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());

View File

@ -37,6 +37,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
{Negative, {}},
{Acos, {}},
{Asin, {}},
{Asinh, {}},
{Atan, {}},
{Cos, {}},
{Cosh, {}},

View File

@ -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);
}

View File

@ -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});
}

View File

@ -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, {}},

View File

@ -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

View File

@ -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} };

View File

@ -35,6 +35,7 @@ const std::map<ActivationTypes, std::vector<std::vector<float>>> activationTypes
{Negative, {}},
{Acos, {}},
{Asin, {}},
{Asinh, {}},
{Atan, {}},
{Cos, {}},
{Cosh, {}},

View File

@ -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"},

View File

@ -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 {

View File

@ -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;

View File

@ -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',

View File

@ -100,6 +100,7 @@ enum ActivationTypes {
Negative,
Acos,
Asin,
Asinh,
Atan,
Cos,
Cosh,

View File

@ -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:

View File

@ -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

View File

@ -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));

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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)])

View File

@ -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)])

View File

@ -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)])

View File

@ -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))

View File

@ -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()])

View File

@ -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 (
@ -65,12 +73,23 @@ 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.

View File

@ -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"

View File

@ -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])

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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}/)

View File

@ -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);

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.

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.

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)

View File

@ -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

View File

@ -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

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;

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;

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>>;

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:

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));
}

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)));
}

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;

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

View File

@ -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)

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)

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

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();
}

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}}},

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();
}

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}));
}

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
}

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());
}

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());
}

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});

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"}));
}

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
)

View File

@ -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

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())
{

View File

@ -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
{

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;
}

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;
};
}
}
}

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});
}

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

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;
}

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

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)};
}

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

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)

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

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;
}

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;
};

View File

@ -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;
}

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More