Transpose ngraph op and reference implementation revision (#5315)

* Extend single layer Transpose tests

* Add more Transpose backend tests

* Update Transpose reference implementation

* Use reference implementation in Transpose evaluate

* Add type prop test with interval dimension

* Move Transpose eval tests to separate file

* Update ie unit test manifest for dynamic cases

* Update evaluate default axes order calculation

* Add Transpose to summarize script

* Add serialize single layer tests

* Add axes order checks in evaluate

* Move ref function default args behaviour to legacy function

* Add new line at EOF

* Remove redundant transpose get_vector helper

* Add set_element_type in transpose evaluate

* Simplify vector convertion

* Add deprecation notice

* Add more tests

* Tests update

* Remove redundant reshape header

* Update unique axes check
This commit is contained in:
Katarzyna Mitrus authored and GitHub committed 2021-04-29 06:58:37 +03:00
1 parent 39b4b65ffd
commit b3de228206
11 files changed
+570 -174

No files matched your search

@@ -0,0 +1,71 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "shared_test_classes/single_layer/transpose.hpp"
using namespace LayerTestsDefinitions;
namespace {
TEST_P(TransposeLayerTest, Serialize) {
Serialize();
}
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16,
InferenceEngine::Precision::I32
};
std::vector<std::vector<size_t>> inputShape2D = {{2, 10}, {10, 2}, {10, 10}};
std::vector<std::vector<size_t>> order2D = {{}, {0, 1}, {1, 0}};
INSTANTIATE_TEST_CASE_P(smoke_Transpose2D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order2D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape2D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
std::vector<std::vector<size_t>> inputShape4D = {{2, 2, 2, 2}};
std::vector<std::vector<size_t>> order4D = {
{}, {0, 1, 2, 3}
};
INSTANTIATE_TEST_CASE_P(smoke_Transpose4D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order4D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
std::vector<std::vector<size_t>> inputShape5D = {{2, 3, 4, 5, 6}};
std::vector<std::vector<size_t>> order5D = {
{}, {0, 1, 2, 3, 4}
};
INSTANTIATE_TEST_CASE_P(smoke_Transpose5D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order5D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
} // namespace
@@ -10,36 +10,64 @@
using namespace LayerTestsDefinitions;
namespace {
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16,
InferenceEngine::Precision::I64,
InferenceEngine::Precision::I32,
InferenceEngine::Precision::I16
};
const std::vector<std::vector<size_t>> inputShapes = {
std::vector<size_t>{1, 3, 100, 100},
std::vector<std::vector<size_t>> inputShape2D = {{2, 10}, {10, 2}, {10, 10}};
std::vector<std::vector<size_t>> order2D = {{}, {0, 1}, {1, 0}};
INSTANTIATE_TEST_CASE_P(smoke_Transpose2D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order2D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape2D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
std::vector<std::vector<size_t>> inputShape4D = {{2, 2, 2, 2}, {1, 10, 2, 3}, {2, 3, 4, 5}};
std::vector<std::vector<size_t>> order4D = {
{}, {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1},
{1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0},
{2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0},
{3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}
};
const std::vector<std::vector<size_t>> inputOrder = {
std::vector<size_t>{0, 3, 2, 1},
std::vector<size_t>{},
INSTANTIATE_TEST_CASE_P(smoke_Transpose4D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order4D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
std::vector<std::vector<size_t>> inputShape5D = {{2, 2, 2, 2, 2}, {1, 10, 2, 3, 4}, {2, 3, 4, 5, 6}};
std::vector<std::vector<size_t>> order5D = {
{}, {0, 1, 2, 3, 4}, {1, 0, 2, 3, 4}, {4, 3, 2, 1, 0}, {0, 2, 3, 4, 1},
{1, 4, 2, 3, 0}, {2, 4, 1, 0, 3}, {3, 0, 2, 1, 4}, {4, 1, 0, 3, 2}
};
const auto params = testing::Combine(
testing::ValuesIn(inputOrder),
testing::ValuesIn(netPrecisions),
testing::Values(InferenceEngine::Precision::UNSPECIFIED),
testing::Values(InferenceEngine::Precision::UNSPECIFIED),
testing::Values(InferenceEngine::Layout::ANY),
testing::Values(InferenceEngine::Layout::ANY),
testing::ValuesIn(inputShapes),
testing::Values(CommonTestUtils::DEVICE_CPU)
);
INSTANTIATE_TEST_CASE_P(
smoke_Transpose,
TransposeLayerTest,
params,
TransposeLayerTest::getTestCaseName
);
INSTANTIATE_TEST_CASE_P(smoke_Transpose5D, TransposeLayerTest,
::testing::Combine(
::testing::ValuesIn(order5D),
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShape5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
TransposeLayerTest::getTestCaseName);
} // namespace
@@ -80,5 +80,6 @@ VERIFIED_OP_REFERENCES = [
'Swish-4',
'Tile-1',
'TopK-1',
'TopK-3'
]
'TopK-3',
'Transpose-1'
]
@@ -7,11 +7,9 @@
#include <cfenv>
#include <cmath>
#include <numeric>
#include <stdexcept>
#include <vector>
#include "ngraph/axis_vector.hpp"
#include "ngraph/coordinate_transform.hpp"
#include "ngraph/runtime/opt_kernel/reshape.hpp"
#include "ngraph/shape.hpp"
namespace ngraph
@@ -20,41 +18,62 @@ namespace ngraph
{
namespace reference
{
template <typename T, typename U>
void transpose(const T* arg, T* out, Shape arg_size, const U* axes_order = nullptr)
void transpose(const char* data,
char* out,
const Shape& data_shape,
size_t element_size,
const int64_t* axes_order,
Shape out_shape)
{
std::vector<U> range_vector;
// To reuse opt_kernel::reshape axes order vector has to be converted to AxisVector
// Negative axes are not supported, it is validated by transpose evaluate method
std::vector<size_t> axis_vector(axes_order, axes_order + data_shape.size());
runtime::opt_kernel::reshape(
data, out, data_shape, axis_vector, out_shape, element_size);
}
// Legacy function template to ensure backward compatibility
// Can be removed after ARM plugin start using evaluate or no template function
template <typename T, typename U>
NGRAPH_DEPRECATED(
"Traspose function with template types is deprecated, use function with char* "
"args.")
void transpose(const T* arg, T* out, Shape arg_shape, const U* axes_order = nullptr)
{
std::vector<std::int64_t> converted_axes_order(arg_shape.size());
if (axes_order == nullptr)
{
range_vector.resize(arg_size.size());
std::iota(range_vector.begin(), range_vector.end(), 0);
std::reverse(range_vector.begin(), range_vector.end());
axes_order = range_vector.data();
std::iota(converted_axes_order.begin(), converted_axes_order.end(), 0);
std::reverse(converted_axes_order.begin(), converted_axes_order.end());
}
std::vector<size_t> input_strides(arg_size.size());
std::vector<size_t> output_strides(arg_size.size());
input_strides.back() = 1;
output_strides.back() = 1;
for (int i = input_strides.size() - 2; i >= 0; i--)
else
{
input_strides[i] = input_strides[i + 1] * arg_size[i + 1];
output_strides[i] = output_strides[i + 1] * arg_size[axes_order[i + 1]];
}
for (int i = 0; i < shape_size(arg_size); ++i)
{
size_t in_position = 0;
size_t new_position = i;
for (int j = 0; j < arg_size.size(); ++j)
for (size_t i = 0; i < converted_axes_order.size(); ++i)
{
in_position +=
(new_position / output_strides[j]) * input_strides[axes_order[j]];
new_position %= output_strides[j];
converted_axes_order[i] = static_cast<std::int64_t>(axes_order[i]);
}
out[i] = arg[in_position];
}
Shape output_shape(arg_shape.size());
std::transform(
converted_axes_order.begin(),
converted_axes_order.end(),
output_shape.begin(),
[&](const int64_t& v) {
NGRAPH_CHECK(v >= 0,
"Negative values for transpose axes order are not supported.");
NGRAPH_CHECK(v < int64_t(arg_shape.size()),
"Transpose axis ",
v,
" is out of shape range.");
return arg_shape[v];
});
transpose(reinterpret_cast<const char*>(arg),
reinterpret_cast<char*>(out),
arg_shape,
sizeof(T),
converted_axes_order.data(),
output_shape);
}
} // namespace reference
} // namespace runtime
+24 -35
View File
@@ -6,7 +6,7 @@
#include "itt.hpp"
#include "ngraph/op/transpose.hpp"
#include "ngraph/runtime/opt_kernel/reshape.hpp"
#include "ngraph/runtime/reference/transpose.hpp"
using namespace std;
using namespace ngraph;
@@ -78,56 +78,45 @@ shared_ptr<Node> op::v1::Transpose::clone_with_new_inputs(const OutputVector& ne
namespace transpose
{
template <element::Type_t ET>
std::vector<int64_t> get_vector(const HostTensorPtr& arg)
{
std::vector<int64_t> rc;
auto p = arg->get_data_ptr<ET>();
for (size_t i = 0; i < shape_size(arg->get_shape()); i++)
{
rc.push_back(p[i]);
}
return rc;
}
bool evaluate_transpose(const HostTensorPtr& arg1,
const HostTensorPtr& arg2,
const HostTensorPtr& out)
{
NGRAPH_CHECK(arg2->get_element_type().is_integral_number(),
"axis element type is not integral data type");
std::vector<int64_t> axis_order = host_tensor_2_vector<int64_t>(arg2);
"Transpose axis element type has to be integral data type.");
std::vector<int64_t> axes_order = host_tensor_2_vector<int64_t>(arg2);
Shape in_shape = arg1->get_shape();
AxisVector in_axis_order(shape_size(arg2->get_shape()));
if (in_axis_order.empty())
if (shape_size(arg2->get_shape()) == 0)
{
size_t rank = in_shape.size();
for (size_t i = 1; i <= rank; ++i)
in_axis_order.emplace_back(rank - i);
axes_order.resize(in_shape.size());
std::iota(axes_order.begin(), axes_order.end(), 0);
std::reverse(axes_order.begin(), axes_order.end());
}
else
{
std::transform(axis_order.begin(),
axis_order.end(),
in_axis_order.begin(),
[&](const int64_t& v) { return (v > 0) ? v : 0; });
std::unordered_set<int64_t> axes_set(axes_order.begin(), axes_order.end());
bool is_unique_order = axes_set.size() == axes_order.size();
NGRAPH_CHECK(is_unique_order, "Transpose axes order values must be unique.");
}
Shape out_shape(in_shape.size());
std::transform(in_axis_order.begin(),
in_axis_order.end(),
out_shape.begin(),
[&](const int64_t& v) { return in_shape[v]; });
std::transform(
axes_order.begin(), axes_order.end(), out_shape.begin(), [&](const int64_t& v) {
NGRAPH_CHECK(v >= 0, "Negative values for transpose axes order are not supported.");
NGRAPH_CHECK(
v < int64_t(in_shape.size()), "Transpose axis ", v, " is out of shape range.");
return in_shape[v];
});
out->set_shape(out_shape);
runtime::opt_kernel::reshape(arg1->get_data_ptr<char>(),
out->get_data_ptr<char>(),
arg1->get_shape(),
in_axis_order,
out->get_shape(),
arg1->get_element_type().size());
out->set_element_type(arg1->get_element_type());
runtime::reference::transpose(arg1->get_data_ptr<char>(),
out->get_data_ptr<char>(),
arg1->get_shape(),
arg1->get_element_type().size(),
axes_order.data(),
out_shape);
return true;
}
} // namespace transpose
+1
View File
@@ -78,6 +78,7 @@ set(SRC
op_eval/split.cpp
op_eval/swish.cpp
op_eval/strided_slice.cpp
op_eval/transpose.cpp
op_eval/variadic_split.cpp
op_is.cpp
opset1.cpp
+121 -1
View File
@@ -7,6 +7,8 @@
#include "ngraph/runtime/tensor.hpp"
#include "runtime/backend.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"
@@ -14,8 +16,9 @@ using namespace std;
using namespace ngraph;
static string s_manifest = "${MANIFEST}";
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
NGRAPH_TEST(${BACKEND_NAME}, transpose)
NGRAPH_TEST(${BACKEND_NAME}, transpose_basic)
{
//
// Create a graph for f(x,perm) = Transpose(x,Convert<i64>(perm)). We'll do the permutation in
@@ -61,3 +64,120 @@ NGRAPH_TEST(${BACKEND_NAME}, transpose)
ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS));
}
}
NGRAPH_TEST(${BACKEND_NAME}, transpose_axes_constant)
{
const auto data_shape = Shape{2, 1, 3, 4};
const auto axes_shape = Shape{4};
const auto output_shape = Shape{3, 4, 2, 1};
auto data_param = make_shared<op::Parameter>(element::f32, data_shape);
auto axes_const = op::Constant::create(element::i64, axes_shape, {2, 3, 0, 1});
auto transpose = make_shared<op::Transpose>(data_param, axes_const);
auto function = make_shared<ngraph::Function>(NodeVector{transpose}, ParameterVector{data_param});
std::vector<float> data(shape_size(data_shape));
std::iota(data.begin(), data.end(), 1);
std::vector<float> expected_result{ 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9,
21, 10, 22, 11, 23, 12, 24};
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>(data_shape, data);
test_case.add_expected_output<float>(output_shape, expected_result);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, transpose_axes_empty_constant)
{
const auto data_shape = Shape{2, 1, 3, 4};
const auto axes_shape = Shape{0};
const auto output_shape = Shape{4, 3, 1, 2};
auto data_param = make_shared<op::Parameter>(element::f32, data_shape);
auto axes_const = op::Constant::create(element::i64, axes_shape, std::vector<int>{});
auto transpose = make_shared<op::Transpose>(data_param, axes_const);
auto function = make_shared<ngraph::Function>(NodeVector{transpose}, ParameterVector{data_param});
std::vector<float> data(shape_size(data_shape));
std::iota(data.begin(), data.end(), 1);
std::vector<float> expected_result{ 1, 13, 5, 17, 9, 21, 2, 14, 6, 18, 10, 22, 3, 15, 7, 19, 11,
23, 4, 16, 8, 20, 12, 24};
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>(data_shape, data);
test_case.add_expected_output<float>(output_shape, expected_result);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, transpose_axes_parameter_static_shapes)
{
const auto data_shape = Shape{2, 1, 3, 4};
const auto axes_shape = Shape{4};
const auto output_shape = Shape{3, 4, 2, 1};
auto data_param = make_shared<op::Parameter>(element::f32, data_shape);
auto axes_param = make_shared<op::Parameter>(element::i32, axes_shape);
auto transpose = make_shared<op::Transpose>(data_param, axes_param);
auto function = make_shared<ngraph::Function>(NodeVector{transpose}, ParameterVector{data_param, axes_param});
std::vector<float> data(shape_size(data_shape));
std::iota(data.begin(), data.end(), 1);
std::vector<int> axes{2, 3, 0, 1};
std::vector<float> expected_result{ 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9,
21, 10, 22, 11, 23, 12, 24};
auto test_case = test::TestCase<TestEngine, test::TestCaseType::DYNAMIC>(function);
test_case.add_input<float>(data_shape, data);
test_case.add_input<int>(axes_shape, axes);
test_case.add_expected_output<float>(output_shape, expected_result);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, transpose_axes_parameter_dynamic_shapes)
{
const auto data_shape = Shape{2, 1, 3, 4};
const auto axes_shape = Shape{4};
const auto output_shape = Shape{3, 4, 2, 1};
auto data_param = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
auto axes_param = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
auto transpose = make_shared<op::Transpose>(data_param, axes_param);
auto function = make_shared<ngraph::Function>(NodeVector{transpose}, ParameterVector{data_param, axes_param});
std::vector<float> data(shape_size(data_shape));
std::iota(data.begin(), data.end(), 1);
std::vector<int> axes{2, 3, 0, 1};
std::vector<float> expected_result{ 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9,
21, 10, 22, 11, 23, 12, 24};
auto test_case = test::TestCase<TestEngine, test::TestCaseType::DYNAMIC>(function);
test_case.add_input<float>(data_shape, data);
test_case.add_input<int>(axes_shape, axes);
test_case.add_expected_output<float>(output_shape, expected_result);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, transpose_int_data_axes_constant)
{
const auto data_shape = Shape{2, 1, 3, 4};
const auto axes_shape = Shape{4};
const auto output_shape = Shape{3, 4, 2, 1};
auto data_param = make_shared<op::Parameter>(element::i32, data_shape);
auto axes_const = op::Constant::create(element::i64, axes_shape, {2, 3, 0, 1});
auto transpose = make_shared<op::Transpose>(data_param, axes_const);
auto function = make_shared<ngraph::Function>(NodeVector{transpose}, ParameterVector{data_param});
std::vector<int32_t> data(shape_size(data_shape));
std::iota(data.begin(), data.end(), 1);
std::vector<int32_t> expected_result{ 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9,
21, 10, 22, 11, 23, 12, 24};
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<int32_t>(data_shape, data);
test_case.add_expected_output<int32_t>(output_shape, expected_result);
test_case.run();
}
-80
View File
@@ -53,7 +53,6 @@
#include "ngraph/op/tan.hpp"
#include "ngraph/op/tanh.hpp"
#include "ngraph/op/topk.hpp"
#include "ngraph/op/transpose.hpp"
#include "ngraph/op/unsqueeze.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/validation_util.hpp"
@@ -1296,85 +1295,6 @@ TEST(eval, evaluate_dynamic_concat)
ASSERT_EQ(cval, out);
}
template <element::Type_t T>
void test_eval(shared_ptr<Function> fun,
vector<vector<float>>& inputs,
vector<Shape>& x_shapes,
vector<Shape>& result_shapes,
vector<vector<float>>& results)
{
using IN_T = typename element_type_traits<T>::value_type;
std::vector<std::vector<IN_T>> perms{{0, 1}, {1, 0}, {2, 1, 0}};
for (size_t i = 0; i < x_shapes.size(); i++)
{
auto result_tensor = make_shared<HostTensor>();
ASSERT_TRUE(fun->evaluate({result_tensor},
{make_host_tensor<element::Type_t::f32>(x_shapes[i], inputs[i]),
make_host_tensor<T>(Shape{perms[i].size()}, perms[i])}));
ASSERT_EQ(result_tensor->get_shape(), result_shapes[i]);
auto actual_results = read_vector<float>(result_tensor);
ASSERT_EQ(actual_results, results[i]);
}
}
TEST(eval, eval_transpose)
{
auto x = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
vector<shared_ptr<op::Parameter>> axes;
axes.push_back(make_shared<op::Parameter>(element::i8, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i16, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i64, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u8, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u16, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u32, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u64, PartialShape{Dimension::dynamic()}));
std::vector<Shape> x_shapes{Shape{2, 3}, Shape{2, 3}, Shape{2, 2, 3}};
std::vector<std::vector<float>> inputs{
{1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}};
std::vector<Shape> result_shapes{Shape{2, 3}, Shape{3, 2}, {3, 2, 2}};
std::vector<std::vector<float>> results{
{1, 2, 3, 4, 5, 6}, {1, 4, 2, 5, 3, 6}, {1, 7, 4, 10, 2, 8, 5, 11, 3, 9, 6, 12}};
for (auto& axis : axes)
{
auto x_transpose = make_shared<op::v1::Transpose>(x, axis);
auto fun = make_shared<Function>(NodeVector{x_transpose}, ParameterVector{x, axis});
switch (axis->get_element_type())
{
case element::Type_t::i8:
test_eval<element::Type_t::i8>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::i16:
test_eval<element::Type_t::i16>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::i32:
test_eval<element::Type_t::i32>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::i64:
test_eval<element::Type_t::i64>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::u8:
test_eval<element::Type_t::u8>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::u16:
test_eval<element::Type_t::u16>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::u32:
test_eval<element::Type_t::u32>(fun, inputs, x_shapes, result_shapes, results);
break;
case element::Type_t::u64:
test_eval<element::Type_t::u64>(fun, inputs, x_shapes, result_shapes, results);
break;
default: NGRAPH_CHECK(false, "Invalid type"); break;
}
}
}
TEST(eval, max_pool_v1_dynamic)
{
+236
View File
@@ -0,0 +1,236 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "ngraph/op/transpose.hpp"
#include "ngraph/runtime/reference/transpose.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/validation_util.hpp"
#include "runtime/backend.hpp"
#include "util/test_tools.hpp"
#include "util/all_close_f.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ngraph;
template <element::Type_t IN_ET, element::Type_t AXIS_ET>
void test_tranpose_eval(shared_ptr<Function> fun)
{
using T = typename element_type_traits<IN_ET>::value_type;
using T_AXIS = typename element_type_traits<AXIS_ET>::value_type;
const std::vector<std::vector<T>> input_data{
{1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}};
std::vector<Shape> data_shapes{{2, 3}, {2, 3}, {2, 3}, {2, 3, 1}, {2, 2, 3}};
const std::vector<std::vector<T_AXIS>> axes_order{{0, 1}, {1, 0}, {}, {1, 2, 0}, {2, 1, 0}};
std::vector<std::vector<T>> expected_results{
{1, 2, 3, 4, 5, 6}, {1, 4, 2, 5, 3, 6}, {1, 4, 2, 5, 3, 6}, {1, 4, 2, 5, 3, 6}, {1, 7, 4, 10, 2, 8, 5, 11, 3, 9, 6, 12}};
std::vector<Shape> expected_result_shapes{{2, 3}, {3, 2}, {3, 2}, {3, 1, 2}, {3, 2, 2}};
for (size_t i = 0; i < data_shapes.size(); i++)
{
auto result_tensor = make_shared<HostTensor>(element::dynamic, PartialShape::dynamic());
ASSERT_TRUE(fun->evaluate({result_tensor},
{make_host_tensor<IN_ET>(data_shapes[i], input_data[i]),
make_host_tensor<AXIS_ET>(Shape{axes_order[i].size()}, axes_order[i])}));
auto actual_results = read_vector<T>(result_tensor);
ASSERT_EQ(actual_results, expected_results[i]);
{ // Temporary test for legacy reference function template
NGRAPH_SUPPRESS_DEPRECATED_START
std::vector<T> ref_results(input_data[i].size());
runtime::reference::transpose<T, T_AXIS>(input_data[i].data(), ref_results.data(), data_shapes[i], axes_order[i].data());
ASSERT_EQ(ref_results, expected_results[i]);
NGRAPH_SUPPRESS_DEPRECATED_END
}
}
}
TEST(op_eval, eval_transpose)
{
vector<shared_ptr<op::Parameter>> axes;
axes.push_back(make_shared<op::Parameter>(element::i8, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i16, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::i64, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u8, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u16, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u32, PartialShape{Dimension::dynamic()}));
axes.push_back(make_shared<op::Parameter>(element::u64, PartialShape{Dimension::dynamic()}));
for (auto& axis : axes)
{
const auto input_integral = make_shared<op::Parameter>(element::i16, PartialShape::dynamic());
const auto transpose_integral = make_shared<op::v1::Transpose>(input_integral, axis);
const auto function_integral = make_shared<Function>(OutputVector{transpose_integral}, ParameterVector{input_integral, axis});
const auto input_floating = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
const auto transpose_floating = make_shared<op::v1::Transpose>(input_floating, axis);
const auto function_floating = make_shared<Function>(OutputVector{transpose_floating}, ParameterVector{input_floating, axis});
switch (axis->get_element_type())
{
case element::Type_t::i8:
test_tranpose_eval<element::Type_t::i16, element::Type_t::i8>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::i8>(function_floating);
break;
case element::Type_t::i16:
test_tranpose_eval<element::Type_t::i16, element::Type_t::i16>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::i16>(function_floating);
break;
case element::Type_t::i32:
test_tranpose_eval<element::Type_t::i16, element::Type_t::i32>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::i32>(function_floating);
break;
case element::Type_t::i64:
test_tranpose_eval<element::Type_t::i16, element::Type_t::i64>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::i64>(function_floating);
break;
case element::Type_t::u8:
test_tranpose_eval<element::Type_t::i16, element::Type_t::u8>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::u8>(function_floating);
break;
case element::Type_t::u16:
test_tranpose_eval<element::Type_t::i16, element::Type_t::u16>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::u16>(function_floating);
break;
case element::Type_t::u32:
test_tranpose_eval<element::Type_t::i16, element::Type_t::u32>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::u32>(function_floating);
break;
case element::Type_t::u64:
test_tranpose_eval<element::Type_t::i16, element::Type_t::u64>(function_integral);
test_tranpose_eval<element::Type_t::f32, element::Type_t::u64>(function_floating);
break;
default: NGRAPH_CHECK(false, "Invalid type"); break;
}
}
}
TEST(op_eval, eval_axes_transpose)
{
auto data_param = make_shared<op::Parameter>(element::i32, PartialShape::dynamic());
auto axes_order = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
auto x_transpose = make_shared<op::v1::Transpose>(data_param, axes_order);
auto function = make_shared<Function>(NodeVector{x_transpose}, ParameterVector{data_param, axes_order});
const std::vector<int32_t> data{1, 2, 3, 4, 5, 6};
std::vector<size_t> data_shape{2, 3, 1};
const std::vector<int32_t> perm{1, 2, 0};
std::vector<int32_t> expected_result{1, 4, 2, 5, 3, 6};
auto result_tensor = make_shared<HostTensor>();
function->evaluate({result_tensor},
{make_host_tensor<element::Type_t::i32>(data_shape, data),
make_host_tensor<element::Type_t::i32>(Shape{perm.size()}, perm)});
auto actual_results = read_vector<int32_t>(result_tensor);
ASSERT_EQ(actual_results, expected_result);
}
TEST(op_eval, eval_duplicated_axes_transpose)
{
auto data_param = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
auto axes_order = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
auto x_transpose = make_shared<op::v1::Transpose>(data_param, axes_order);
auto function = make_shared<Function>(NodeVector{x_transpose}, ParameterVector{data_param, axes_order});
const std::vector<float> data{1, 2, 3, 4, 5, 6};
std::vector<size_t> data_shape{2, 3, 1};
const std::vector<int32_t> perm{2, 1, 2};
try
{
auto result_tensor = make_shared<HostTensor>();
function->evaluate({result_tensor},
{make_host_tensor<element::Type_t::f32>(data_shape, data),
make_host_tensor<element::Type_t::i32>(Shape{perm.size()}, perm)});
FAIL() << "Duplicated axes values not detected";
}
catch (const ngraph_error& error)
{
EXPECT_HAS_SUBSTRING(error.what(), std::string("must be unique"));
}
catch (...)
{
FAIL() << "Failed for unexpected reason";
}
}
TEST(op_eval, eval_out_of_shape_axes_transpose)
{
auto data_param = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
auto axes_order = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
auto x_transpose = make_shared<op::v1::Transpose>(data_param, axes_order);
auto function = make_shared<Function>(NodeVector{x_transpose}, ParameterVector{data_param, axes_order});
const std::vector<float> data{1, 2, 3, 4, 5, 6};
std::vector<size_t> data_shape{2, 3, 1};
const std::vector<int32_t> perm{0, 1, 3};
try
{
auto result_tensor = make_shared<HostTensor>();
function->evaluate({result_tensor},
{make_host_tensor<element::Type_t::f32>(data_shape, data),
make_host_tensor<element::Type_t::i32>(Shape{perm.size()}, perm)});
FAIL() << "Out of shape axes not detected";
}
catch (const ngraph_error& error)
{
EXPECT_HAS_SUBSTRING(error.what(), std::string("out of shape"));
}
catch (...)
{
FAIL() << "Failed for unexpected reason";
}
}
TEST(op_eval, eval_negative_axes_transpose)
{
auto data_param = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
auto axes_order = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
auto x_transpose = make_shared<op::v1::Transpose>(data_param, axes_order);
auto function = make_shared<Function>(NodeVector{x_transpose}, ParameterVector{data_param, axes_order});
const std::vector<float> data{1, 2, 3, 4, 5, 6};
std::vector<size_t> data_shape{2, 3, 1};
const std::vector<int32_t> perm{-1, -2, -3};
std::vector<float> expected_result{1, 4, 2, 5, 3, 6};
try
{
auto result_tensor = make_shared<HostTensor>();
function->evaluate({result_tensor},
{make_host_tensor<element::Type_t::f32>(data_shape, data),
make_host_tensor<element::Type_t::i32>(Shape{perm.size()}, perm)});
auto actual_results = read_vector<float>(result_tensor);
ASSERT_EQ(actual_results, expected_result);
FAIL() << "Negative axes for Transpose were not supported before.";
}
catch (const ngraph_error& error)
{
EXPECT_HAS_SUBSTRING(error.what(), std::string("not supported"));
}
catch (...)
{
FAIL() << "Failed for unexpected reason";
}
}
+2 -2
View File
@@ -866,8 +866,6 @@ broadcast_algo_matrix_stride_3
# Cannot find blob with name: Parameter_1
dyn_group_convolution_backprop_data
dynamic_transpose
transpose
# todo: check negative indices implementation
gather_2d_negative_and_positive_indices_axis_0_2d_input
@@ -1151,6 +1149,8 @@ IE_CPU.onnx_model_reduce_sum_13_axes_as_input
IE_CPU.onnx_model_reduce_sum_13_input_dynamic
IE_CPU.onnx_model_reduce_sum_13_axes_empty_dynamic_rank_input
IE_CPU.onnx_model_reduce_sum_dynamic_rank_input
IE_CPU.transpose_axes_parameter_static_shapes
IE_CPU.transpose_axes_parameter_dynamic_shapes
# Axes has zero dimension which is not allowed
IE_CPU.onnx_model_reduce_sum_13_axes_as_0_dim_input
+11
View File
@@ -122,6 +122,17 @@ TEST(type_prop, transpose_arg_rank_static_dynamic_input_order_rank_dynamic_ok)
EXPECT_TRUE(r->get_output_partial_shape(0).same_scheme(PartialShape::dynamic(4)));
}
TEST(type_prop, transpose_dynamic_interval_input_data)
{
auto arg = make_shared<op::Parameter>(element::f32, PartialShape{Dimension(4, 6), Dimension(2, 3), 8});
auto input_order = make_shared<op::Parameter>(element::i64, Shape{3});
auto r = make_shared<op::Transpose>(arg, input_order);
EXPECT_EQ(r->get_output_element_type(0), element::f32);
EXPECT_TRUE(r->get_output_partial_shape(0).same_scheme(PartialShape::dynamic(3)));
}
TEST(type_prop, transpose_arg_static_input_order_static_input_order_not_vector)
{
auto arg = make_shared<op::Parameter>(element::f32, PartialShape{2, 4, 6, 8});