ShuffleChannels ng op and reference implementation revision (#5764)

* Unblock shuffle channels tests from ie test manifest

* Add more backend tests

* ShiffleChannel reference impl update

* Update attr visitor test

* Remove unused get_pre_shuffle_shape helper function

* Update class descriprion

* Add type prop shape tests

* Remove NGRAPH_SUPPRESS_DEPRECATED macro

* Add single layer tests

* Update layer tests

* Remove unused header

* Move implementation to cpp file
This commit is contained in:
Katarzyna Mitrus 2021-06-15 06:04:06 +02:00 committed by GitHub
parent f8759e1982
commit 8dff04df28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 508 additions and 155 deletions

View File

@ -36,4 +36,65 @@ INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels4D, ShuffleChannelsLayerTest,
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
// ND support tests
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels6D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(2, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({24, 6, 12, 18, 30, 36})),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels5D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(2, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({6, 12, 18, 30, 36})),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels3D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(1, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({18, 30, 36})),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels2D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(1, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({18, 30})),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels1D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(0, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({30})),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
ShuffleChannelsLayerTest::getTestCaseName);
} // namespace

View File

@ -35,3 +35,40 @@ const auto testCases = ::testing::Combine(::testing::ValuesIn(shuffleParameters)
INSTANTIATE_TEST_CASE_P(smoke_GPU_ShuffleChannels, ShuffleChannelsLayerTest, testCases, ShuffleChannelsLayerTest::getTestCaseName);
// ND support tests
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels3D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(1, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({18, 30, 36})),
::testing::Values(CommonTestUtils::DEVICE_GPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels2D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(1, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({18, 30})),
::testing::Values(CommonTestUtils::DEVICE_GPU)),
ShuffleChannelsLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels1D, ShuffleChannelsLayerTest,
::testing::Combine(
::testing::Values(std::tuple<int, int>(0, 3)),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(std::vector<size_t >({30})),
::testing::Values(CommonTestUtils::DEVICE_GPU)),
ShuffleChannelsLayerTest::getTestCaseName);

View File

@ -24,14 +24,12 @@ namespace ngraph
ShuffleChannels() = default;
/// \brief Constructs a ShuffleChannels node.
///
/// \param data - Node producing the input tensor
/// \param axis - channel dimension index in the data tensor. A negative value means
/// that the index should be calculated from the back of the input
/// data
/// shape.
/// \param group - number of group the channel dimension specified by axis should
/// be
/// split into
/// \param data Node producing the input tensor.
/// \param axis Channel dimension index in the data tensor.
/// A negative value means that the index should be
/// calculated from the back of the input data shape.
/// \param group Number of group the channel dimension should be split into.
///
ShuffleChannels(const Output<Node>& data,
const int64_t axis = 1,
const int64_t group = 1);
@ -51,11 +49,6 @@ namespace ngraph
bool has_evaluate() const override;
private:
/// \brief Generates a shape required to permute the data
///
/// \param data_shape - Shape of the original input data tensor
/// \return A 4D tensor to be used to reshape the input data before shuffling it
Shape get_pre_shuffle_shape(const Shape& data_shape) const;
bool evaluate_shuffle_channels(const HostTensorVector& outputs,
const HostTensorVector& inputs) const;

View File

@ -0,0 +1,27 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cmath>
#include <numeric>
#include <vector>
#include "ngraph/shape.hpp"
namespace ngraph
{
namespace runtime
{
namespace reference
{
void shuffle_channels(const char* arg,
char* out,
const Shape& data_shape,
size_t elem_size,
const int64_t axis,
const int64_t group);
} // namespace reference
} // namespace runtime
} // namespace ngraph

View File

@ -0,0 +1,60 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/runtime/reference/shuffle_channels.hpp"
#include "ngraph/runtime/opt_kernel/reshape.hpp"
namespace ngraph
{
namespace runtime
{
namespace reference
{
void shuffle_channels(const char* arg,
char* out,
const Shape& data_shape,
size_t elem_size,
const int64_t axis,
const int64_t group)
{
// Input ND tensor of data_shape (ds) is always considered as 4D tensor with the
// following shape:
// dim 0: ds[0] * ds[1] * ... * ds[axis-1] (or 1 if axis == 0)
// dim 1: group
// dim 2: ds[axis] / group
// dim 3: ds[axis+1] * ds[axis+2] * ... * ds[ds.size()-1]
// (or 1 if axis points to last dimension)
// The representation of ND tensor as 4D tensor doesn't affect flat data order
Shape reshaped_input_shape(4, 1);
const size_t axis_zb =
axis >= 0 ? axis : axis + data_shape.size(); // Allow negative indices
for (size_t i = 0; i < axis_zb; ++i)
{
// All dimensions before input channels dim axis
reshaped_input_shape[0] *= data_shape[i];
}
reshaped_input_shape[1] = group;
reshaped_input_shape[2] = data_shape[axis_zb] / group;
for (size_t i = axis_zb + 1; i < data_shape.size(); ++i)
{
// All dimensions after input channels dim axis
reshaped_input_shape[3] *= data_shape[i];
}
// The two dimensions in the middle are swapped
const Shape transposed_shape{reshaped_input_shape[0],
reshaped_input_shape[2],
reshaped_input_shape[1],
reshaped_input_shape[3]};
AxisVector axis_vector{0, 2, 1, 3};
runtime::opt_kernel::reshape(
arg, out, reshaped_input_shape, axis_vector, transposed_shape, elem_size);
// Reshaped 4D tensor is interpreted as ND output tensor with original shape of data
// input
}
} // namespace reference
} // namespace runtime
} // namespace ngraph

View File

@ -10,14 +10,13 @@
#include "ngraph/op/shuffle_channels.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/runtime/opt_kernel/reshape.hpp"
#include "ngraph/runtime/reference/shuffle_channels.hpp"
#include "ngraph/type/element_type.hpp"
#include "ngraph/type/element_type_traits.hpp"
using namespace std;
using namespace ngraph;
NGRAPH_SUPPRESS_DEPRECATED_START
NGRAPH_RTTI_DEFINITION(op::v0::ShuffleChannels, "ShuffleChannels", 0);
op::ShuffleChannels::ShuffleChannels(const Output<Node>& data,
@ -87,7 +86,8 @@ void op::ShuffleChannels::validate_and_infer_types()
}
else
{
set_output_type(0, data_type, PartialShape::dynamic());
const auto shape = get_input_partial_shape(0);
set_output_type(0, data_type, shape);
}
}
@ -103,76 +103,19 @@ shared_ptr<Node> op::ShuffleChannels::clone_with_new_inputs(const OutputVector&
return make_shared<ShuffleChannels>(new_args.at(0), m_axis, m_group);
}
Shape op::ShuffleChannels::get_pre_shuffle_shape(const Shape& data_shape) const
{
const Shape& ds = data_shape;
// in general the resulting shape should contain the following values:
// [0]: ds[0] * ds[1] * ... * ds[m_axis-1] (or 1 if m_axis == 0)
// [1]: m_group
// [2]: ds[axis] / m_group
// [3]: ds[axis+1] * ds[axis+2] * ... * ds[ds.size()-1] (or 1 if m_axis points to the last elem
// of ds)
Shape res(4, 1);
size_t axis_zb = get_zero_based_axis();
for (size_t i = 0; i < axis_zb; ++i)
{
res[0] *= ds[i];
}
res[1] = m_group;
res[2] = ds[axis_zb] / m_group;
for (size_t i = axis_zb + 1; i < ds.size(); ++i)
{
res[3] *= ds[i];
}
return res;
}
bool op::ShuffleChannels::evaluate_shuffle_channels(const HostTensorVector& outputs,
const HostTensorVector& inputs) const
{
const auto arg = inputs[0]->get_data_ptr<const char>();
auto out = outputs[0]->get_data_ptr<char>();
Shape data_shape = inputs[0]->get_shape();
const Shape& ds = data_shape;
size_t elem_size = inputs[0]->get_element_type().size();
const auto data_shape = inputs[0]->get_shape();
const size_t elem_size = inputs[0]->get_element_type().size();
Shape reshaped_out_shape(4, 1);
size_t axis_zb = m_axis >= 0 ? m_axis : m_axis + data_shape.size();
for (size_t i = 0; i < axis_zb; ++i)
{
reshaped_out_shape[0] *= ds[i];
}
outputs[0]->set_element_type(inputs[0]->get_element_type());
outputs[0]->set_shape(data_shape);
reshaped_out_shape[1] = m_group;
reshaped_out_shape[2] = ds[axis_zb] / m_group;
runtime::reference::shuffle_channels(arg, out, data_shape, elem_size, m_axis, m_group);
for (size_t i = axis_zb + 1; i < ds.size(); ++i)
{
reshaped_out_shape[3] *= ds[i];
}
// first reshape from data_shape to reshaped_out_shape is skipped since it doesn't affect
// out
// data
Shape transpose_axes_order = {0, 2, 1, 3};
Shape transposed_shape(transpose_axes_order.size());
for (size_t i = 0; i < transpose_axes_order.size(); ++i)
{
transposed_shape[i] = data_shape.at(transpose_axes_order.at(i));
}
auto axis_vector = AxisVector{begin(transpose_axes_order), end(transpose_axes_order)};
runtime::opt_kernel::reshape(
arg, out, reshaped_out_shape, axis_vector, transposed_shape, elem_size);
// last reshape from transposed_shape to data_shape is skipped since it doesn't affect out
// data
return true;
}
bool op::ShuffleChannels::evaluate(const HostTensorVector& outputs,

View File

@ -442,6 +442,7 @@ set(MULTI_TEST_SRC
backend/select.in.cpp
backend/selu.in.cpp
backend/shape_of.in.cpp
backend/shuffle_channels.in.cpp
backend/sigmoid.in.cpp
backend/sign.in.cpp
backend/sin.in.cpp

View File

@ -570,66 +570,6 @@ NGRAPH_TEST(${BACKEND_NAME}, DISABLED_grn_2d_with_bias)
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_simple)
{
const auto data = make_shared<op::Parameter>(element::i32, Shape{1, 15, 2, 2});
auto tested_op = make_shared<op::ShuffleChannels>(data, 1, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data(60);
std::iota(std::begin(input_data), std::end(input_data), 0);
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
Shape{1, 15, 2, 2},
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_negative_axis)
{
// in this test the output is the same as in shuffle_channels_simple but
// the axis value is negative and the C(channels) value is in a different dimension(0) of the
// shape
const auto data = make_shared<op::Parameter>(element::i32, Shape{15, 2, 1, 2});
auto tested_op = make_shared<op::ShuffleChannels>(data, -4, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data(60);
std::iota(std::begin(input_data), std::end(input_data), 0);
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
Shape{15, 2, 1, 2},
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_float)
{
const auto data = make_shared<op::Parameter>(element::f32, Shape{6, 1, 1, 1});
auto tested_op = make_shared<op::ShuffleChannels>(data, 0, 2);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>({0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f});
test_case.add_expected_output<float>(Shape{6, 1, 1, 1}, {0.0f, 3.0f, 1.0f, 4.0f, 2.0f, 5.0f});
test_case.run();
}
// TODO: Issue: 37534
NGRAPH_TEST(${BACKEND_NAME}, DISABLED_squared_difference)
{

View File

@ -0,0 +1,192 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "runtime/backend.hpp"
#include "util/all_close.hpp"
#include "util/all_close_f.hpp"
#include "util/engine/test_engines.hpp"
#include "util/test_case.hpp"
#include "util/test_control.hpp"
#include "util/test_tools.hpp"
using namespace std;
using namespace ngraph;
static string s_manifest = "${MANIFEST}";
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_simple)
{
const auto data = make_shared<op::Parameter>(element::i32, Shape{1, 15, 2, 2});
auto tested_op = make_shared<op::ShuffleChannels>(data, 1, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data(60);
std::iota(std::begin(input_data), std::end(input_data), 0);
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
Shape{1, 15, 2, 2},
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_negative_axis)
{
// In this test the output is the same as in shuffle_channels_simple but
// the axis value is negative and the C(channels) value is in a different dimension(0) of the
// shape
const auto data = make_shared<op::Parameter>(element::i32, Shape{15, 2, 1, 2});
auto tested_op = make_shared<op::ShuffleChannels>(data, -4, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data(60);
std::iota(std::begin(input_data), std::end(input_data), 0);
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
Shape{15, 2, 1, 2},
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_float)
{
const auto data = make_shared<op::Parameter>(element::f32, Shape{6, 1, 1, 1});
auto tested_op = make_shared<op::ShuffleChannels>(data, 0, 2);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>({0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f});
test_case.add_expected_output<float>(Shape{6, 1, 1, 1}, {0.0f, 3.0f, 1.0f, 4.0f, 2.0f, 5.0f});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_1d)
{
Shape data_shape{15};
const auto data = make_shared<op::Parameter>(element::i32, data_shape);
auto tested_op = make_shared<op::ShuffleChannels>(data, 0, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
data_shape,
{0, 3, 6, 9, 12,
1, 4, 7, 10, 13,
2, 5, 8, 11, 14});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_2d)
{
Shape data_shape{15, 4};
const auto data = make_shared<op::Parameter>(element::i32, data_shape);
auto tested_op = make_shared<op::ShuffleChannels>(data, 0, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
data_shape,
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_3d)
{
Shape data_shape{15, 2, 2};
const auto data = make_shared<op::Parameter>(element::i32, data_shape);
auto tested_op = make_shared<op::ShuffleChannels>(data, 0, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
data_shape,
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_5d)
{
Shape data_shape{2, 2, 15, 2, 2};
const auto data = make_shared<op::Parameter>(element::i32, data_shape);
auto tested_op = make_shared<op::ShuffleChannels>(data, 2, 5);
auto function = make_shared<Function>(tested_op, ParameterVector{data});
auto test_case = test::TestCase<TestEngine>(function);
std::vector<int32_t> input_data{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
test_case.add_input(input_data);
test_case.add_expected_output<int32_t>(
data_shape,
{0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59,
0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59,
0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59,
0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55,
8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59});
test_case.run();
}

View File

@ -752,11 +752,6 @@ gemm_broadcast_axes_1_input_C
scale_shift_no_broadcast
scale_shift
# Cannot cast ngraph node ShuffleChannels to CNNLayer!
shuffle_channels_simple
shuffle_channels_negative_axis
shuffle_channels_float
# Detected op not belonging to opset1!
onnx_model_quant_conv_linear
onnx_model_quant_conv_linear_2d

View File

@ -9,12 +9,116 @@
using namespace std;
using namespace ngraph;
TEST(type_prop, shuffle_channels_default_4D)
{
const auto data_input_shape = Shape{3, 9, 4, 5};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data);
EXPECT_EQ(shuffle_channels->get_element_type(), element::f32);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
TEST(type_prop, shuffle_channels_basic_4D)
{
const auto data_input_shape = Shape{3, 9, 4, 5};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 1;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_element_type(), element::f32);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
TEST(type_prop, shuffle_channels_dynamic_4D)
{
const auto data_input_shape = PartialShape{Dimension::dynamic(), Dimension(3, 9), 4, Dimension(4, 15)};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 1;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_element_type(), element::f32);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
TEST(type_prop, shuffle_channels_dynamic_fully)
{
const auto data_input_shape = PartialShape::dynamic();
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 1;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_element_type(), element::f32);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
TEST(type_prop, shuffle_channels_ND_bigger)
{
{
// 5D
const auto data_input_shape = Shape{2, 3, 9, 4, 5};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 2;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
{
// 6D
const auto data_input_shape = Shape{6, 2, 3, 9, 4, 5};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 3;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
}
TEST(type_prop, shuffle_channels_ND_smaller)
{
{
// 3D
const auto data_input_shape = Shape{5, 4, 9};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 2;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
{
// 2D
const auto data_input_shape = Shape{9, 20};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 0;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
{
// 1D
const auto data_input_shape = Shape{9};
const auto data = make_shared<op::Parameter>(element::f32, data_input_shape);
const auto axis = 0;
const auto group = 3;
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, axis, group);
EXPECT_EQ(shuffle_channels->get_output_partial_shape(0), data_input_shape);
}
}
TEST(type_prop, shuffle_channels_axis_validation)
{
try
{
const auto data = make_shared<op::Parameter>(element::f64, Shape{1, 2, 3, 4});
const auto shuffle_channels = make_shared<op::ShuffleChannels>(data, -5, 5);
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, -5, 5);
FAIL() << "ShuffleChannels validation did not work. Op node was created with incorrect "
"params.";
}
@ -30,7 +134,7 @@ TEST(type_prop, shuffle_channels_negative_axis_calculation)
{
const auto data = make_shared<op::Parameter>(element::f64, Shape{1, 2, 3, 4});
const auto shuffle_channels = make_shared<op::ShuffleChannels>(data, -3, 2);
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, -3, 2);
EXPECT_EQ(shuffle_channels->get_zero_based_axis(), 1);
}
@ -40,7 +144,7 @@ TEST(type_prop, shuffle_channels_invalid_input_shape)
try
{
const auto data = make_shared<op::Parameter>(element::f64, Shape{});
const auto shuffle_channels = make_shared<op::ShuffleChannels>(data, 0, 1);
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, 0, 1);
FAIL() << "ShuffleChannels validation did not work. Op node was created with incorrect "
"params.";
}
@ -56,7 +160,7 @@ TEST(type_prop, shuffle_channels_invalid_groups_value)
try
{
const auto data = make_shared<op::Parameter>(element::f64, Shape{1, 2, 3, 15});
const auto shuffle_channels = make_shared<op::ShuffleChannels>(data, -1, 2);
const auto shuffle_channels = make_shared<op::v0::ShuffleChannels>(data, -1, 2);
FAIL() << "ShuffleChannels validation did not work. Op node was created with incorrect "
"params.";
}

View File

@ -5,28 +5,28 @@
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/op/util/attr_types.hpp"
#include "ngraph/opsets/opset1.hpp"
#include "ngraph/opsets/opset3.hpp"
#include "ngraph/opsets/opset4.hpp"
#include "ngraph/opsets/opset5.hpp"
#include "util/visitor.hpp"
using namespace std;
using namespace ngraph;
using ngraph::test::NodeBuilder;
using ngraph::test::ValueMap;
TEST(attributes, shuffle_channels_op)
{
NodeBuilder::get_ops().register_factory<opset1::ShuffleChannels>();
using ShuffleChannels = opset1::ShuffleChannels;
NodeBuilder::get_ops().register_factory<ShuffleChannels>();
auto data = make_shared<op::Parameter>(element::i32, Shape{200});
auto axis = 0;
auto groups = 2;
auto shuffle_channels = make_shared<opset1::ShuffleChannels>(data, axis, groups);
auto shuffle_channels = make_shared<ShuffleChannels>(data, axis, groups);
NodeBuilder builder(shuffle_channels);
auto g_shuffle_channels = as_type_ptr<opset1::ShuffleChannels>(builder.create());
auto g_shuffle_channels = as_type_ptr<ShuffleChannels>(builder.create());
const auto expected_attr_count = 2;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
EXPECT_EQ(g_shuffle_channels->get_axis(), shuffle_channels->get_axis());
EXPECT_EQ(g_shuffle_channels->get_group(), shuffle_channels->get_group());