[LPT][CommonOptimizations] ShuffleChannelsTransformation and ShuffleChannelsFusion (#4916)
* [nGraph] op::v0::ShuffleChannels: added type_info macros * [LPT] ShuffleChannelsTransformation * [CPU] ShuffleChannels decomposition disabled * [LPT][TESTS] ShuffleChannelsTransformation functional tests * [LPT][TESTS] ShuffleChannelsTransformation plugin tests * [CommonOptimizations] Added ShuffleChannelsFusion transformation * [CommonOptimizations][TESTS] ShuffleChannelsFusion tests * refactoring and adding comments * [CommonOptimizations] ShuffleChannelsFusion refactoring and fixes * [CommonOptimizations] ShuffleChannelsFusion: removed unnecessary check * [CommonOptimizations] transformation refactored and test-cases with dynamic shape added
This commit is contained in:
parent
576e692b1d
commit
05c23dfd94
|
|
@ -342,7 +342,7 @@ protected:
|
|||
void addPattern(ngraph::pass::GraphRewrite& pass, TransformationContext& context, std::shared_ptr<Node> patternRoot) const;
|
||||
|
||||
//TODO: replace with canBeTransformed when quantization by special dimension is supported for all transformations
|
||||
bool canBeTransformedSpecialDimension(const TransformationContext& context, std::shared_ptr<Node> layer) const;
|
||||
bool canBeTransformedSpatialDimension(const TransformationContext& context, std::shared_ptr<Node> layer) const;
|
||||
|
||||
template <typename Operation>
|
||||
void addSingleNodePattern(ngraph::pass::GraphRewrite& pass, TransformationContext& context) const {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include "low_precision/layer_transformation.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
namespace low_precision {
|
||||
|
||||
class TRANSFORMATIONS_API ShuffleChannelsTransformation : public LayerTransformation {
|
||||
public:
|
||||
ShuffleChannelsTransformation(const Params& params);
|
||||
void registerMatcherIn(GraphRewrite& pass, TransformationContext& context) const override;
|
||||
bool transform(TransformationContext& context, ngraph::pattern::Matcher& m) const override;
|
||||
bool isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept override;
|
||||
bool canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> op) const override;
|
||||
};
|
||||
|
||||
} // namespace low_precision
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
|
@ -115,7 +115,7 @@ bool LayerTransformation::canBeTransformed(const TransformationContext& context,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LayerTransformation::canBeTransformedSpecialDimension(const TransformationContext& context, std::shared_ptr<Node> layer) const {
|
||||
bool LayerTransformation::canBeTransformedSpatialDimension(const TransformationContext& context, std::shared_ptr<Node> layer) const {
|
||||
if (!isQuantized(layer)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ bool MatMulTransformation::isPrecisionPreserved(std::shared_ptr<Node> layer) con
|
|||
}
|
||||
|
||||
bool MatMulTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> layer) const {
|
||||
if (!LayerTransformation::canBeTransformedSpecialDimension(context, layer)) {
|
||||
if (!LayerTransformation::canBeTransformedSpatialDimension(context, layer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "low_precision/shuffle_channels.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
|
||||
#include "low_precision/network_helper.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
namespace low_precision {
|
||||
ShuffleChannelsTransformation::ShuffleChannelsTransformation(const Params& params) : LayerTransformation(params) {}
|
||||
|
||||
void ShuffleChannelsTransformation::registerMatcherIn(GraphRewrite& pass, TransformationContext& context) const {
|
||||
addPattern(
|
||||
pass,
|
||||
context,
|
||||
make_op_pattern<opset1::ShuffleChannels>({ make_op_label<opset1::Multiply>() }));
|
||||
}
|
||||
|
||||
bool ShuffleChannelsTransformation::transform(TransformationContext& context, ngraph::pattern::Matcher& m) const {
|
||||
if (!canBeTransformed(context, m.get_match_root())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto shuffleChannels = as_type_ptr<opset1::ShuffleChannels>(NetworkHelper::separateInStandaloneBranch(m.get_match_root()));
|
||||
auto dequantization = NetworkHelper::getDequantization(shuffleChannels);
|
||||
|
||||
const auto shuffleDequantizationConstant = [&](const std::shared_ptr<Node>& eltwise) {
|
||||
const auto normalizedConst = NetworkHelper::normalizeDequantizationShape(eltwise);
|
||||
const auto constShape = normalizedConst->get_shape();
|
||||
|
||||
if (shape_size(constShape) == 1ul) {
|
||||
return NetworkHelper::toScalar(normalizedConst);
|
||||
} else {
|
||||
const size_t normalizedAxis = ngraph::normalize_axis(
|
||||
shuffleChannels->get_friendly_name(),
|
||||
shuffleChannels->get_axis(),
|
||||
shuffleChannels->get_input_partial_shape(0).rank());
|
||||
|
||||
if (constShape[normalizedAxis] == 1ul) {
|
||||
return normalizedConst;
|
||||
} else {
|
||||
const auto group = shuffleChannels->get_group();
|
||||
const auto shuffledConst = fold<ngraph::opset1::ShuffleChannels>(normalizedConst, normalizedAxis, group);
|
||||
return as_type_ptr<opset1::Constant>(shuffledConst);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (dequantization.subtract) {
|
||||
const auto shuffledSubConst = shuffleDequantizationConstant(dequantization.subtract);
|
||||
replace_node(dequantization.subtractConstant, shuffledSubConst);
|
||||
dequantization.subtractConstant = shuffledSubConst;
|
||||
}
|
||||
|
||||
const auto shuffledMulConst = shuffleDequantizationConstant(dequantization.multiply);
|
||||
replace_node(dequantization.multiplyConstant, shuffledMulConst);
|
||||
dequantization.multiplyConstant = shuffledMulConst;
|
||||
|
||||
moveDequantizationAfter(context, shuffleChannels, dequantization, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShuffleChannelsTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> op) const {
|
||||
if (!LayerTransformation::canBeTransformedSpatialDimension(context, op)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto shuffleChannels = as_type_ptr<opset1::ShuffleChannels>(op);
|
||||
if (shuffleChannels == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(shuffleChannels);
|
||||
if (dequantization.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShuffleChannelsTransformation::isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace low_precision
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
#include "low_precision/prelu.hpp"
|
||||
#include "low_precision/reshape.hpp"
|
||||
#include "low_precision/relu.hpp"
|
||||
#include "low_precision/shuffle_channels.hpp"
|
||||
#include "low_precision/squeeze.hpp"
|
||||
#include "low_precision/subtract.hpp"
|
||||
#include "low_precision/split.hpp"
|
||||
|
|
@ -228,6 +229,7 @@ LowPrecisionTransformations LowPrecisionTransformer::getAllTransformations(const
|
|||
add<PReluTransformation, opset1::PRelu>(params).
|
||||
add<ReluTransformation, opset1::Relu>(params).
|
||||
add<ReshapeTransformation, opset1::Reshape>(params).
|
||||
add<ShuffleChannelsTransformation, opset1::ShuffleChannels>(params).
|
||||
add<SqueezeTransformation, opset1::Squeeze>(params).
|
||||
add<SplitTransformation, opset1::Split>(params).
|
||||
add<StridedSliceTransformation, opset1::StridedSlice>(params).
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <transformations/common_optimizations/depth_to_space_fusion.hpp>
|
||||
#include <transformations/common_optimizations/softmax_fusion.hpp>
|
||||
#include <transformations/op_conversions/convert_depth_to_space.hpp>
|
||||
#include <transformations/op_conversions/convert_shuffle_channels3.hpp>
|
||||
#include <transformations/op_conversions/convert_space_to_depth.hpp>
|
||||
#include <transformations/op_conversions/convert_gelu.hpp>
|
||||
#include <transformations/op_conversions/gelu7_downgrade.hpp>
|
||||
|
|
@ -269,6 +270,7 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) {
|
|||
|
||||
// List of enabled/disabled transformations
|
||||
pass_config->disable<ngraph::pass::ConvertGELU>();
|
||||
pass_config->disable<ngraph::pass::ConvertShuffleChannels3>();
|
||||
pass_config->disable<ngraph::pass::Gelu7Downgrade>();
|
||||
pass_config->disable<ngraph::pass::HSwishDecomposition>();
|
||||
pass_config->disable<ngraph::pass::ReduceL1Decomposition>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <transformations_visibility.hpp>
|
||||
|
||||
#include <ngraph/pass/graph_rewrite.hpp>
|
||||
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
|
||||
class TRANSFORMATIONS_API ShuffleChannelsFusion;
|
||||
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
||||
/**
|
||||
* @ingroup ie_transformation_common_api
|
||||
* @brief ShuffleChannelsFusion transformation detects Reshape-Transpose-Reshape pattern
|
||||
* and tries to fuse it into a single ShuffleChannels layer with axis = 1.
|
||||
*
|
||||
* x' = reshape(x, [N, group, C / group, H, W]) or reshape(x, [N, group, C / group, H * W])
|
||||
* x'' = transpose(x', [0, 2, 1, 3, 4]) or transpose(x', [0, 2, 1, 3])
|
||||
* y = reshape(x'', [N, C, H, W])
|
||||
*
|
||||
* @param reshape_constants_check the flag that defines the need for additional checks of reshapes constant
|
||||
* Additional checks are required when ShuffleChannelsFusion using inside offline transformations
|
||||
* and are not necessary when ShuffleChannelsFusion using inside CommonOptimizations
|
||||
*/
|
||||
|
||||
class ngraph::pass::ShuffleChannelsFusion : public ngraph::pass::MatcherPass {
|
||||
public:
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
ShuffleChannelsFusion(const bool reshape_constants_check);
|
||||
};
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
#include "transformations/common_optimizations/clamp_fusion.hpp"
|
||||
#include "transformations/common_optimizations/pad_fusion.hpp"
|
||||
#include "transformations/common_optimizations/eliminate_unsqueeze_gather.hpp"
|
||||
#include "transformations/common_optimizations/shuffle_channels_fusion.hpp"
|
||||
#include "transformations/common_optimizations/softmax_fusion.hpp"
|
||||
#include "transformations/common_optimizations/mvn_fusion.hpp"
|
||||
#include "transformations/common_optimizations/binarize_weights.hpp"
|
||||
|
|
@ -104,6 +105,7 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr<ngraph::
|
|||
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::ShuffleChannelsFusion>(false);
|
||||
common_fusions->add_matcher<ngraph::pass::HSwishFusion>();
|
||||
common_fusions->add_matcher<ngraph::pass::HSigmoidFusion>();
|
||||
common_fusions->add_matcher<ngraph::pass::NormalizeL2Fusion>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "transformations/common_optimizations/shuffle_channels_fusion.hpp"
|
||||
#include "itt.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <ngraph/opsets/opset6.hpp>
|
||||
#include <ngraph/pattern/op/wrap_type.hpp>
|
||||
#include <ngraph/rt_info.hpp>
|
||||
|
||||
bool check_shapes(const ngraph::Shape& shape_input, const ngraph::Shape& shape_reshape_before,
|
||||
const ngraph::AxisVector& transpose_constant_values, const ngraph::Shape& shape_reshape_after) {
|
||||
// x: [N, C, H, W]
|
||||
bool is_transformation_valid = (shape_input.size() == 4);
|
||||
|
||||
// x'= reshape(x, [N, group, C / group, H * W]) or reshape(x, [N, group, C / group, H, W])
|
||||
bool is_reshape_before_valid = (shape_reshape_before.size() == 4 || shape_reshape_before.size() == 5);
|
||||
if (is_reshape_before_valid) {
|
||||
size_t group = shape_reshape_before[1];
|
||||
ngraph::Shape expected_reshape_before = { shape_input[0], group, shape_input[1] / group };
|
||||
|
||||
if (shape_reshape_before.size() == 4) {
|
||||
expected_reshape_before.push_back(shape_input[2] * shape_input[3]);
|
||||
} else {
|
||||
expected_reshape_before.push_back(shape_input[2]);
|
||||
expected_reshape_before.push_back(shape_input[3]);
|
||||
}
|
||||
|
||||
is_reshape_before_valid &= (expected_reshape_before == shape_reshape_before);
|
||||
}
|
||||
|
||||
// x''= transpose(x', [0, 2, 1, 3]) or transpose(x', [0, 2, 1, 3, 4])
|
||||
bool is_transpose_valid = (transpose_constant_values.size() == 4 || transpose_constant_values.size() == 5);
|
||||
if (is_transpose_valid) {
|
||||
ngraph::AxisVector expected_transpose_values{ 0, 2, 1, 3 };
|
||||
if (transpose_constant_values.size() == 5) {
|
||||
expected_transpose_values.push_back(4);
|
||||
}
|
||||
|
||||
is_transpose_valid &= (expected_transpose_values == transpose_constant_values);
|
||||
}
|
||||
|
||||
// y = reshape(x'', [N, C, H, W])
|
||||
bool is_reshape_after_valid = (shape_input == shape_reshape_after);
|
||||
|
||||
is_transformation_valid &= is_reshape_before_valid & is_transpose_valid & is_reshape_after_valid;
|
||||
return is_transformation_valid;
|
||||
}
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(ngraph::pass::ShuffleChannelsFusion, "ShuffleChannelsFusion", 0);
|
||||
|
||||
ngraph::pass::ShuffleChannelsFusion::ShuffleChannelsFusion(const bool reshape_constants_check) {
|
||||
MATCHER_SCOPE(ShuffleChannelsFusion);
|
||||
auto input = ngraph::pattern::any_input(pattern::has_static_shape());
|
||||
auto reshape_before_const_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Constant>();
|
||||
auto transpose_const_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Constant>();
|
||||
auto reshape_after_const_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Constant>();
|
||||
|
||||
auto has_static_shape_and_single_consumer = [](const Output<Node>& output) {
|
||||
return pattern::has_static_shape()(output) && pattern::consumers_count(1)(output);
|
||||
};
|
||||
auto reshape_before_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Reshape>({input, reshape_before_const_pattern},
|
||||
has_static_shape_and_single_consumer);
|
||||
auto transpose_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Transpose>({reshape_before_pattern, transpose_const_pattern},
|
||||
has_static_shape_and_single_consumer);
|
||||
auto reshape_after_pattern = ngraph::pattern::wrap_type<ngraph::opset6::Reshape>({transpose_pattern, reshape_after_const_pattern},
|
||||
pattern::has_static_shape());
|
||||
|
||||
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
|
||||
const auto& pattern_map = m.get_pattern_value_map();
|
||||
|
||||
auto data = pattern_map.at(input);
|
||||
auto reshape_before = std::dynamic_pointer_cast<ngraph::opset6::Reshape>(pattern_map.at(reshape_before_pattern).get_node_shared_ptr());
|
||||
auto transpose = std::dynamic_pointer_cast<ngraph::opset6::Transpose>(pattern_map.at(transpose_pattern).get_node_shared_ptr());
|
||||
auto reshape_after = std::dynamic_pointer_cast<ngraph::opset6::Reshape>(pattern_map.at(reshape_after_pattern).get_node_shared_ptr());
|
||||
if (!reshape_after || !transpose || !reshape_after)
|
||||
return false;
|
||||
|
||||
if (reshape_constants_check) {
|
||||
auto reshape_before_constant = std::dynamic_pointer_cast<ngraph::opset6::Constant>(
|
||||
pattern_map.at(reshape_before_const_pattern).get_node_shared_ptr());
|
||||
auto reshape_after_constant = std::dynamic_pointer_cast<ngraph::opset6::Constant>(
|
||||
pattern_map.at(reshape_after_const_pattern).get_node_shared_ptr());
|
||||
|
||||
if (!reshape_before_constant || !reshape_after_constant)
|
||||
return false;
|
||||
|
||||
const auto& reshape_before_values = reshape_before_constant->cast_vector<int64_t>();
|
||||
const auto& reshape_after_values = reshape_after_constant->cast_vector<int64_t>();
|
||||
if (std::any_of(reshape_before_values.cbegin(), reshape_before_values.cend(), [](const int64_t& value) { return value == -1; }) ||
|
||||
std::any_of(reshape_after_values.cbegin(), reshape_after_values.cend(), [](const int64_t& value) { return value == -1; })) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto shape_input = reshape_before->get_input_shape(0);
|
||||
auto shape_reshape_before = reshape_before->get_output_shape(0);
|
||||
auto shape_reshape_after = reshape_after->get_output_shape(0);
|
||||
|
||||
auto transpose_constant = std::dynamic_pointer_cast<ngraph::opset6::Constant>(pattern_map.at(transpose_const_pattern).get_node_shared_ptr());
|
||||
auto transpose_constant_values = transpose_constant->get_axis_vector_val();
|
||||
if (!check_shapes(shape_input, shape_reshape_before, transpose_constant_values, shape_reshape_after))
|
||||
return false;
|
||||
|
||||
int64_t axis = 1ul;
|
||||
int64_t group = shape_reshape_before[1];
|
||||
|
||||
auto shuffle_shannels = std::make_shared<ngraph::opset6::ShuffleChannels>(data, axis, group);
|
||||
shuffle_shannels->set_friendly_name(reshape_after->get_friendly_name());
|
||||
ngraph::copy_runtime_info({ reshape_before, transpose, reshape_after }, shuffle_shannels);
|
||||
ngraph::replace_node(reshape_after, shuffle_shannels);
|
||||
return true;
|
||||
};
|
||||
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(reshape_after_pattern, matcher_name);
|
||||
register_matcher(m, callback);
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "layer_transformation.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <transformations/utils/utils.hpp>
|
||||
#include <low_precision/shuffle_channels.hpp>
|
||||
|
||||
#include "common_test_utils/ngraph_test_utils.hpp"
|
||||
#include "simple_low_precision_transformer.hpp"
|
||||
#include "lpt_ngraph_functions/shuffle_channels_function.hpp"
|
||||
#include "lpt_ngraph_functions/common/dequantization_operations.hpp"
|
||||
|
||||
namespace {
|
||||
using namespace testing;
|
||||
using namespace ngraph::pass;
|
||||
|
||||
class ShuffleChannelsTransformationTestValues {
|
||||
public:
|
||||
public:
|
||||
class Actual {
|
||||
public:
|
||||
ngraph::element::Type inputPrecision;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantization;
|
||||
};
|
||||
|
||||
class Expected {
|
||||
public:
|
||||
ngraph::element::Type inputPrecision;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationBefore;
|
||||
ngraph::element::Type preicsionAfterOperation;
|
||||
ngraph::builder::subgraph::DequantizationOperations dequantizationAfter;
|
||||
};
|
||||
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
std::int64_t axis;
|
||||
std::int64_t group;
|
||||
Actual actual;
|
||||
Expected expected;
|
||||
};
|
||||
|
||||
typedef std::tuple<
|
||||
ngraph::Shape,
|
||||
ShuffleChannelsTransformationTestValues> ShuffleChannelsTransformationParams;
|
||||
|
||||
class ShuffleChannelsTransformation : public LayerTransformation, public testing::WithParamInterface<ShuffleChannelsTransformationParams> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
ngraph::Shape inputShape = std::get<0>(GetParam());
|
||||
ShuffleChannelsTransformationTestValues testValues = std::get<1>(GetParam());
|
||||
|
||||
actualFunction = ngraph::builder::subgraph::ShuffleChannelsFunction::getOriginal(
|
||||
testValues.actual.inputPrecision,
|
||||
inputShape,
|
||||
testValues.actual.dequantization,
|
||||
testValues.axis,
|
||||
testValues.group);
|
||||
|
||||
SimpleLowPrecisionTransformer transform;
|
||||
transform.add<ngraph::pass::low_precision::ShuffleChannelsTransformation, ngraph::opset1::ShuffleChannels>(testValues.params);
|
||||
transform.transform(actualFunction);
|
||||
|
||||
referenceFunction = ngraph::builder::subgraph::ShuffleChannelsFunction::getReference(
|
||||
testValues.expected.inputPrecision,
|
||||
inputShape,
|
||||
testValues.expected.dequantizationBefore,
|
||||
testValues.axis,
|
||||
testValues.group,
|
||||
testValues.expected.preicsionAfterOperation,
|
||||
testValues.expected.dequantizationAfter);
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(testing::TestParamInfo<ShuffleChannelsTransformationParams> obj) {
|
||||
ngraph::Shape inputShape = std::get<0>(obj.param);
|
||||
ShuffleChannelsTransformationTestValues testValues = std::get<1>(obj.param);
|
||||
|
||||
std::ostringstream result;
|
||||
result <<
|
||||
LayerTransformation::getTestCaseNameByParams(testValues.actual.inputPrecision, inputShape, testValues.params) << "_" <<
|
||||
testValues.actual.dequantization << "_axis_" <<
|
||||
testValues.axis << "_group_" << testValues.group;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(ShuffleChannelsTransformation, CompareFunctions) {
|
||||
actualFunction->validate_nodes_and_infer_types();
|
||||
auto res = compare_functions(referenceFunction, actualFunction, true, true);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
}
|
||||
|
||||
const std::vector<ngraph::Shape> inputShapes = {
|
||||
{ 1, 3, 8, 10 },
|
||||
{ 4, 3, 8, 10 },
|
||||
};
|
||||
|
||||
const std::vector<ShuffleChannelsTransformationTestValues> testValues = {
|
||||
// U8 per tensor quantization
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
1, // axis
|
||||
1, // group
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {128.f}, {0.02f}}
|
||||
},
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{},
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {128.f}, {0.02f}}
|
||||
}
|
||||
},
|
||||
// U8 per channel quantization
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
1,
|
||||
1,
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
},
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{},
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
}
|
||||
},
|
||||
// U8 quantization by special dimension, shuffling by the same dimension
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
2,
|
||||
4,
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{
|
||||
{ngraph::element::f32},
|
||||
{{121.f, 122.f, 123.f, 124.f, 125.f, 126.f, 127.f, 128.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}},
|
||||
{{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}}
|
||||
}
|
||||
},
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{},
|
||||
ngraph::element::u8,
|
||||
{
|
||||
{ngraph::element::f32},
|
||||
{{121.f, 123.f, 125.f, 127.f, 122.f, 124.f, 126.f, 128.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}},
|
||||
{{1.f, 3.f, 5.f, 7.f, 2.f, 4.f, 6.f, 8.f}, ngraph::element::f32, ngraph::Shape {1, 1, 8, 1}},
|
||||
}
|
||||
}
|
||||
},
|
||||
// U8 per channel quantization, shuffling by special dimension
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
-2,
|
||||
4,
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
},
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{},
|
||||
ngraph::element::u8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
}
|
||||
},
|
||||
// I8 per tensor quantization
|
||||
{
|
||||
LayerTransformation::createParamsI8I8(),
|
||||
1,
|
||||
1,
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {128.f}, {0.02f}}
|
||||
},
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{},
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {128.f}, {0.02f}}
|
||||
}
|
||||
},
|
||||
// I8 per channel quantization
|
||||
{
|
||||
LayerTransformation::createParamsI8I8(),
|
||||
1,
|
||||
1,
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
},
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{},
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
}
|
||||
},
|
||||
// I8 quantization by special dimension, shuffling by the same dimension
|
||||
{
|
||||
LayerTransformation::createParamsI8I8(),
|
||||
2,
|
||||
4,
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{
|
||||
{ngraph::element::f32},
|
||||
{{121.f, 122.f, 123.f, 124.f, 125.f, 126.f, 127.f, 128.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}},
|
||||
{{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}}
|
||||
}
|
||||
},
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{},
|
||||
ngraph::element::i8,
|
||||
{
|
||||
{ngraph::element::f32},
|
||||
{{121.f, 123.f, 125.f, 127.f, 122.f, 124.f, 126.f, 128.f}, ngraph::element::f32, ngraph::Shape{1, 1, 8, 1}},
|
||||
{{1.f, 3.f, 5.f, 7.f, 2.f, 4.f, 6.f, 8.f}, ngraph::element::f32, ngraph::Shape {1, 1, 8, 1}},
|
||||
}
|
||||
}
|
||||
},
|
||||
// I8 per channel quantization, shuffling by special dimension
|
||||
{
|
||||
LayerTransformation::createParamsI8I8(),
|
||||
-2,
|
||||
4,
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
},
|
||||
{
|
||||
ngraph::element::i8,
|
||||
{},
|
||||
ngraph::element::i8,
|
||||
{{ngraph::element::f32}, {{128.f, 64.f, 32.f}}, {{0.01f, 0.02f, 0.03f}}}
|
||||
}
|
||||
},
|
||||
// U8 per tensor quantization, not update precision
|
||||
{
|
||||
LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
|
||||
3,
|
||||
5,
|
||||
{
|
||||
ngraph::element::f32,
|
||||
{{}, {128.f}, {0.02f}}
|
||||
},
|
||||
{
|
||||
ngraph::element::f32,
|
||||
{},
|
||||
ngraph::element::f32,
|
||||
{{}, {128.f}, {0.02f}}
|
||||
}
|
||||
},
|
||||
// U8 without dequantization operations
|
||||
{
|
||||
LayerTransformation::createParamsU8I8(),
|
||||
2,
|
||||
4,
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{{}, {}, {}}
|
||||
},
|
||||
{
|
||||
ngraph::element::u8,
|
||||
{},
|
||||
ngraph::element::u8,
|
||||
{{}, {}, {}}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
smoke_LPT,
|
||||
ShuffleChannelsTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(inputShapes),
|
||||
::testing::ValuesIn(testValues)),
|
||||
ShuffleChannelsTransformation::getTestCaseName);
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common_test_utils/test_common.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <ngraph/function.hpp>
|
||||
#include <ngraph/opsets/opset6.hpp>
|
||||
#include <transformations/common_optimizations/shuffle_channels_fusion.hpp>
|
||||
#include <transformations/init_node_info.hpp>
|
||||
#include <ngraph/pass/manager.hpp>
|
||||
|
||||
#include "common_test_utils/ngraph_test_utils.hpp"
|
||||
|
||||
namespace {
|
||||
using namespace testing;
|
||||
using namespace ngraph;
|
||||
|
||||
class ShuffleChannelsFusionTestValues {
|
||||
public:
|
||||
bool dynamicShape;
|
||||
std::vector<int64_t> reshape_before_val;
|
||||
std::vector<size_t> transpose_val;
|
||||
std::vector<int64_t> reshape_after_val;
|
||||
size_t batch_size;
|
||||
bool check_reshape_values;
|
||||
bool fuse_happened;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& values) {
|
||||
os << "{ ";
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
os << values[i];
|
||||
if (i != (values.size() - 1ul)) {
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
os << " }";
|
||||
return os;
|
||||
}
|
||||
|
||||
class ShuffleChannelsFusion : public ::testing::Test, public testing::WithParamInterface<ShuffleChannelsFusionTestValues> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const auto values = GetParam();
|
||||
{
|
||||
const PartialShape inputPartialShape = values.dynamicShape ? PartialShape::dynamic() : Shape{ values.batch_size, 128, 720, 480 };
|
||||
auto input0 = std::make_shared<opset6::Parameter>(element::f32, inputPartialShape);
|
||||
auto shape_reshape_before = opset6::Constant::create(element::i64, Shape{ values.reshape_before_val.size() }, values.reshape_before_val);
|
||||
auto permutation = opset6::Constant::create(element::i64, Shape{ values.transpose_val.size() }, values.transpose_val);
|
||||
auto shape_reshape_after = opset6::Constant::create(element::i64, Shape{ values.reshape_after_val.size() }, values.reshape_after_val);
|
||||
|
||||
auto reshape_before = std::make_shared<ngraph::opset6::Reshape>(input0, shape_reshape_before, false);
|
||||
auto permute = std::make_shared<ngraph::opset6::Transpose>(reshape_before, permutation);
|
||||
auto reshape_after = std::make_shared<ngraph::opset6::Reshape>(permute, shape_reshape_after, false);
|
||||
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{ reshape_after }, ngraph::ParameterVector{ input0 });
|
||||
|
||||
ngraph::pass::Manager manager;
|
||||
auto pass_config = manager.get_pass_config();
|
||||
manager.register_pass<ngraph::pass::InitNodeInfo>();
|
||||
manager.register_pass<ngraph::pass::ShuffleChannelsFusion>(values.check_reshape_values);
|
||||
manager.run_passes(f);
|
||||
ASSERT_NO_THROW(check_rt_info(f));
|
||||
}
|
||||
|
||||
if (values.fuse_happened) {
|
||||
auto input0 = std::make_shared<ngraph::opset6::Parameter>(ngraph::element::f32, ngraph::Shape{ values.batch_size, 128, 720, 480 });
|
||||
auto shuffle_channels = std::make_shared<ngraph::opset6::ShuffleChannels>(input0, 1, values.reshape_before_val[1]);
|
||||
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{ shuffle_channels }, ngraph::ParameterVector{ input0 });
|
||||
} else {
|
||||
f_ref = f;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(testing::TestParamInfo<ShuffleChannelsFusionTestValues> obj) {
|
||||
const ShuffleChannelsFusionTestValues testValues = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
if (testValues.dynamicShape) {
|
||||
result << "_dynamic_shape_";
|
||||
} else {
|
||||
result << "_batch_size_" << testValues.batch_size;
|
||||
}
|
||||
|
||||
result << "_before_" << testValues.reshape_before_val
|
||||
<< "_transpose_" << testValues.transpose_val << "_after_" << testValues.reshape_after_val
|
||||
<< (testValues.check_reshape_values ? "check_reshape_values" : "");
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ngraph::Function> f;
|
||||
std::shared_ptr<ngraph::Function> f_ref;
|
||||
};
|
||||
|
||||
TEST_P(ShuffleChannelsFusion, CompareFunctions) {
|
||||
auto res = compare_functions(f, f_ref);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
}
|
||||
|
||||
const std::vector<ShuffleChannelsFusionTestValues> testValues = {
|
||||
{ true, {1, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, 128, 720, 480}, 1, false, false },
|
||||
{ false, {1, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, 128, 720, 480}, 1, false, true },
|
||||
{ false, {1, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, 128, 720, 480}, 1, true, true },
|
||||
{ false, {1, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, -1, 720, 480}, 1, false, true },
|
||||
{ false, {4, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, -1, 720, 480}, 4, false, false },
|
||||
{ false, {1, 2, 64, 720, 480}, {0, 2, 1, 3, 4}, {1, -1, 720, 480}, 1, true, false },
|
||||
{ true, {1, 4, 32, 720 * 480}, {0, 2, 1, 3}, {1, 128, 720, 480}, 1, false, false },
|
||||
{ false, {1, 4, 32, 720 * 480}, {0, 2, 1, 3}, {1, 128, 720, 480}, 1, false, true },
|
||||
{ false, {1, 2, 64, 720 * 480}, {0, 2, 1, 3}, {1, 128, 720, 480}, 1, true, true },
|
||||
{ false, {1, 2, 64, 720 * 480}, {0, 2, 1, 3}, {1, -1, 720, 480}, 1, false, true },
|
||||
{ false, {4, 2, 64, 720 * 480}, {0, 2, 1, 3}, {1, -1, 720, 480}, 4, false, false },
|
||||
{ false, {1, 2, 64, 720 * 480}, {0, 2, 1, 3}, {1, -1, 720, 480}, 1, true, false },
|
||||
};
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TransformationTests,
|
||||
ShuffleChannelsFusion,
|
||||
::testing::ValuesIn(testValues),
|
||||
ShuffleChannelsFusion::getTestCaseName);
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "low_precision_transformations/shuffle_channels_transformation.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
const std::vector<ngraph::element::Type> netPrecisions = {
|
||||
ngraph::element::f32,
|
||||
// ngraph::element::f16
|
||||
};
|
||||
|
||||
const std::vector<ngraph::Shape> inputShapes = {
|
||||
{ 1, 3, 16, 16 },
|
||||
{ 4, 3, 16, 16 }
|
||||
};
|
||||
|
||||
const std::vector<ngraph::pass::low_precision::LayerTransformation::Params> trasformationParamValues = {
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(true),
|
||||
};
|
||||
|
||||
const std::vector<LayerTestsDefinitions::ShuffleChannelsTransformationParam> params = {
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
0,
|
||||
1,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
-3,
|
||||
1,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ 0.f, 0.f, 0.f },
|
||||
{ 25.5f / 2.f, 25.5f / 4.f, 25.5f }
|
||||
},
|
||||
-3,
|
||||
1,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ -4.f, -3.f, 0.f },
|
||||
{ 10.f, 12.f, 25.5f }
|
||||
},
|
||||
-3,
|
||||
1,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
2,
|
||||
4,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ 0.f, 0.f, 0.f },
|
||||
{ 25.5f / 2.f, 25.5f / 4.f, 25.5f }
|
||||
},
|
||||
-1,
|
||||
8,
|
||||
"output_original",
|
||||
"U8"
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke_LPT, ShuffleChannelsTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::ValuesIn(inputShapes),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU),
|
||||
::testing::ValuesIn(trasformationParamValues),
|
||||
::testing::ValuesIn(params)),
|
||||
ShuffleChannelsTransformation::getTestCaseName);
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "low_precision_transformations/shuffle_channels_transformation.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
const std::vector<ngraph::element::Type> netPrecisions = {
|
||||
ngraph::element::f32,
|
||||
ngraph::element::f16
|
||||
};
|
||||
|
||||
const std::vector<ngraph::Shape> inputShapes = {
|
||||
{ 1, 3, 16, 16 }
|
||||
};
|
||||
|
||||
const std::vector<ngraph::pass::low_precision::LayerTransformation::Params> trasformationParamValues = {
|
||||
LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams(),
|
||||
};
|
||||
|
||||
const std::vector<LayerTestsDefinitions::ShuffleChannelsTransformationParam> params = {
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
0,
|
||||
1,
|
||||
},
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
-3,
|
||||
1,
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ 0.f, 0.f, 0.f },
|
||||
{ 25.5f / 2.f, 25.5f / 4.f, 25.5f }
|
||||
},
|
||||
-3,
|
||||
1,
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ -4.f, -3.f, 0.f },
|
||||
{ 10.f, 12.f, 25.5f }
|
||||
},
|
||||
-3,
|
||||
1,
|
||||
},
|
||||
{
|
||||
{ 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } },
|
||||
2,
|
||||
4,
|
||||
},
|
||||
{
|
||||
{
|
||||
256ul,
|
||||
ngraph::Shape { 1, 3, 1, 1 },
|
||||
{ 0.f },
|
||||
{ 25.5f },
|
||||
{ 0.f, 0.f, 0.f },
|
||||
{ 25.5f / 2.f, 25.5f / 4.f, 25.5f }
|
||||
},
|
||||
-1,
|
||||
8,
|
||||
},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke_LPT, ShuffleChannelsTransformation,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::ValuesIn(inputShapes),
|
||||
::testing::Values(CommonTestUtils::DEVICE_GPU),
|
||||
::testing::ValuesIn(trasformationParamValues),
|
||||
::testing::ValuesIn(params)),
|
||||
ShuffleChannelsTransformation::getTestCaseName);
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "shared_test_classes/base/low_precision_transformations/layer_transformation.hpp"
|
||||
#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
class ShuffleChannelsTransformationParam {
|
||||
public:
|
||||
ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantizeOnData;
|
||||
std::int64_t axis;
|
||||
std::int64_t group;
|
||||
std::string layerName;
|
||||
std::string expectedKernelType;
|
||||
};
|
||||
|
||||
typedef std::tuple<
|
||||
ngraph::element::Type,
|
||||
ngraph::Shape,
|
||||
std::string,
|
||||
ngraph::pass::low_precision::LayerTransformation::Params,
|
||||
ShuffleChannelsTransformationParam
|
||||
> ShuffleChannelsTransformationParams;
|
||||
|
||||
class ShuffleChannelsTransformation :
|
||||
public testing::WithParamInterface<ShuffleChannelsTransformationParams>,
|
||||
public LayerTestsUtils::LayerTransformation {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<ShuffleChannelsTransformationParams> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void Run() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "low_precision_transformations/shuffle_channels_transformation.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <ie_core.hpp>
|
||||
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
#include "functional_test_utils/plugin_cache.hpp"
|
||||
#include "shared_test_classes/base/layer_test_utils.hpp"
|
||||
#include "lpt_ngraph_functions/shuffle_channels_function.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::string ShuffleChannelsTransformation::getTestCaseName(testing::TestParamInfo<ShuffleChannelsTransformationParams> obj) {
|
||||
ngraph::element::Type netPrecision;
|
||||
ngraph::Shape inputShape;
|
||||
std::string targetDevice;
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
ShuffleChannelsTransformationParam param;
|
||||
std::tie(netPrecision, inputShape, targetDevice, params, param) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
result << getTestCaseNameByParams(netPrecision, inputShape, targetDevice, params) << "_" <<
|
||||
param.fakeQuantizeOnData << "_axis_" << param.axis << "_group_" << param.group;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void ShuffleChannelsTransformation::SetUp() {
|
||||
ngraph::element::Type netPrecision;
|
||||
ngraph::Shape inputShape;
|
||||
ngraph::pass::low_precision::LayerTransformation::Params params;
|
||||
ShuffleChannelsTransformationParam param;
|
||||
std::tie(netPrecision, inputShape, targetDevice, params, param) = this->GetParam();
|
||||
|
||||
function = ngraph::builder::subgraph::ShuffleChannelsFunction::getOriginal(
|
||||
netPrecision,
|
||||
inputShape,
|
||||
param.fakeQuantizeOnData,
|
||||
param.axis,
|
||||
param.group);
|
||||
}
|
||||
|
||||
void ShuffleChannelsTransformation::Run() {
|
||||
LayerTestsCommon::Run();
|
||||
|
||||
const auto params = std::get<4>(GetParam());
|
||||
const auto actualType = getRuntimePrecision(params.layerName);
|
||||
EXPECT_EQ(actualType, params.expectedKernelType);
|
||||
}
|
||||
|
||||
TEST_P(ShuffleChannelsTransformation, CompareWithRefImpl) {
|
||||
Run();
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#include <low_precision/layer_transformation.hpp>
|
||||
|
||||
#include "lpt_ngraph_functions/common/dequantization_operations.hpp"
|
||||
#include "lpt_ngraph_functions/common/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
|
||||
class ShuffleChannelsFunction {
|
||||
public:
|
||||
static std::shared_ptr<ngraph::Function> getOriginal(
|
||||
const ngraph::element::Type inputPrecision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& deqBefore,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getOriginal(
|
||||
const ngraph::element::Type inputPrecision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::FakeQuantizeOnData& fqOnData,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group);
|
||||
|
||||
static std::shared_ptr<ngraph::Function> getReference(
|
||||
const ngraph::element::Type inputPrecision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& deqBefore,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group,
|
||||
const ngraph::element::Type precisionAfterOperation,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& deqAfter);
|
||||
};
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
|
||||
#include "low_precision/network_helper.hpp"
|
||||
#include "lpt_ngraph_functions/common/builders.hpp"
|
||||
|
||||
#include "lpt_ngraph_functions/shuffle_channels_function.hpp"
|
||||
#include "ngraph_functions/subgraph_builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
namespace subgraph {
|
||||
std::shared_ptr<Function> ShuffleChannelsFunction::getOriginal(
|
||||
const element::Type inputPrecision,
|
||||
const Shape& inputShape,
|
||||
const builder::subgraph::DequantizationOperations& deqBefore,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group) {
|
||||
const auto input = std::make_shared<opset1::Parameter>(inputPrecision, inputShape);
|
||||
const auto dequantization = makeDequantization(input, deqBefore);
|
||||
|
||||
const auto shuffleChannels = std::make_shared<opset1::ShuffleChannels>(dequantization, axis, group);
|
||||
shuffleChannels->set_friendly_name("output");
|
||||
|
||||
const auto function = std::make_shared<ngraph::Function>(
|
||||
ResultVector{ std::make_shared<opset1::Result>(shuffleChannels) },
|
||||
ParameterVector{ input },
|
||||
"ShuffleChannelsFunction");
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> ShuffleChannelsFunction::getOriginal(
|
||||
const ngraph::element::Type inputPrecision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::FakeQuantizeOnData& fqOnData,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group) {
|
||||
const auto input = std::make_shared<opset1::Parameter>(inputPrecision, inputShape);
|
||||
const auto fakeQuantize = makeFakeQuantize(input, inputPrecision, fqOnData);
|
||||
|
||||
const auto shuffleChannels = std::make_shared<opset1::ShuffleChannels>(fakeQuantize, axis, group);
|
||||
shuffleChannels->set_friendly_name("output");
|
||||
|
||||
const auto function = std::make_shared<ngraph::Function>(
|
||||
ResultVector{ std::make_shared<opset1::Result>(shuffleChannels) },
|
||||
ParameterVector{ input },
|
||||
"ShuffleChannelsFunction");
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Function> ShuffleChannelsFunction::getReference(
|
||||
const ngraph::element::Type inputPrecision,
|
||||
const ngraph::Shape& inputShape,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& deqBefore,
|
||||
const std::int64_t axis,
|
||||
const std::int64_t group,
|
||||
const ngraph::element::Type precisionAfterOperation,
|
||||
const ngraph::builder::subgraph::DequantizationOperations& deqAfter) {
|
||||
const auto input = std::make_shared<opset1::Parameter>(inputPrecision, inputShape);
|
||||
const auto dequantizationBefore = makeDequantization(input, deqBefore);
|
||||
|
||||
const auto shuffleChannels = std::make_shared<opset1::ShuffleChannels>(dequantizationBefore, axis, group);
|
||||
ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(shuffleChannels, precisionAfterOperation);
|
||||
|
||||
const auto dequantizationAfter = makeDequantization(shuffleChannels, deqAfter);
|
||||
dequantizationAfter->set_friendly_name("output");
|
||||
|
||||
const auto function = std::make_shared<ngraph::Function>(
|
||||
ResultVector{ std::make_shared<opset1::Result>(dequantizationAfter) },
|
||||
ParameterVector{ input },
|
||||
"ShuffleChannelsFunction");
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
} // namespace subgraph
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
|
|
@ -19,8 +19,8 @@ namespace ngraph
|
|||
class NGRAPH_API ShuffleChannels : public Op
|
||||
{
|
||||
public:
|
||||
static constexpr NodeTypeInfo type_info{"ShuffleChannels", 0};
|
||||
const NodeTypeInfo& get_type_info() const override { return type_info; }
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
|
||||
ShuffleChannels() = default;
|
||||
/// \brief Constructs a ShuffleChannels node.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
constexpr NodeTypeInfo op::ShuffleChannels::type_info;
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(op::v0::ShuffleChannels, "ShuffleChannels", 0);
|
||||
|
||||
op::ShuffleChannels::ShuffleChannels(const Output<Node>& data,
|
||||
const int64_t axis,
|
||||
|
|
|
|||
Loading…
Reference in New Issue